尝试使用OpenCV分割字符-轮廓问题

时间:2020-05-31 09:28:10

标签: python python-3.x opencv image-processing

我的代码在没有字母的情况下正在检测另一个盒子!

# 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)

图像是这样的:

enter image description here

使用此二进制图像:

enter image description here

这是结果:

enter image description here

您看到最后5个吗?目的是避免这种情况。

为什么会这样?

我处理图像的方式是:

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. 灰度
  2. 模糊
  3. 二值化
  4. 细分

我认为是因为轮廓,如何才能更好地去除轮廓?

2 个答案:

答案 0 :(得分:1)

通过二值化对字符进行分段时,找到外来斑点是规则而不是例外。

您可以通过简单的大小/面积/长宽比...标准来摆脱许多此类问题。在给定的情况下,您可以使用以下事实:它们与图像边缘并排,或者与其他字符一起向上移。

无论如何,可能有一些斑点会因为它们看起来像字符而抵制任何形式的特征拒绝。

下一步的过滤是正确识别的,它将告诉您斑点是否具有已知字符的形状(这取决于字体)。

最后但并非最不重要的一点是,您甚至可以使Blob看起来像合法字符并与字符串一致。然后,您无能为力。

答案 1 :(得分:1)

使用形态重建,您可以轻松地从二进制图像中删除接触边缘的元素。这类似于Matlab / Octave中的imclearborder()函数。

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 )

enter image description here