如何在python opencv中完成/关闭轮廓?

时间:2017-03-24 22:07:25

标签: python opencv

我有一个Pi相机指向白色背景上的卡片。然而,局部阴影似乎阻止了我用于卡片检测的轮廓的关闭,这意味着整体检测失败。这是我的意思截图:

Screenshot of open contours

你可以看到它特别是在底角附近褴褛。这是我用来实现这个目标的代码:

gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
gray = cv2.blur(gray, (5,5))
gray = cv2.bilateralFilter(gray, 11, 17, 17) #blur. very CPU intensive.
cv2.imshow("Gray map", gray)

edges = cv2.Canny(gray, 30, 120)

cv2.imshow("Edge map", edges)

#find contours in the edged image, keep only the largest
# ones, and initialize our screen contour
# use RETR_EXTERNAL since we know the largest (external) contour will be the card edge.
_, cnts, _ = cv2.findContours(edges.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = sorted(cnts, key = cv2.contourArea, reverse = True)[:1]
screenCnt = None

# loop over our contours
for c in cnts:
    # approximate the contour
    peri = cv2.arcLength(c, True)
    approx = cv2.approxPolyDP(c, 0.3 * peri, True)

    cv2.drawContours(image, [cnts[0]], -1, (0, 255, 0), 2)

    # if our approximated contour has four points, then
    # we can assume that we have found our card
    if len(approx) == 4:
        screenCnt = approx;
    break

有没有办法强迫它关闭特定的轮廓?如果我模糊图像更多以平滑不起作用的阴影,因为它只是忽略那些没有边缘的角落。令人讨厌的是它距离关闭轮廓只有几个像素,但它从来没有......

编辑:我现在有一个更逼真的设置,背景是米色,并且有更多的阴影干扰。米色是必要的,因为有一些白色边框卡,所以白色不起作用。边缘检测主要在阴影所在的左侧失败。

enter image description here

1 个答案:

答案 0 :(得分:8)

正如我在评论中提到的那样,在边框中“连接”线条的最简单方法之一是使用形态运算符。在以下代码中,使用椭圆体形状扩大图像的边缘。这种技术允许我们合并靠近的线并填充一些空的空间。您可以在OpenCV Documentation

中获得有关此主题的更多信息
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(9,9))
dilated = cv2.dilate(image, kernel)
_, cnts, _ = cv2.findContours(dilated.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

在这里,您可以看到原始边缘图像,扩张图像和使用扩张边缘获得的轮廓(使用原始屏幕截图的裁剪区域获得的图像):

但是,正如你所看到的那样,也可以想象,为更一般的情况解决这个问题更复杂,需要使用其他方法,并且可能比SO问题更广泛(或者至少在制定它的方式现在)。

通过查看更困难的情况,我建议您使用其他图像表示来替换灰度输入图像(例如HSV色彩空间中的H通道),以减少或减弱阴影效果。您还可以探索问题中的一些约束:卡总是将直线作为边界并使用能够处理参数形式的方法,例如Hough Lines检测器。看看这个问题,它可以为您提供有关如何改善结果的一些见解:How to identify square or rectangle with variable lengths and width by using javacv?

备注:双边过滤的计算成本非常高,尤其是在使用RPi运行应用程序时。我建议投资其他一些替代方案,例如高斯滤波,以减少图片中的噪声量(假设你真的需要这样做)。