Any ideas on how to remove the stamp from this bill prior to OCR processing?
Here is one way to do that in Python/OpenCV.
Read input
Threshold on yellow
Dilate to fill out rectangle
Get largest contour
Draw a white filled contour on the input image
Save the results
Input:
import cv2
import numpy as np
# read image
img = cv2.imread('form_with_label.jpg')
# threshold on yellow
lower=(0,200,200)
upper=(100,255,255)
thresh = cv2.inRange(img, lower, upper)
# apply dilate morphology
kernel = np.ones((9,9), np.uint8)
mask = cv2.morphologyEx(thresh, cv2.MORPH_DILATE, kernel)
# get largest contour
contours = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
big_contour = max(contours, key=cv2.contourArea)
x,y,w,h = cv2.boundingRect(big_contour)
# draw filled white contour on input
result = img.copy()
cv2.drawContours(result,[big_contour],0,(255,255,255),-1)
# save cropped image
cv2.imwrite('form_with_label_thresh.png',thresh)
cv2.imwrite('form_with_label_mask.png',mask)
cv2.imwrite('form_with_label_removed.png',result)
# show the images
cv2.imshow("THRESH", thresh)
cv2.imshow("MASK", mask)
cv2.imshow("RESULT", result)
cv2.waitKey(0)
cv2.destroyAllWindows()
Thresholded Image:
Morphology Dilated Image:
Result:
Related
How can I remove a black color rectangle from an image like this below,
I want to detect that huge black color rectangle box and change it to white color? Its my next pre-processing stage.
Any help is appreciated
Here is one way to do that in Python/OpenCV.
Read the input
Convert to gray
Threshold to binary and invert
Get the largest external contour
Get the bounding box for that contour
Fill that region of the input with white
Save the result
Input:
import cv2
import numpy as np
# read image
img = cv2.imread('black_rectangle.png')
ht, wd = img.shape[:2]
print(img.shape)
# convert to grayscale
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# threshold
thresh = cv2.threshold(gray,128,255,cv2.THRESH_BINARY)[1]
# invert
thresh = 255 - thresh
# get largest external contour
contours = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
big_contour = max(contours, key=cv2.contourArea)
# get bounding box of largest contour
x,y,w,h = cv2.boundingRect(big_contour)
# make that region white in the input image
result = img.copy()
result[y:y+h, x:x+w] = (255,255,255)
# show thresh and result
cv2.imshow("result", result)
cv2.waitKey(0)
cv2.destroyAllWindows()
# save resulting image
cv2.imwrite('black_rectangle_2white.png',result)
Result:
I need to detect only the black rectangle that appears there, but for some reason my code does not detect it but it does detect many other things.
import cv2
img=cv2.imread('vision.png') #read image
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
Blur=cv2.GaussianBlur(gray,(5,5),1) #apply blur to roi
Canny=cv2.Canny(Blur,10,50) #apply canny to roi
#Find my contours
contours =cv2.findContours(Canny,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)[0]
cntrRect = []
for i in contours:
epsilon = 0.05*cv2.arcLength(i,True)
approx = cv2.approxPolyDP(i,epsilon,True)
if len(approx) == 4:
cv2.drawContours(img,cntrRect,-1,(0,255,0),2)
cv2.imshow('Image Rect ONLY',img)
cntrRect.append(approx)
cv2.waitKey(0)
cv2.destroyAllWindows()
How do I detect only the black rectangle that appears in the image
But this code detect more rectangles and I don't want whis, but I only want detect the black countour rectangle
Here is one way to do that in Python/OpenCV.
Threshold the image. Then use morphology to fill out the rectangle. Then get the largest contour and draw on the input.
Input:
import cv2
import numpy as np
# load image
img = cv2.imread("black_rectangle_outline.png")
# convert to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# threshold
thresh = cv2.threshold(gray, 30, 255, cv2.THRESH_BINARY)[1]
# apply close morphology
kernel = np.ones((111,111), np.uint8)
morph = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
# invert so rectangle is white
morph = 255 - morph
# get largest contour and draw on copy of input
result = img.copy()
contours = cv2.findContours(morph, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
big_contour = max(contours, key=cv2.contourArea)
cv2.drawContours(result, [big_contour], 0, (255,255,255), 1)
# write result to disk
cv2.imwrite("black_rectangle_outline_thresh.png", thresh)
cv2.imwrite("black_rectangle_outline_morph.png", morph)
cv2.imwrite("black_rectangle_outline_result.png", result)
# display results
cv2.imshow("THRESH", thresh)
cv2.imshow("MORPH", morph)
cv2.imshow("RESULT", result)
cv2.waitKey(0)
cv2.destroyAllWindows()
Threshold Image:
Morphology Image:
Result:
I am trying to remove the backgrounds of a set of tea leaf images.
I tried these codes in StackOverflow itself but they don't work with my images.
How to remove the background from a picture in OpenCV python
how to remove background of images in python
How can I delete the whole background around the leaf and keep only the single leaf.
This is a one-sample of the image set.
# Read image
img = cv2.imread('leaf.jpg')
# Convert to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Find edges
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU + cv2.THRESH_BINARY)[1]
# Find contour
contours = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
# Sort contour by area
contours = sorted(contours, key=cv2.contourArea, reverse=True)
# Find the bounding box and crop image to get ROI
for cnt in contours:
x,y,w,h = cv2.boundingRect(cnt)
ROI = img[y:y+h, x:x+w]
break
# Define lower and upper threshold for background
lower = np.array([128, 128, 128])
upper = np.array([255, 255, 255])
# Create mask to only select black
thresh = cv2.inRange(ROI, lower, upper)
# Apply morphology
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
morph = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
# invert morph image to get background as black
mask = 255 - morph
# apply mask to image
result = cv2.bitwise_and(ROI, ROI, mask=mask)
plt.imshow(result)
I've got a shape detection with OpenCV in Python going on; bolts and nuts. I take a picture, make it binary, and detect edges. Now the white area is always grainy because of dust and grime. My detection uses the largest areas as parts, which works great. But how can I delete the thousands of objects caused by dust?
In short, I want to reduce the array of shapes to only the biggest ones for further processing.
Here is one way to do that as per my comment above using Python/OpenCV.
From your binary image get the contours. Then select the largest contour. Then draw a white filled contour on a black background image the same size as your input as a mask. Then use numpy to blacken everything in your image that is black in your mask.
Input:
import cv2
import numpy as np
# load image
img = cv2.imread("coke_bottle2.png")
hh, ww = img.shape[:2]
# convert to gray
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# threshold using inRange
thresh = cv2.threshold(gray, 50, 255, cv2.THRESH_BINARY)[1]
# apply morphology closing to fill black holes and smooth outline
# could use opening to remove white spots, but we will use contours
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (25,25))
thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
# get the largest contour
contours = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
big_contour = max(contours, key=cv2.contourArea)
# draw largest contour as white filled on black background as mask
mask = np.zeros((hh,ww), dtype=np.uint8)
cv2.drawContours(mask, [big_contour], 0, 255, -1)
# use mask to black all but largest contour
result = img.copy()
result[mask==0] = (0,0,0)
# write result to disk
cv2.imwrite("coke_bottle2_threshold.png", thresh)
cv2.imwrite("coke_bottle2_mask.png", mask)
cv2.imwrite("coke_bottle2_background_removed.jpg", result)
# display it
cv2.imshow("thresh", thresh)
cv2.imshow("mask", mask)
cv2.imshow("result", result)
cv2.waitKey(0)
cv2.destroyAllWindows()
Threshold Image (contains small extraneous white regions):
Mask Image (only the largest filled contour):
Result:
Hello, for a personal project I need to crop out extract this underwater gate from an image, and leave out anything other than the gate. The image is colored here but I can assume that the image of the gate I receive will only be lined, with the gate being white lines and the background being black. Could anyone give me any advice about how to go about this solution? I'm a novice when it comes to OpenCV so I'm a bit lost.
Here's the main idea
Gaussian blur image and extract blue channel
Threshold image with cv2.threshold()
Erode to remove black lines and isolate gate with cv2.erode()
Find contours and filter for gate contour using cv2.findContours() and cv2.contourArea()
Create a mask and dilate image using cv2.dilate()
Crop gate using cv2.bitwise_and()
import cv2
import numpy as np
# Load in image and create copy
image = cv2.imread('1.png')
original = image.copy()
# Gaussian blur and extract blue channel
blur = cv2.GaussianBlur(image, (3,3), 0)
blue = blur[:,:,0]
# Threshold image and erode to isolate gate contour
thresh = cv2.threshold(blue,135, 255, cv2.THRESH_BINARY_INV)[1]
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
erode = cv2.erode(thresh, kernel, iterations=4)
# Create a mask and find contours
mask = np.zeros(original.shape, dtype=np.uint8)
cnts = cv2.findContours(erode, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
# Filter for gate contour using area and draw onto mask
for c in cnts:
area = cv2.contourArea(c)
if area > 6000:
cv2.drawContours(mask, [c], -1, (255,255,255), 2)
# Dilate to restore contour and mask it with original image
dilate = cv2.dilate(mask, kernel, iterations=7)
result = cv2.bitwise_and(original, dilate)
cv2.imshow('thresh', thresh)
cv2.imshow('erode', erode)
cv2.imshow('mask', mask)
cv2.imshow('dilate', dilate)
cv2.imshow('result', result)
cv2.waitKey()