OpenCV:使用轮廓和霍夫变换进行矩形检测

5

我正在尝试使用不同的方法在灰度图像中检测白色矩形:轮廓检测和Hough变换。不幸的是,我处理的图像存在以下一些限制:

  1. 图像中有许多特征,而矩形并不是唯一的特征。
  2. 矩形可能与其他特征合并(例如,矩形的一条边可能与一条长直线重叠)。
  3. 矩形可能包含其他一些特征(例如,字母、数字或矩形内部的某个标志)。
  4. 有一些特征看起来像矩形(例如,字符“D”看起来像顶部右侧和底部右侧带有小弧的矩形;另一个例子是梯形而不是平行四边形)。
  5. 矩形可以在0到15度的范围内顺时针和逆时针旋转。
  6. 在不同的光照条件下可能会将线段断成几条线段(例如1像素间隙),因此在过滤线段的最小长度必须很小(例如,在Hough变换中)。
  7. 当将最小线段长度设置为小值时,更容易看到同一条线在不同方向上的重复线(即需要组合几条线)。
对于轮廓法,某些图像的轮廓会被打断。此外,图像可能包含矩形等特征(例如字符“D”)。我不确定这是否是一个好方法。
我看过许多文章/论坛,建议使用霍夫变换来检测类似矩形的物体,如下面的帖子所示。不幸的是,我必须设置较小的最小线长度,并且看到了重复的线条。我不知道如何处理上述提到的点(例如组合所有重复的线条,为每个边缘选择一条线条,如何区分大部分是线条但具有小弧度的特征,如“D”,以及如何隔离与长直线合并的一条边的正方形等)。
任何建议都受欢迎!
编辑:添加一些图片

Character D

角色D

Rect edge merged with long straight line

矩形带有标志,边缘与长直线融合

enter image description here

梯形(顶部有阴影,形成底部梯形)

展示一个输入图像的例子会有所帮助。 - Antonio
@Antonio:图片已添加,谢谢 :) - chesschi
1个回答

1
我建议您在每个图像上使用二值阈值(自适应或其他),这将为轮廓检测提供一些清晰的线条。您还可以腐蚀/膨胀图像以消除噪声(例如第二张图像中的细线)。
然后使用轮廓检测,计算轮廓数量,并找到具有四边的图像中最大的对象(这可能是您的对象)。
在使用二进制/侵蚀之前,请复制图像,以便一旦从轮廓检测中获得感兴趣的区域,您就可以将副本图像裁剪到该区域。
抱歉,示例链接是用Python编写的,但我相信一旦您理解了这个想法,将其移植到C ++将很容易。
希望这可以帮助您。
编辑

我刚才尝试了上述方法,通过对每个图像进行阈值化、轮廓检测,然后在最大轮廓周围绘制一个边界框。

下面是结果:

enter image description here

最大轮廓周围的边界框

enter image description here

相同的内容,在原始图像上绘制。

enter image description here


我以前做过你建议的类似的事情。但是我发现,在二值化阈值处理后,矩形的轮廓在不同的光照条件下可能会被分成2-3个部分。对我来说,Hough变换给出了更好的直线。我知道我们需要找到交点来得到矩形。然而,如果每条边上有多条具有不同方向的直线,你知道如何将这些线组合成一条并找到交点吗?对于轮廓法,我认为这比Hough线更难组合轮廓。 - chesschi
如果您使用自适应阈值(如链接中所示),您应该会发现对象不会被分割,因为阈值是在几个局部区域内计算的,而不是整个图像,这将确保光照条件对最终得到的二进制影响较小。如果您发现霍夫线性变换给出更好的结果,也许最好坚持使用它,我发现,将您熟悉的东西调整到适合您的目的总是更容易的。如果您能够获得每条线的XY或每个端点,您可能能够根据周围的线来选择正确的线。 - Aphire
我记得我也尝试过自适应阈值,但结果更差。对于霍夫变换,是否有一种常见的做法来“选择”正确的线条,或者将每个边缘的线条合并成一条? - chesschi
我建议您重新审视阈值和轮廓,我刚刚尝试了一下,效果非常好。我使用全局阈值获取二进制图像,然后检测轮廓,并在最大轮廓集周围绘制边界框。我将编辑我的帖子并为您添加图片。 - Aphire
我必须承认,我不知道这是否是常见的做法,但这是我会做的:P 我认为如果你使用二进制阈值,然后用Canny算子处理图像,应该可以去除大部分噪音,使得霍夫线变换更加精确。如果你仍然得到很多线条,那么你可以看看“平均角点”有多准确 :) - Aphire
显示剩余4条评论

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