问题
My code is detecting another box when there is no letter!
# Create sort_contours() function to grab the contour of each digit from left to right
def sort_contours(cnts,reverse = False):
i = 0
boundingBoxes = [cv2.boundingRect(c) for c in cnts]
(cnts, boundingBoxes) = zip(*sorted(zip(cnts, boundingBoxes),
key=lambda b: b[1][i], reverse=reverse))
return cnts
cont, _ = cv2.findContours(thre_mor, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# creat a copy version "test_roi" of plat_image to draw bounding box
test_roi = plate_image.copy()
# Initialize a list which will be used to append charater image
crop_characters = []
# define standard width and height of character
digit_w, digit_h = 40, 80 #40,80
for c in sort_contours(cont):
(x, y, w, h) = cv2.boundingRect(c)
ratio = h/w
if 1<=ratio<=2.5: # Only select contour with defined ratio
if h/plate_image.shape[0]>=0.4: # Select contour which has the height larger than 50% of the plate
# Draw bounding box arroung digit number
cv2.rectangle(test_roi, (x, y), (x + w, y + h), (0, 255,0), 2)
# Sperate number and gibe prediction
curr_num = thre_mor[y:y+h,x:x+w]
curr_num = cv2.resize(curr_num, dsize=(digit_w, digit_h))
_, curr_num = cv2.threshold(curr_num, 220, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
crop_characters.append(curr_num)
print("Detect {} letters...".format(len(crop_characters)))
fig = plt.figure(figsize=(10,6))
plt.axis(False)
plt.imshow(test_roi)
The image it is this:
With this binary image:
This is the result:
Do you see the last 5? The goal it is avoid this.
Why this is happening?
The way I procces the image it is:
gray = cv2.cvtColor(plate_image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray,(7,7),0)
binary = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
kernel3 = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
thre_mor = cv2.morphologyEx(binary, cv2.MORPH_DILATE, kernel3)
- Grayscale
- Blur
- Binarization
- Segmentation
I think it's because of the contour, how could I remove the contour better?
回答1:
Using morphological reconstruction, you can easily remove elements that touch the edges from a binary image. This is similar to the imclearborder() function from Matlab / Octave.
import cv2
import numpy as np
img = cv2.imread('CpO0b.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)[1]
marker=thresh.copy()
marker[1:-1,1:-1]=0
kernel = np.ones((3,3),np.uint8)
while True:
tmp=marker.copy()
marker=cv2.dilate(marker, kernel)
marker=cv2.min(thresh, marker)
difference = cv2.subtract(marker, tmp)
if cv2.countNonZero(difference) == 0:
break
mask=cv2.bitwise_not(marker)
out=cv2.bitwise_and(thresh, mask)
cv2.imwrite('out.png', out)
cv2.imshow('result', out )
回答2:
When segmenting characters by binarisation, finding alien blobs is the rule rather than the exception.
You can get rid of many of them by simple size/area/aspect ratio… criteria. In the given case, you can use the fact that they go alongside the edges of the image, or that they are shifted up wrt the other characters.
Anyway, there can be blobs that resist to any form of by-feature rejection just for the reason that they look like characters.
The next level of filtering is recognition proper, which will tell you if the blob has the shape of a known character (this is font dependent).
Last but not least, you can even have blobs taking the appearance of legit characters and being in-line with the string. Then there is nothing you can do.
来源:https://stackoverflow.com/questions/62114137/trying-to-segment-characters-using-opencv-contour-problem