【发布时间】:2021-05-22 00:04:01
【问题描述】:
我想获取页面的 4 个角, 我采取的步骤:
- 转换为灰度
- 图像应用阈值
- 应用 Canny 检测边缘
- 之后我使用了
findContours - 为每个多边形绘制近似多边形,我的假设是相关的多边形必须有 4 个顶点。
但在此过程中我发现我的解决方案有时会丢失, 显然我的解决方案不够健壮(可能有点幼稚的解决方案)。
我认为那些纸角检测失败的一些原因是:
- 手动选择阈值以进行精确检测。
-
approxPolyDP的 epsilon 值相同
我的代码
import cv2
import numpy as np
image = cv2.imread('page1.jpg')
descalingFactor = 3
imgheight, imgwidth = image.shape[:2]
resizedImg = cv2.resize(image, (int(imgwidth / descalingFactor), int(imgheight / descalingFactor)),
interpolation=cv2.INTER_AREA)
cv2.imshow(winname="original", mat=resizedImg)
cv2.waitKey()
gray = cv2.cvtColor(resizedImg, cv2.COLOR_BGR2GRAY)
cv2.imshow(winname="gray", mat=gray)
cv2.waitKey()
img_blur = cv2.GaussianBlur(gray, (5, 5), 1)
cv2.imshow(winname="blur", mat=img_blur)
cv2.waitKey()
canny = cv2.Canny(gray,
threshold1=120,
threshold2=255,
edges=1)
cv2.imshow(winname="Canny", mat=canny)
cv2.waitKey()
contours, _ = cv2.findContours(image=canny, mode=cv2.RETR_EXTERNAL, method=cv2.CHAIN_APPROX_SIMPLE)
contours = sorted(contours, key=cv2.contourArea, reverse=True)
for idx, cnt in enumerate(contours):
# print("Contour #", idx)
# print("Contour #", idx, " len(cnt): ", len(cnt))
cv2.drawContours(image=resizedImg, contours=[cnt], contourIdx=0, color=(255, 0, 0), thickness=3)
cv2.imshow(winname="contour" + str(idx), mat=resizedImg)
conv = cv2.convexHull(cnt)
epsilon = 0.1 * cv2.arcLength(cnt, True)
approx = cv2.approxPolyDP(cnt, epsilon, True)
cv2.drawContours(resizedImg, [approx], 0, (0, 0, 255), 3)
cv2.waitKey(0)
if len(approx) == 4:
print("found the paper!!")
break
pts = np.squeeze(approx)
另一种方法
我想知道将具有 4 个顶点(四边形)的多边形拟合到轮廓,然后检查多边形与轮廓之间的面积差是否低于指定阈值,这不是更好的方法。
有人可以建议一个更强大的解决方案(用代码演示),谢谢。
图片:
image1:https://ibb.co/K2SqLwZ
image4:https://ibb.co/xh7W41V
【问题讨论】:
-
您需要更好的背景和照明。光反射使得很难从背景中确定页面。使用漫反射照明。带纹理的背景也很难处理。使用固定颜色的。
-
如果您一次拍摄多于一页(3 和 4 有两页),您很容易得到超过 4 个角。
-
您可以使用 cv2.goodFeaturesToTrack() 进行角点检测。它可以让你避免角落靠得太近。
标签: python opencv image-processing