【问题标题】:opencv contours and or boundingrect of number image not detected correctly未正确检测到数字图像的opencv轮廓和/或boundingrect
【发布时间】:2018-10-24 21:06:38
【问题描述】:

我正在尝试分割下图的数字和/或字符,然后使用 ocr 将每个单独的 num/char 转换为文本:

这是使用的代码(在python中):

new, contours, hierarchy = cv2.findContours(gray, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

digitCnts = []

final = gray.copy()    

# loop over the digit area candidates
for c in contours:

    (x, y, w, h) = cv2.boundingRect(c)
    # if the contour is sufficiently large, it must be a digit
    if (w >= 20 and w <= 290) and h >= (gray.shape[0]>>1)-15:
        x1 = x+w
        y1 = y+h
        digitCnts.append([x,x1,y,y1])
        #print(x,x1,y,y1)
        # Drawing the selected contour on the original image
        cv2.rectangle(final,(x,y),(x1,y1),(0, 255, 0), 2)

plt.imshow(final, cmap=cm.gray, vmin=0, vmax=255)

我得到以下输出:

您会看到除了中间的 2 之外,所有的都被正确检测到,只有顶部有边界框,而不是整个数字周围。我无法弄清楚为什么只有这个没有正确检测到,尤其是它与其他的相似。知道如何解决这个问题吗?

【问题讨论】:

  • 尝试绘制轮廓,看看它提取了什么。
  • 我画了包围矩形。我画轮廓而不是?我试试看
  • 图像应该是二值的,而不是灰色的,如果是灰色最好将其转换为具有一定阈值的黑白。
  • 嗯,它是二进制的。实际上,当我在尝试检测之前将图像延迟为二进制转换时,我解决了这个问题。图像最初在转换后旋转。也许,二进制转换后的旋转对数字检测的影响比以前更大。也许我需要总是将二进制转换延迟到最后。

标签: opencv bounding-box opencv-contour


【解决方案1】:

据我所知,大多数二进制图像的 OpenCV 方法都运行white objects on the black background

来源:

阈值 INV 和 morph-open:

按高度过滤并在src上绘制:


#!/usr/bin/python3
# 2018/10/25 08:30 
import cv2
import numpy as np

# (1) src 
img = cv2.imread( "car.png")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# (2) threshold-inv and morph-open 
th, threshed = cv2.threshold(gray, 100, 255, cv2.THRESH_OTSU|cv2.THRESH_BINARY_INV)
morphed = cv2.morphologyEx(threshed, cv2.MORPH_OPEN, np.ones((2,2)))
# (3) find and filter contours, then draw on src 
cnts = cv2.findContours(morphed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2]

nh, nw = img.shape[:2]
for cnt in cnts:
    x,y,w,h = bbox = cv2.boundingRect(cnt)
    if h < 0.3 * nh:
        continue
    cv2.rectangle(img, (x,y), (x+w, y+h), (255, 0, 255), 1, cv2.LINE_AA)

cv2.imwrite("dst.png", img)
cv2.imwrite("morphed.png", morphed)

【讨论】:

    【解决方案2】:

    您的图像有点嘈杂,因此将其二值化就可以了。

    cv2.threshold(gray,  127, 255, cv2.THRESH_BINARY, gray)
    new, contours, hierarchy = cv2.findContours(gray, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)
    
    # cv2.drawContours(gray, contours, -1, 127, 5)
    digitCnts = []
    
    final = gray.copy()
    
    # loop over the digit area candidates
    for c in contours:
        (x, y, w, h) = cv2.boundingRect(c)
        # if the contour is sufficiently large, it must be a digit
        if (w >= 20 and w <= 290) and h >= (gray.shape[0]>>1)-15:
            x1 = x+w
            y1 = y+h
            digitCnts.append([x,x1,y,y1])
            #print(x,x1,y,y1)
            # Drawing the selected contour on the original image
            cv2.rectangle(final,(x,y),(x1,y1),(0, 255, 0), 2)
    

    【讨论】:

    • 是的,有点吵。虽然我试图先消除噪音,但没有奏效。我已经以不同的方式解决了。不过,谢谢。
    • @mj1261829 做得好。如果您自己的答案以更好的方式解决了您的问题 - 您是 encouraged 将解决方案添加为答案并将其标记为已接受的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-24
    • 1970-01-01
    • 1970-01-01
    • 2019-12-06
    • 2019-07-08
    相关资源
    最近更新 更多