如何在OpenCV Python中对附近轮廓进行分组?-斑马线检测

3
我想检测斑马线路。我已经尝试使用轮廓查找图像中斑马线路的坐标,但它仅为不同的白色框(仅斑马线中的白线)提供输出。但我需要整个斑马线路的坐标。
请告诉我如何分组轮廓或建议另一种检测斑马线路的方法。 输入图像 获得的输出图像 期望的输出
import cv2
import numpy as np
image = cv2.imread('d.jpg',-1)
paper = cv2.resize(image,(500,500))
ret, thresh_gray = cv2.threshold(cv2.cvtColor(paper, cv2.COLOR_BGR2GRAY),
                        200, 255, cv2.THRESH_BINARY)
image, contours, hier = cv2.findContours(thresh_gray, cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
for c in contours:
    rect = cv2.minAreaRect(c)
    box = cv2.boxPoints(rect)
    # convert all coordinates floating point values to int
    box = np.int0(box)
    cv2.drawContours(paper, [box], 0, (0, 255, 0),1)
cv2.imshow('paper', paper)
cv2.imwrite('paper.jpg',paper)
cv2.waitKey(0)

1
你看过合并相邻轮廓吗? - coffeewin
你能分享源图像吗? - Yunus Temurlenk
1
@YunusTemurlenk 我想要检测斑马线。我已经在描述中添加了预期的输出图像,请查看。谢谢。 - Thrisha Ramkumar
1
可以创建算法,但不能期望它在每个图像中都能正常工作。我认为训练似乎是更好的解决方案。 - Yunus Temurlenk
1
尝试使用cv2.inRange()对白色进行颜色阈值处理。然后使用形态学方法合并二进制图像中的区域。最后获取轮廓。 - fmw42
显示剩余2条评论
1个回答

4

您可以使用 closing 形态学运算来填补空隙。

我建议按照以下步骤进行:

  • thresh_gray 中查找轮廓。
  • 删除面积非常小的轮廓(噪声)。
  • 删除长宽比较低的轮廓(假设斑马线必须是长而窄的)。
  • 使用 morphologyEx 进行闭合形态学操作 - 闭合操作会合并相邻的组件。
  • 在擦除和闭合后的图像中再次查找轮廓。
    在最后一个阶段,忽略小轮廓。

这里是一个可用的代码示例:

import cv2
import numpy as np

image = cv2.imread('d.jpg', -1)
paper = cv2.resize(image, (500,500))
ret, thresh_gray = cv2.threshold(cv2.cvtColor(paper, cv2.COLOR_BGR2GRAY), 200, 255, cv2.THRESH_BINARY)
image, contours, hier = cv2.findContours(thresh_gray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

# Erase small contours, and contours which small aspect ratio (close to a square)
for c in contours:
    area = cv2.contourArea(c)

    # Fill very small contours with zero (erase small contours).
    if area < 10:
        cv2.fillPoly(thresh_gray, pts=[c], color=0)
        continue

    # https://stackoverflow.com/questions/52247821/find-width-and-height-of-rotatedrect
    rect = cv2.minAreaRect(c)
    (x, y), (w, h), angle = rect
    aspect_ratio = max(w, h) / min(w, h)

    # Assume zebra line must be long and narrow (long part must be at lease 1.5 times the narrow part).
    if (aspect_ratio < 1.5):
        cv2.fillPoly(thresh_gray, pts=[c], color=0)
        continue


# Use "close" morphological operation to close the gaps between contours
# https://stackoverflow.com/questions/18339988/implementing-imcloseim-se-in-opencv
thresh_gray = cv2.morphologyEx(thresh_gray, cv2.MORPH_CLOSE, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (51,51)));

# Find contours in thresh_gray after closing the gaps
image, contours, hier = cv2.findContours(thresh_gray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

for c in contours:
    area = cv2.contourArea(c)

    # Small contours are ignored.
    if area < 500:
        cv2.fillPoly(thresh_gray, pts=[c], color=0)
        continue

    rect = cv2.minAreaRect(c)
    box = cv2.boxPoints(rect)
    # convert all coordinates floating point values to int
    box = np.int0(box)
    cv2.drawContours(paper, [box], 0, (0, 255, 0),1)

cv2.imshow('paper', paper)
cv2.imwrite('paper.jpg', paper)
cv2.waitKey(0)
cv2.destroyAllWindows()

在擦除小而方的轮廓之前,thresh_gray 的图像如下:
enter image description here 在擦除小而方的轮廓之后,thresh_gray 的图像如下:
enter image description here 在闭合操作之后,thresh_gray 的图像如下:
enter image description here 最终结果为:
enter image description here

备注:
我对使用形态学操作来填补间隙的益处有些疑虑。
也许更好的方法是基于几何智能逻辑。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接