从图像中,我需要提取一张纸,就像 camscanner 应用程序一样,https: //www.camscanner.com/
我知道我可以通过检测我想要检测的纸张的边缘来做到这一点。然后进行透视变换。我在 python 中使用 openCV 库。这是我试图在其中找到这张纸的图像:
这是我已经尝试过的:
方法1:(使用阈值)
- 使用图像平滑(高斯模糊/双边模糊)对图像进行预处理
- 将图像拆分为 h,s,v 通道
- 饱和通道上的自适应阈值
- 一些形态学操作,如膨胀和腐蚀
- 寻找轮廓,识别最大轮廓并找到角点
我已经根据 stackoverflow 答案实现了这个方法: 检测一张纸/正方形检测
我可以找到一些图像的纸张,但对于这样的图像它失败了:
方法2:(使用sobel梯度算子)
- 通过转换为灰度对图像进行预处理,图像平滑(高斯模糊/双边模糊)
- 寻找图像的梯度
- 对图像进行下采样和上采样
- 在此之后,我不知道如何找到包含图像的适当边界。
我已经根据 stackoverflow 答案实现了这种方法: 从背景中检测纸张几乎与纸张颜色相同
这是我对图像的了解程度:
方法3:(使用canny边缘检测器)
根据我在这个社区上阅读的帖子,似乎每个人都更喜欢精明的边缘方法来提取边缘,但就我而言,结果并不令人满意。这是我所做的:
- 通过转换为灰度对图像进行预处理,图像平滑(高斯模糊/双边模糊)
- 使用精明的边缘寻找边缘
- 一些形态学操作,如膨胀和腐蚀
- 但是从canny那里得到的边缘确实不合格。
我已经根据 stackoverflow 的答案实现了这个方法: Detecting a sheet / Square Detection,我也没有通过在这个答案中迭代多个通道来完成他的工作。这是我对图像的了解程度:
这是method1(阈值)的一些代码:
#READING IMAGE INTO BGR SPACE
image = cv2.imread("./images/sheet3.png")
#BILATERAL FILTERING TO SMOOTHEN THE IMAGE BUT NOT THE EDGES
img = cv2.bilateralFilter(image,20,75,75)
#CONVERTING BGR TO HSV
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
#SPLITTING THE HSV CHANNELS
h,s,v = cv2.split(hsv)
#DOUBLING THE SATURATION CHANNEL
gray_s = cv2.addWeighted(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY), 0.0, s, 2.0, 0)
#THRESHOLDING USING ADAPTIVETHRESHOLDING
threshed = cv2.adaptiveThreshold(gray_s, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, 109, 10)
#APPLYING MORPHOLOGICAL OPERATIONS OF DILATION AND EROSION
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (2, 2))
morph = cv2.morphologyEx(threshed, cv2.MORPH_OPEN, kernel)
#FINDING ALL THE CONTOURS
cnts = cv2.findContours(morph, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[-2]
canvas = img.copy()
#SORTING THE CONTOURS AND TAKING THE LARGEST CONTOUR
cnts = sorted(cnts, key = cv2.contourArea)
cnt = cnts[-1]
#FINDING THE PERIMETER OF THE CONTOUR
arclen = cv2.arcLength(cnt, True)
#FINDING THE END POINTS OF THE CONTOUR BY APPROX POLY DP
approx = cv2.approxPolyDP(cnt, 0.02* arclen, True)
cv2.drawContours(canvas, [cnt], -1, (255,0,0), 1, cv2.LINE_AA)
cv2.drawContours(canvas, [approx], -1, (0, 0, 255), 1, cv2.LINE_AA)
cv2.imwrite("detected.png", canvas)
我对图像处理和openCV有点陌生。请分享一些关于如何更进一步并更准确地获得结果的见解。TIA。