algorithm检测照片中的纸张angular落

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

我目前的做法是:

RGB>灰度> Canny边缘检测与阈值> Dilate(1)>移除小物件(6)>清除边界物件>根据凸面区域挑选大型博客。 > [angular落检测 – 未实施]

我不禁想到,必须有一个更强大的“智能”/统计方法来处理这种types的分割。 我没有很多训练的例子,但是我可能一起得到100张图片。

更广泛的上下文:

我正在使用matlab来build立原型,并计划在OpenCV和Tesserect-OCR中实现这个系统。 这是我需要为这个特定应用程序解决的许多image processing问题中的第一个。 所以我期待推出自己的解决scheme,并重新熟悉image processingalgorithm。

下面是一些我希望algorithm处理的示例图片:如果您想要接受挑战,那么大图片位于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

预先感谢所有伟大的想法! 我喜欢这样!

编辑:霍夫变换进展

问:什么algorithm将聚类线findangular落? 根据答案的build议,我能够使用霍夫变换,挑线,并过滤它们。 我目前的做法相当粗糙。 我已经做了这样的假设,发票总是小于15deg与图像不一致。 如果是这种情况,我最终会得到合理的结果(见下文)。 但是,我不完全确定一个合适的algorithm来聚类(或投票)线外推的angular落。 霍夫线不连续。 而在嘈杂的图像中,可以有平行的线条,因此需要一些与线条原点度量相关的forms或距离。 有任何想法吗?

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

我是马丁的朋友,今年早些时候正在做这个工作。 这是我第一次编码项目,有点急于结束,所以代码需要一些errr …解码…我会给你一些我已经看到你做的,在我明天rest的时候把代码分类。

第一个技巧, OpenCVpython是很棒的,尽快移动到它们。 :d

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

对于Houghline2()变换,请使用CV_HOUGH_STANDARD而不是CV_HOUGH_PROBABILISTIC ,它会给出rhotheta值,在极坐标中定义该行,然后您可以将这些行分组到一定范围内。

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

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

希望这可以帮助。

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

  • 中值filter可以完全删除纸上的文字(这是白纸上的手写文字,具有相当好的照明效果,可能无法使用打印的文字,但效果很好)。 原因是它使angular点检测更容易。
  • Hough变换线
  • 在霍夫变换累加器空间中查找峰值,并在整个图像上绘制每一行。
  • 分析线条,并删除任何非常接近,并在相似的angular度(聚集成一条线)。 这是必要的,因为霍夫变换并不完美,因为它在一个不连续的样本空间中工作。
  • 查找大致平行的线条,并与其他线条相交以查看哪些线条形成四边形。

这似乎工作得很好,他们能够拍下一张纸或一本书的照片,进行angular落检测,然后将图像中的文档几乎实时地映射到平面上(有一个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() 

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

1234

而不是从边缘检测开始,你可以使用angular检测。

Marvin框架为此提供了Moravecalgorithm的实现。 你可以find论文的angular落作为出发点。 在Moravecalgorithm的输出之下:

在这里输入图像说明

边缘检测之后,使用Hough变换。 然后,将这些点与它们的标签一起放入SVM(支持向量机)中,如果例子中有平滑的线条,SVM就不会有任何困难去划分例子和其他部分的必要部分。 我对SVM的build议,把连接和长度等参数。 也就是说,如果积分相连并且很长,那么它们很可能是收据的一行。 那么,你可以消除所有其他的问题。

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

但是,这种检测对于实时检测而言并不总是会返回最佳结果,而是非常有用。

结果

这里你有@Vanuan的代码使用C ++:

 cv::cvtColor(mat, mat, CV_BGR2GRAY); cv::GaussianBlur(mat, mat, cv::Size(3,3), 0); cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Point(9,9)); cv::Mat dilated; cv::dilate(mat, dilated, kernel); cv::Mat edges; cv::Canny(dilated, edges, 84, 3); std::vector<cv::Vec4i> lines; lines.clear(); cv::HoughLinesP(edges, lines, 1, CV_PI/180, 25); std::vector<cv::Vec4i>::iterator it = lines.begin(); for(; it!=lines.end(); ++it) { cv::Vec4i l = *it; cv::line(edges, cv::Point(l[0], l[1]), cv::Point(l[2], l[3]), cv::Scalar(255,0,0), 2, 8); } std::vector< std::vector<cv::Point> > contours; cv::findContours(edges, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_TC89_KCOS); std::vector< std::vector<cv::Point> > contoursCleaned; for (int i=0; i < contours.size(); i++) { if (cv::arcLength(contours[i], false) > 100) contoursCleaned.push_back(contours[i]); } std::vector<std::vector<cv::Point> > contoursArea; for (int i=0; i < contoursCleaned.size(); i++) { if (cv::contourArea(contoursCleaned[i]) > 10000){ contoursArea.push_back(contoursCleaned[i]); } } std::vector<std::vector<cv::Point> > contoursDraw (contoursCleaned.size()); for (int i=0; i < contoursArea.size(); i++){ cv::approxPolyDP(Mat(contoursArea[i]), contoursDraw[i], 40, true); } Mat drawing = Mat::zeros( mat.size(), CV_8UC3 ); cv::drawContours(drawing, contoursDraw, -1, cv::Scalar(0,255,0),1); 
  1. 转换为实验室空间

  2. 使用kmeans段2群集

  3. 然后在其中一个簇(内部)上使用轮廓或hough,