Contours opencv:如何消除二进制图像中的小轮廓

我目前正在从事图像处理项目。 我在VC ++中使用Opencv2.3.1。 我编写了这样的代码,输入图像被过滤为仅蓝色并转换为二进制图像。 二进制图像有一些我不想要的小物体。 我想消除那些小对象,所以我使用openCV的cvFindContours()方法来检测二进制图像中的轮廓。 但问题是我无法消除图像输出中的小物体。 我使用了cvContourArea()函数,但没有正常工作..,侵蚀function也无法正常工作。

所以请有人帮我解决这个问题..

我获得的二进制图像

在此处输入图像描述

我想要获得的结果/输出图像

在此处输入图像描述

好的,我相信你的问题可以通过OpenCV最近推出的边界框演示来解决。

在此处输入图像描述

您可能已经注意到,您感兴趣的对象应位于图片中最大的矩形绘制区域内。 幸运的是,这段代码并不是很复杂,我相信你可以通过调查和实验来解决这个问题。

这是我消除小轮廓的解决方案。 基本思想是检查每个轮廓的长度/面积,然后从矢量容器中删除较小的一个。

通常你会得到这样的轮廓

 Mat canny_output; //example from OpenCV Tutorial vector > contours; vector hierarchy; Canny(src_img, canny_output, thresh, thresh*2, 3);//with or without, explained later. findContours(canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0,0)); 

使用Canny()预处理,您将获得轮廓线段,但每个线段都存储有边界像素作为闭环。 在这种情况下,您可以检查长度并删除小的长度

 for (vector >::iterator it = contours.begin(); it!=contours.end(); ) { if (it->size() 

如果没有Canny()预处理,您将获得对象的轮廓。 相似之处,您也可以使用区域来定义阈值以消除小对象,如OpenCV教程所示

 vector contour = contours[i]; double area0 = contourArea(contour); 

此contourArea()是非零像素的数量

你确定通过小轮廓区域过滤不起作用吗? 它总是对我有用。 我们能看到您的代码吗?

此外,正如sue-ling所提到的,使用侵蚀和扩张来大致保留区域是个好主意。 要去除小的噪声位,首先使用侵蚀,并填充孔,首先使用扩张。

另外,如果您还没有了解cv *函数的新C ++版本,那么您可能需要查看它们( findContours 文档 )。 在我看来,它们更容易使用。

通过前后图像判断,需要确定所有白色区域或斑点的面积,然后应用阈值区域值。 这将消除小于该值的所有区域,并且仅留下在第二图像中看到的大的白色区域。 使用cvFindContours函数后,尝试使用0阶时刻。 这将返回图像中斑点的区域。 此链接可能有助于实现我刚才描述的内容。 http://www.aishack.in/2010/07/tracking-colored-objects-in-opencv/

我相信你可以使用像erode和dilate这样的形态学操作符( 在这里阅读更多)

您需要使用靠近右侧圆圈半径的内核大小(您要消除的那个)执行侵蚀。 然后使用相同的内核进行扩张,以填补侵蚀步骤产生的间隙。

使用相同内核进行扩张后的FYI侵蚀称为开放。

代码将是这样的

 int erosion_size = 30; // adjust with you application Mat erode_element = getStructuringElement( MORPH_ELLIPSE, Size( 2*erosion_size + 1, 2*erosion_size+1 ), Point( erosion_size, erosion_size ) ); erode( binary_img, binary_img, erode_element ); dilate( binary_img, binary_img, erode_element ); 

这不是一种快速的方法,但在某些情况下可能有用。 OpencCV 3.0中有一个新function – connectedComponentsWithStats。 有了它,我们可以获得连接组件的区域,并消除不必要的。 因此,我们可以轻松地删除带孔的圆,使用与实心圆相同的边界框。