使用OpenCV检测损坏的形状

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用OpenCV检测损坏的形状相关的知识,希望对你有一定的参考价值。

我试图检测4条内的方块。目标是比较他们的质心。在大多数情况下,我的方法(如下所述)正确识别大多数情况。在焦点不好或光线太低的图像中,处理后的图像有一个破碎或断开的正方形,其轮廓未使用Canny检测到。以下是一般方法流程:

  1. 使用模板匹配来查找“条形图”并创建ROI
  2. 在ROI上使用adaptiveThreshold和ADAPTIVE_THRESH_MEAN_C
  3. 通过将ROI的边缘设置为255(白色)来隔离正方形
  4. 使用PHYSEx和MORPH_OPEN以及(8,8)MORPH_RECT作为结构元素
  5. 通过imutils.auto_canny方法(由Adri Rosebrock在pyimagesearch.com上编写)使用优化的Canny来查找正方形
  6. 返回'bars'和'square'的中心,并在原始图像上显示它们的minAreaRect

以下是一个典型成功的例子:thresholded ROI'bars' removedmorphology appliedoriginal with detected shapes

这是一个破碎的,无法察觉的'正方形'的例子:thresholded ROI'bars' removedmorphology appliedoriginal with detected shapes

我试过的事情:

在第2步:

methods = ['cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)[1]',
           'cv2.threshold(cv2.GaussianBlur(gray, (5, 5), 0), 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]',
           'cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 51, 2)',
           'cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 51, 2)']

全局阈值无法解释从图像到图像的不同亮度。 ADAPTIVE_THRESH_MEAN_C的成功率高于ADAPTIVE_THRESH_GAUSSIAN_C。两者中的'51'都是随意的;通过测试,似乎更高的数字产生了更清洁的形状。

在第4步:

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (8, 8))
roi = cv2.morphologyEx(roi, cv2.MORPH_OPEN, kernel)

对于结构元素,我使用了各种大小的RECT,ELLIPSE和CROSS。如果它们变得太大,我最终会在'square'中创建形状,auto.canny更喜欢检测它,并且不知何故再也无法找到外部'square'。使用RETR_EXTERNAL而不是RETR_LIST,RETR_CCOMP或RETR_TREE不能解决此问题。对于形态学操作,我已经尝试过MORPH_OPEN并分别扩张/侵蚀,以便在轮廓检测之前关闭破碎的“方形”形状。

在第5步:

auto_canny似乎运作良好。在所有这些处理之后我尝试了匹配'square'的模板,但它经常失败。

我正在寻找一种能够捕捉当前成功和一些更“可实现”失败的独特解决方案。我愿意接受你提供的任何智慧。我正在考虑的新方向:

  • 在侧面使用线检测并找到它们连接的位置
  • 我可以用approxPolyDP估算一个正方形吗?
  • 为'square'编写我自己的检测算法。它将涉及在numpy数组中找到角点,在这些点之间创建一个正方形,并稍微扩展它。

虽然我希望有一种神奇的方法可以完全满足我的需求,但我花了几个时间来研究这个问题,并期待一个类似的困难答案。预先感谢您的帮助!

答案

在找到中心之前尝试填充广场。我通过迭代行并连接最左边和最右边的黑色像素来做到这一点。

filling in square

# Iterate through each row in the image
for row in range(img.shape[0]):
    # Find the left-most and right-most pixel in the sqare
    start, stop = 0, 0
    for col in range(img.shape[1]):
        # Find the left-most
        if img[row,col] != 255 and start == 0: start = col, row
        # Find the right-most
        if img[row,col] != 255: stop = col, row
    # If there was a pixel in that row, connect them with a line
    if start != 0:
        cv2.line(img, start, stop, 0, 1)

以上是关于使用OpenCV检测损坏的形状的主要内容,如果未能解决你的问题,请参考以下文章

pyhton—opencv直线检测(HoughLines)找到最长的一条线

Python OpenCV 人脸检测代码有时会引发“元组”对象没有属性“形状”

使用OpenCV实时检测不同形状的交通标志

在 iOS 上使用 OpenCV 检测人脸边缘/形状

使用 OpenCV 检测图像中已知形状/对象的方法

如何使用 Opencv 检测三角形交通标志