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

Nat*_*ler 91 opencv image-processing edge-detection image-segmentation hough-transform

检测照片中发票/收据/纸张角落的最佳方法是什么?在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 - post 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变换,拾取线条并过滤它们.我目前的做法相当粗糙.我已经假设发票总是小于15度,与图像不对齐.如果是这种情况,我最终得到合理的线条结果(见下文).但我不完全确定一个合适的算法来聚集线(或投票)来推断角落.霍夫线不连续.并且在嘈杂的图像中,可以存在平行线,因此需要与线原点度量的某种形式或距离.有任何想法吗?

案例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

Dan*_*ley 27

今年早些时候,我是马丁的朋友.这是我的第一个编码项目,有点匆匆结束,所以代码需要一些错误...解码...我会从我已经看到你做的一些提示,然后我明天休息一天.

第一个提示,OpenCV并且python很棒,尽快移动到它们.:d

而不是删除小物体和/或噪音,降低精确限制,因此它接受更多的边缘,然后找到最大的闭合轮廓(在OpenCV中使用findcontour()一些简单的参数,我想我用过CV_RETR_LIST).当它在一张白纸上时可能仍然会挣扎,但肯定会提供最好的结果.

对于Houghline2()变换,尝试使用CV_HOUGH_STANDARD相反的CV_HOUGH_PROBABILISTIC,它将给出rhotheta值,在极坐标中定义线,然后您可以将线分组在一定的容差范围内.

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

然后,您可以更轻松地分析平行线或线之间的距离.

希望这可以帮助.


Mar*_*oot 18

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

  • 中位数过滤器可以完全删除纸张上的文本(这是在白纸上手写的文字,具有相当好的照明,可能无法与打印文本一起使用,效果非常好).原因是它使角落检测更容易.
  • Hough变换线
  • 在Hough Transform累加器空间中找到峰值,并在整个图像上绘制每条线.
  • 分析线条并移除任何彼此非常接近的线条并且线条处于相似的角度(将线条聚为一个).这是必要的,因为霍夫变换并不完美,因为它在离散的样本空间中工作.
  • 找到大致平行且与其他对相交的线对,以查看哪些线形成四边形.

这似乎工作得相当好,他们能够拍摄一张纸或书的照片,执行角点检测,然后几乎实时地将图像中的文档映射到平面上(只有一个OpenCV函数可以执行映射).当我看到它工作时没有OCR.


Van*_*uan 16

这是我在经过一些实验后想出的:

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()
Run Code Online (Sandbox Code Playgroud)

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

1 2 3 4

  • 我正在做类似的项目.我在代码上方运行,它给出了错误"没有名为cv的模块".我安装了Open CV 2.4版本,导入cv2对我来说非常合适. (2认同)

Gab*_*njo 9

您可以使用角点检测,而不是从边缘检测开始.

Marvin Framework为此提供了Moravec算法的实现.您可以找到论文的角落作为起点.在Moravec算法的输出下面:

在此输入图像描述


Fla*_*ayn 5

您也可以在 Sobel 算子结果上使用MSER(最大稳定极值区域)来查找图像的稳定区域。对于 MSER 返回的每个区域,您可以应用凸包和多边形近似以获得如下所示的区域:

但是这种检测对于实时检测不仅仅是一张并不总是返回最佳结果的图片很有用。

结果