【问题标题】:Detecting contours separated by blank pixel检测由空白像素分隔的轮廓
【发布时间】:2018-07-23 15:06:59
【问题描述】:

我目前正在尝试使用 python 中的图像中的字符的 opencv 检测轮廓,并在此特定轮廓周围绘制一个边界矩形。

问题是我有一个字符“

这里是字符:

(在检测轮廓之前,我正在应用二进制阈值)

有没有办法指示opencv连接两个彼此太近的轮廓?

干杯, 阿斯特鲁斯

【问题讨论】:

  • 在找到轮廓之前应用一些形态学操作。扩张后腐蚀可以解决您的问题。
  • 只是为了补充 Sunreef 的答案,如果您使用 Canny 来查找边缘,则有一个参数可以调整它如何连接附近的边缘
  • @Sunreef 这并不容易,因为相应的图像是 72 个对齐字符的表示。确实,我需要找到所有 72 个字符的轮廓,而您的变换可能会伤害附近的字符(也许其他字符轮廓就可以了)。
  • @MartinBeckett 我没有使用 Canny,我目前正在使用 opencv findcontours 方法,然后使用 boundingRect 在角色周围绘制一个矩形。您认为我可以使用 Canny 替换 findcontours 并在 之后使用 boundingRect 吗?
  • @Astrus:重要的是要了解,世界上没有算法可以猜测附近的两个部分是来自一个损坏的字符还是两个不同的字符。因此,如果您的角色彼此接近,那么您所要求的几乎是无望的。但是你应该显示整个图像。

标签: python opencv


【解决方案1】:

代码可能会进行很多优化(大麦从编程开始)并且速度非常慢,但它可能对您的情况有所帮助或只是给您一个想法。我所做的是找到所有轮廓并将它们绘制在空白蒙版上。然后您可以使用cv2.findNonZero 确定轮廓的所有非黑色(零)像素。之后,您可以搜索所有相似点,例如具有相同 x 坐标和略有不同 y 坐标的点(在示例图片中 +-2) - 这代表您的空白区域。之后,您可以简单地用cv2.line() 绘制线条,它将填充空白区域。然后只需再次搜索轮廓并绘制边界框。希望能帮助到你。干杯!

示例代码:

import cv2
import numpy as np

img  = cv2.imread('seperated_example.png')
gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(gray_image,170,255,cv2.THRESH_BINARY_INV)
_, contours, _ = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
mask = np.zeros(gray_image.shape,np.uint8)
cv2.drawContours(mask, contours, -1, 255, -1)
pixelpoints = cv2.findNonZero(mask)

for i in pixelpoints:
    for j in pixelpoints:
        if int(i[:,0]) == int(j[:,0]) and int(i[:,1]) == int(j[:,1]):
            pass
        else:
            if int(i[:,0]) == int(j[:,0]) and int(j[:,1])-2 <= int(i[:,1]) <= int(j[:,1])+2:
                cv2.line(img, (int(i[:,0]), int(i[:,1])), (int(j[:,0]), int(j[:,1])), (0,0,0), 1)

cv2.imwrite('seperated_result.png', img)
cv2.imshow('img', img)

img = cv2.imread('seperated_result.png')
gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(gray_image,170,255,cv2.THRESH_BINARY_INV)
_, contours, _ = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

for i in contours:
    cnt = i
    x,y,w,h = cv2.boundingRect(cnt)
    cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),1)

cv2.imwrite('seperated_result2.png', img)
cv2.imshow('img2', img)

输入图像(黑色文本,用白线将其分成两半):

结果:

【讨论】:

    【解决方案2】:

    应用至少大小为 3x3 的中值滤波器。

    【讨论】:

      猜你喜欢
      • 2021-08-03
      • 1970-01-01
      • 2018-09-30
      • 1970-01-01
      • 2018-06-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多