使用cv :: findContours从二进制掩码中查找最大区域对象失败,因为轮廓未关闭。怎么预防?

时间:2015-08-25 18:25:33

标签: c++ opencv opencv-contour

我试图在视频源中根据其形状特征(例如:面积,轮廓长度等)执行暗(几乎黑色)物体检测,但是我在检测二进制掩模中的轮廓时遇到问题。

有时即使对象没有改变形状并且轮廓是从仅包含一个紧凑blob的简单蒙版派生的,轮廓也没有关闭(我可以说,因为我用CV_FILLED选项显示它,并且对于许多帧,轮廓被填充),并且由于该计算的区域实际上不可靠(值降低到几个像素)。

我也注意到,当物体的轮廓没有关闭时,长度大约是假设的2倍(这是有意义的)。

为什么简单blob的轮廓有时会打开并且有时会关闭,以及我如何强制它们始终关闭?我已经尝试过凸包,并将轮廓的第一个点复制到它的末端,但它没有用。

我的方法步骤如下:

  1. 将图像转换为灰度
  2. 进行阈值处理,侵蚀和扩张以消除噪音并改善"形状"
  3. 使用Canny边缘检测器确实只获得边缘
  4. 使用findContours获取轮廓及其区域:
  5. 使用arcLength计算轮廓长度和其他特征。

1 个答案:

答案 0 :(得分:0)

  
      
  1. 使用Canny边缘检测器确实只获得边缘
  2.   

这是一个经典的错误。在步骤2之后和期间,我假设你有一个二进制图像,即带有一堆填充白色斑点的黑色图像,表示你想要找到的区域。 这正是cv::findContours的作用。

当你进行边缘检测时,你实际上将那些漂亮的填充区域变成了一堆非常细长的可能但不一定的闭合线,这些线条束缚了你以前的区域,这会让一切变得混乱。因此cv::findContours将完全返回,一堆非常薄的轮廓。那些轮廓 实际上也是闭合的,因为它们代表一个封闭的多边形,最后一个点连接回第一个,只是这个多边形环绕那些细线从边缘检测,这解释了为什么他们的面积非常小,周长大约是你期望的两倍。它基本上将边缘检测产生的线条视为实际轮廓,而不是想要找到边界轮廓的非常薄区域,这可能不是你的打算。

如果这些边界线已关闭,您只能检索外部轮廓(例如使用CV_RETR_EXTERNAL),可能获取关于你期望的相同的适当面积轮廓,但这不能保证,很容易弄乱。

因此,简单的解决方案是放弃Canny边缘检测步骤并直接处理正确的二进制图像,因为cv::findContours 通常意图。