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

2024-05-23 21:52:19 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个圆周率摄像机对着一张白底卡片。但是,局部阴影似乎阻止了我用于卡片检测的轮廓的闭合,这意味着检测整体失败。这是我的意思的截图:

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


Tags: thetrueourcv2轮廓wecontour阴影
1条回答
网友
1楼 · 发布于 2024-05-23 21:52:19

正如我在给你的回复中提到的,最简单的“连接”边界线的方法之一就是使用形态学运算符。在下面的代码中,使用椭球形状来放大图像的边缘。这项技术允许我们合并比较接近的行,并填充一些空白区域。您可以在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)

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

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

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

备注:双边过滤在计算上非常昂贵,特别是在使用RPi运行应用程序时。我建议投资一些其他的选择,例如高斯滤波,以减少图片中的噪声量(假设您真的需要这样做)。

相关问题 更多 >