Trying to segment characters using opencv - Contour problem

瘦欲@ 提交于 2020-12-15 05:26:36

问题


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)
  1. Grayscale
  2. Blur
  3. Binarization
  4. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!