2

从图像中,我需要提取一张纸,就像 camscanner 应用程序一样,https: //www.camscanner.com/

我知道我可以通过检测我想要检测的纸张的边缘来做到这一点。然后进行透视变换。我在 python 中使用 openCV 库。这是我试图在其中找到这张纸的图像:

一张纸来检测

这是我已经尝试过的:

方法1:(使用阈值)

  1. 使用图像平滑(高斯模糊/双边模糊)对图像进行预处理
  2. 将图像拆分为 h,s,v 通道
  3. 饱和通道上的自适应阈值
  4. 一些形态学操作,如膨胀和腐蚀
  5. 寻找轮廓,识别最大轮廓并找到角点

我已经根据 stackoverflow 答案实现了这个方法: 检测一张纸/正方形检测

我可以找到一些图像的纸张,但对于这样的图像它失败了:

纸张检测失败

方法2:(使用sobel梯度算子)

  1. 通过转换为灰度对图像进行预处理,图像平滑(高斯模糊/双边模糊)
  2. 寻找图像的梯度
  3. 对图像进行下采样和上采样
  4. 在此之后,我不知道如何找到包含图像的适当边界。

我已经根据 stackoverflow 答案实现了这种方法: 从背景中检测纸张几乎与纸张颜色相同

这是我对图像的了解程度:

索贝尔梯度结果

方法3:(使用canny边缘检测器)

根据我在这个社区上阅读的帖子,似乎每个人都更喜欢精明的边缘方法来提取边缘,但就我而言,结果并不令人满意。这是我所做的:

  1. 通过转换为灰度对图像进行预处理,图像平滑(高斯模糊/双边模糊)
  2. 使用精明的边缘寻找边缘
  3. 一些形态学操作,如膨胀和腐蚀
  4. 但是从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。

4

0 回答 0