如何使用opencv python在不同颜色背景中找到文档边缘?【各种背景下的文档扫描】

7

我目前有一份需要进行智能扫描的文档。

为此,我需要在任何背景下找到文档的适当轮廓,以便我可以对图像进行透视映射和检测。

在此过程中遇到的主要问题是文档边缘会检测到任何类型的背景。

我已经尝试使用HoughLineP函数,并尝试在通过Canny边缘检测的灰度模糊图像上查找轮廓。


            MORPH = 9
            CANNY = 84
            HOUGH = 25

            IM_HEIGHT, IM_WIDTH, _ = rescaled_image.shape

            # convert the image to grayscale and blur it slightly
            gray = cv2.cvtColor(rescaled_image, cv2.COLOR_BGR2GRAY)
            gray = cv2.GaussianBlur(gray, (7,7), 0)

            #dilate helps to remove potential holes between edge segments
            kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(MORPH,MORPH))
            dilated = cv2.dilate(gray, kernel)

            # find edges and mark them in the output map using the Canny algorithm
            edged = cv2.Canny(dilated, 0, CANNY)
            test_corners = self.get_corners(edged)

            approx_contours = []

    (_, cnts, hierarchy) = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
            cnts = sorted(cnts, key=cv2.contourArea, reverse=True)[:5]

            # loop over the contours
            for c in cnts:
                # approximate the contour
                approx = cv2.approxPolyDP(c, 80, True)
                if self.is_valid_contour(approx, IM_WIDTH, IM_HEIGHT):
                    approx_contours.append(approx)
                    break

文档示例图片 如何通过OpenCV代码找到文档的适当边界框。 非常感谢您的任何帮助。(文档是从任意角度和任何彩色背景的相机中拍摄的。)


1
请建议应该采用什么类型的图像作为输入来查找轮廓。 - Pratik Prajapati
是否有基于图像的规则可以让我们预测边界框,如果没有,那么您正在查看一个机器学习应用程序,如果有,请提及一些规则,最好的方法应该是梯度分析或图割,但在没有更多数据集信息的情况下无法确定。 - anand_v.singh
不,它不是基于某个数据集的机器学习应用程序。它需要直接检测放置在任何背景中的文档的边缘。 - Pratik Prajapati
没有硬性规定,但它应该适用于任何文档。让我添加一个示例图像。 - Pratik Prajapati
https://stackoverflow.com/questions/51927043/image-processing-how-to-detect-borders-of-a-bill-in-an-image/51927693#51927693 有一个类似的问题,但是这里的页面也是弯曲的,并且照明不同。 - abunickabhi
是的。让我也检查一下这个链接。谢谢@abunickabhi。 - Pratik Prajapati
2个回答

9
以下代码可能会帮助您检测/分割图像中的页面...
import cv2
import matplotlib.pyplot as plt
import numpy as np
image = cv2.imread('test_p.jpg')
image = cv2.imread('test_p.jpg')
print(image.shape)
ori = image.copy()
image = cv2.resize(image, (image.shape[1]//10,image.shape[0]//10))

将图像调整大小以使操作更快,以便我们可以在实时环境下工作。

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (11,11), 0)
edged = cv2.Canny(gray, 75, 200)
print("STEP 1: Edge Detection")
plt.imshow(edged)
plt.show()
cnts = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
cnts = sorted(cnts[1], key = cv2.contourArea, reverse = True)[:5]

在这里,我们只考虑基于面积排序列表中的前5个轮廓。 高斯模糊的大小有些敏感,因此根据图像大小选择适当的大小。 经过上述操作后,图像可能看起来像这样...

Image with Edges

for c in cnts:
    ### Approximating the contour
    #Calculates a contour perimeter or a curve length
    peri = cv2.arcLength(c, True)
    approx = cv2.approxPolyDP(c, 0.01 * peri, True)
    # if our approximated contour has four points, then we
    # can assume that we have found our screen
    screenCnt = approx
    if len(approx) == 4:
        screenCnt = approx
        break
    # show the contour (outline) 
    print("STEP 2: Finding Boundary")
cv2.drawContours(image, [screenCnt], -1, (0, 255, 0), 2)
image_e = cv2.resize(image,(image.shape[1],image.shape[0]))
cv2.imwrite('image_edge.jpg',image_e)
plt.imshow(image_e)
plt.show()

最终图像可能看起来像这样...

得到最终图像后,其余的事情可以处理...

代码参考:- Git存储库

我想这个答案会有帮助的...


高斯模糊的大小是否敏感? - abunickabhi
1
感谢您提供的出色答案。它在大多数背景下都能正常工作。 - Pratik Prajapati
这段代码看起来很像 https://www.pyimagesearch.com/2014/09/01/build-kick-ass-mobile-document-scanner-just-5-minutes/ 上的那个。 - Erdogan Kurtur

2

有一个类似的问题被称为正交投影。

正交投影方法

不要尝试使用高斯模糊+形态学操作来获取文档的边缘,而是先进行正交投影,然后再通过您的方法找到轮廓。

为了找到合适的边界框,请尝试一些预设值或参考字母,然后进行正交投影,从而计算出边界框的高度和尺寸。

"Original Answer"翻译成"最初的回答"

1
让我试试看。谢谢。 - Pratik Prajapati

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接