用于检测照片中纸张角落的算法

检测照片中发票/收据/纸张角落的最佳方法是什么? 在OCR之前,这将用于后续的透视校正。

我目前的做法是:

RGB>灰度>带阈值的Canny边缘检测>扩张(1)>移除小物体(6)>清除边界物体>根据凸面区域选择大型博客。 > [角落检测 - 未实施]

我不禁想到,必须有更强大的“智能”/统计方法来处理这种类型的细分。 我没有很多训练实例,但我可能会一起获得100张图像。

更广泛的上下文:

我正在使用matlab进行原型设计,并计划在OpenCV和Tesserect-OCR中实现该系统。 这是我需要为这个特定应用程序解决的许多图像处理问题中的第一个。 所以我期待推出我自己的解决方案并重新熟悉图像处理算法。

以下是我希望算法处理的一些示例图像:如果您想接受挑战,大图像位于http://madteckhead.com/tmp

案例1 http://madteckhead.com/tmp/IMG_0773_sml.jpg案例2 http://madteckhead.com/tmp/IMG_0774_sml.jpg案例3 http://madteckhead.com/tmp/IMG_0775_sml.jpg案例4 http:/ /madteckhead.com/tmp/IMG_0776_sml.jpg

最好的情况是:

案例1 - canny http://madteckhead.com/tmp/IMG_0773_canny.jpg案例1 - 发布canny http://madteckhead.com/tmp/IMG_0773_postcanny.jpg案例1 - 最大的博客http://madteckhead.com/tmp/ IMG_0773_blob.jpg

但在其他情况下很容易失败:

案例2 - canny http://madteckhead.com/tmp/IMG_0774_canny.jpg案例2 - post canny http://madteckhead.com/tmp/IMG_0774_postcanny.jpg案例2 - 最大的博客http://madteckhead.com/tmp/ IMG_0774_blob.jpg

预先感谢所有伟大的创意! 我喜欢这样!

编辑:霍夫变换进展

问:什么算法会聚合轮廓线以找到角落? 根据答案的建议,我可以使用Hough变换,拾取线条并对其进行过滤。 我目前的做法很粗糙。 我已经做出了这样的假设,发票总是小于15deg与图像不一致。 如果情况如此,我最终会得到合理的结果(见下文)。 但是我不完全确定一个合适的算法来聚合这些线(或者投票)来推算角落。 霍夫线不连续。 在嘈杂的图像中,可以有平行线,因此需要一些与线起点度量相关的形式或距离。 有任何想法吗?

案例1 http://madteckhead.com/tmp/IMG_0773_hough.jpg案例2 http://madteckhead.com/tmp/IMG_0774_hough.jpg案例3 http://madteckhead.com/tmp/IMG_0775_hough.jpg案例4 http:/ /madteckhead.com/tmp/IMG_0776_hough.jpg


我是马丁的朋友,今年早些时候正在研究这个问题。 这是我有史以来第一个编码项目,有点急于结束,所以代码需要一些错误...解码...我会给你看看你已经做过的一些技巧,然后在明天我的假期中对我的代码进行排序。

第一个技巧, OpenCVpython非常棒,尽快转移到它们。 :d

除去消除小物体和/或噪声,降低canny约束,所以它接受更多的边缘,然后找到最大的封闭轮廓(在OpenCV中使用findcontour()和一些简单的参数,我想我使用了CV_RETR_LIST )。 当它在一张白纸上时可能仍然很困难,但肯定会提供最好的结果。

对于Houghline2()变换,尝试使用CV_HOUGH_STANDARD而不是CV_HOUGH_PROBABILISTIC ,它会给出rho和theta值,在极坐标中定义该线,然后您可以将这些线分组到一定的容差范围内。

我的分组作为查找表,对于从hough变换输出的每一行,它将给出一个rho和theta对。 如果这些数值在表格中的一对数值的5%以内,则将其丢弃,如果它们超出5%,则将新条目添加到表格中。

然后,您可以更容易地分析平行线或线之间的距离。

希望这可以帮助。


我的大学里的一个学生组最近演示了一个iPhone应用程序(和python OpenCV应用程序),他们写的是这样做的。 我记得,步骤是这样的:

  • 中值过滤器可以完全去除纸上的文字(这是白纸上的手写文字,具有相当好的照明效果,可能不适用于印刷文字,它工作得很好)。 原因是它使拐角检测更容易。
  • Hough变换线
  • 在霍夫变换累加器空间中查找峰值并在整个图像上绘制每一行。
  • 分析线条并删除彼此非常接近并且角度相似的线条(将线条组合成一个)。 这是必要的,因为霍夫变换并不完美,因为它在离散样本空间中工作。
  • 查找大致平行并与其他对相交的线对,以查看哪些线形成四边形。
  • 这似乎工作得很好,他们能够拍摄一张纸或一本书的照片,执行角落检测,然后几乎实时地将图像中的文档映射到平面上(有一个OpenCV函数可以执行映射)。 当我看到它工作时没有OCR。


    下面是我经过一些实验后得出的结论:

    import cv, cv2, numpy as np
    import sys
    
    def get_new(old):
        new = np.ones(old.shape, np.uint8)
        cv2.bitwise_not(new,new)
        return new
    
    if __name__ == '__main__':
        orig = cv2.imread(sys.argv[1])
    
        # these constants are carefully picked
        MORPH = 9
        CANNY = 84
        HOUGH = 25
    
        img = cv2.cvtColor(orig, cv2.COLOR_BGR2GRAY)
        cv2.GaussianBlur(img, (3,3), 0, img)
    
    
        # this is to recognize white on white
        kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(MORPH,MORPH))
        dilated = cv2.dilate(img, kernel)
    
        edges = cv2.Canny(dilated, 0, CANNY, apertureSize=3)
    
        lines = cv2.HoughLinesP(edges, 1,  3.14/180, HOUGH)
        for line in lines[0]:
             cv2.line(edges, (line[0], line[1]), (line[2], line[3]),
                             (255,0,0), 2, 8)
    
        # finding contours
        contours, _ = cv2.findContours(edges.copy(), cv.CV_RETR_EXTERNAL,
                                       cv.CV_CHAIN_APPROX_TC89_KCOS)
        contours = filter(lambda cont: cv2.arcLength(cont, False) > 100, contours)
        contours = filter(lambda cont: cv2.contourArea(cont) > 10000, contours)
    
        # simplify contours down to polygons
        rects = []
        for cont in contours:
            rect = cv2.approxPolyDP(cont, 40, True).copy().reshape(-1, 2)
            rects.append(rect)
    
        # that's basically it
        cv2.drawContours(orig, rects,-1,(0,255,0),1)
    
        # show only contours
        new = get_new(img)
        cv2.drawContours(new, rects,-1,(0,255,0),1)
        cv2.GaussianBlur(new, (9,9), 0, new)
        new = cv2.Canny(new, 0, CANNY, apertureSize=3)
    
        cv2.namedWindow('result', cv2.WINDOW_NORMAL)
        cv2.imshow('result', orig)
        cv2.waitKey(0)
        cv2.imshow('result', dilated)
        cv2.waitKey(0)
        cv2.imshow('result', edges)
        cv2.waitKey(0)
        cv2.imshow('result', new)
        cv2.waitKey(0)
    
        cv2.destroyAllWindows()
    

    不完美,但至少适用于所有样品:

    1234

    链接地址: http://www.djcxy.com/p/13961.html

    上一篇: Algorithm to detect corners of paper sheet in photo

    下一篇: Predator TLK Algorithm in C#