【发布时间】:2017-03-24 22:07:24
【问题描述】:
我有一个 Pi 相机对准一张白色背景上的卡片。然而,局部阴影似乎阻止了我用于卡片检测的轮廓的闭合,这意味着检测总体上失败了。这是我的意思的截图:
您可以看到它在底角处变得参差不齐。这是我用来实现这一目标的代码:
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
有没有办法强制它关闭特定的轮廓?如果我进一步模糊图像以平滑不起作用的阴影,因为它只是忽略了那些没有边缘的角落。令人讨厌的是它距离关闭轮廓只有几个像素,但它从来没有......
编辑:我现在有一个更逼真的设置,其中背景是米色,并且有更多的阴影干扰。米色是必要的,因为有些卡片有白色边框,所以白色不起作用。边缘检测主要在阴影所在的左侧失败。
【问题讨论】:
-
有几种方法可以解决您的问题。 1)您可以使用形态运算符来关闭您的图像边界(扩张等)。 2)您可以使用 Otsu 方法对图像进行阈值处理,然后找到边界。 3)你可能想看看这个问题:stackoverflow.com/questions/8667818/…
-
@EliezerBernart 我将在什么上应用形态运算符;边缘层还是原始层?我尝试了 Otsu 阈值,但它不会自动找出正确的阈值来去除阴影。此外,有些卡片有白色边框(我已经移到了棕色背景),这至少会使简单的阈值无效。
-
如果您的背景颜色变化很大并且 Otsu 没有帮助,您可能需要扩大您的边缘或与其他运算符和您应用它们的顺序一起玩一点。您可以尝试的另一种方法是使用霍夫线来检测卡片的边框:) 能否分享您的卡片图片,以便我运行您的代码并验证问题所在?
-
@EliezerBernart 将我当前设置的屏幕截图附加到 OP。
-
好的,谢谢!我去看看;)