20

我正在尝试从来自“文档”的图像中找到水平线和垂直线。这些文档是合同中的扫描页面,因此这些行看起来像您在表格或合同块中看到的内容。使用OpenCV进行水平线检测

我一直在尝试OpenCV的工作。 OpenCV中的Hough变换实现对于这项工作似乎很有用,但是我找不到任何允许它干净地找到垂直和水平线的参数组合。我尝试了和没有边缘检测。没有运气。如果有人做了类似的事情,我有兴趣知道如何。

在这里看到我的前后使用OpenCV中的HoughP实验的图像。这是我能做的最好的,http://dl.dropbox.com/u/3787481/Untitled%201.png

所以现在我想知道是否有另一种转换我可以使用,这将允许我可靠地找到水平和垂直线(最好是虚线)。

我知道这个问题是可以解决的,因为我有Nuance和ABBYY OCR工具,它们都可以可靠地提取水平线和垂直线,并返回线框的边界框。

谢谢! Patrick。

回答

25

您是否看过HoughLinesP函数文档中的代码示例?

我认为你可以用它作为算法的起点。要选择水平垂直线,您只需按行角度过滤掉其他线。

UPDATE:

当我看到你需要找到不是在页面上线,但水平的垂直边缘。对于这个任务,你需要结合几个处理步骤来获得好的结果。

对于您的图片,我可以通过将Canny边缘检测与HoughLinesP相结合来获得良好的效果。这里是我的代码(我用Python,但我认为你看到的想法):

img = cv2.imread("C:/temp/1.png") 
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 
edges = cv2.Canny(gray, 80, 120) 
lines = cv2.HoughLinesP(edges, 1, math.pi/2, 2, None, 30, 1); 
for line in lines[0]: 
    pt1 = (line[0],line[1]) 
    pt2 = (line[2],line[3]) 
    cv2.line(img, pt1, pt2, (0,0,255), 3) 
cv2.imwrite("C:/temp/2.png", img) 

结果如下:

+0

嗨安德烈,谢谢。是的,我尝试了许多不同变量的HoughLinesP。我已经调整了我的原始问题,并且包含了我可以从HoughLinesP中获得的最佳图像的链接。是的,我确实试图限制只接近水平线。 –

+0

太棒了。显然我错过了Canny探测器。这是一个很好的结果。我还发现了一种称为Orthogonal Zig-Zag的算法,它可以提供这些线,然后扩展它们以确定线的宽度(这是HoughP无法做到的)。 –

+0

python中没有分号;) – mak

5

你可能会考虑离开霍夫线检测,因为这方法查找“全局”线,不一定是线段。最近,我实施了一个确定“平行四边形”的应用程序 - 基本上可以旋转的正方形以及由于视角而缩小的视角。你可能会考虑类似的东西。我的管道是:从RGB

  1. 转换为灰度(cvCvtColor)
  2. 平滑(cvSmooth)
  3. 阈值(cvThreshold)
  4. 检测边缘(cvCanny)
  5. 查找轮廓(cvFindContours)
  6. 具有线性特征的近似轮廓(cvApproxPoly)

在您的应用程序中,生成的轮廓列表可能很大(取决于Canny边缘检测器的平滑和特征增强的“积极性”。您可以通过各种参数修剪该列表:从轮廓查找器返回的点数,轮廓区域(cvContourArea)等等。根据我的经验,我希望应用程序中的“有效”行可以有明确的定义面积和顶点计数属性。此外,您可以根据端点之间的距离,连接端点的线所定义的角度等来滤除轮廓。

根据您拥有多少CPU“时间”,可以始终将Hough算法与像上面这样的算法来稳健地识别水平线和垂直线。

8

如果你只是想要“线”而不是“线段”,我会避免使用Canny,Hough,FindContours或任何其他此类功能,以防您希望代码中有更多速度。如果你的图像不旋转,你想要找到的东西总是垂直或水平的,我只需使用cv :: Sobel(一个用于垂直,另一个用于水平),并为列和行创建累加数组。然后,您可以在这些累积或配置文件中搜索最大值,例如通过设置阈值,并且您将知道存在垂直或水平边缘线的行或列。

+1

您是否知道在cv :: sobel中为水平线和垂直线设置的参数? –

4

不要将RGB转换为灰度。有时,RGB中的不同颜色可以合并为相同的灰度值,因此可能会遗漏一些轮廓。您应该分别分析每个RGB通道。