OpenCV - 查找或访问形状轮廓,不被背景包围,仅由轮廓分离

3
我一直在尝试使用OpenCV的findContour(我想使用C++语法)在一个非常简单的背景中找到单个形状的轮廓。然而,它一直在将轮廓作为外轮廓而不是形状本身。我认为这是由于Canny产生的白色边缘没有使形状闭合。
情况A:形状位于图像边缘 (这不是实际输入图像,而是更简单的输入图像,以说明该问题。)
情况B:背景包围形状
以下是我使用的主要函数:
findContours( grayImage, contours, hierarchy, RETR_LIST,CHAIN_APPROX_SIMPLE);
approxPolyDP(Mat(contours.at(largestContourIndex)),poly,3,true);
drawContours(output, contours, largestContourIndex, RGB(250,0,100), -1, 8, hierarchy, 0, Point() );

编辑:跳过边缘检测可以得到我需要的轮廓,但我需要尽可能接近最佳的轮廓近似。

提前致谢。


我看到你在我的回答之后编辑了你的帖子。如果你留下一个评论解释一下我的回答是否有帮助,如果没有,为什么这种方法不起作用(即当你尝试时发生了什么),那就太好了。 - penelope
我之前尝试过你的方法和其他几种方法。我只是在犹豫是否要让这个问题变得复杂和令人沮丧。很快会回复和编辑。感谢您的帮助。 - leya
3个回答

1

你尝试过使用形态学操作吗?

如果你的基本问题是得到的轮廓在物体外部而不是内部,特别是如果你的物体由明显的、大多数规则的形状组成,那么形态学可能会有所帮助。

我知道OpenCV有实现膨胀腐蚀,以及开运算闭运算操作。一个非常简单的方法,可能适用于你的情况,就是稍微侵蚀一下形状(也许1-2-3次迭代),然后做你已经在做的事情。希望这样,你将得到侵蚀形状的外轮廓,实际上应该是原始形状的内轮廓。

我认为OpenCV实际上实现了更复杂的形态学,但像往常一样,先尝试简单的东西:D


我实际上对输入图像进行腐蚀和膨胀,并使用轨迹条来控制它们的内核。我知道你的方法可以让我消除靠近边缘的形状部分。但是,在找到其轮廓之前,我必须先进行边缘检测以改善轮廓的逼近。进行边缘检测仍会给我一个带有轮廓的黑色图像。基本上会有三组像素 - (1) 背景,(2) 白色轮廓和(3) 形状,这就带来了我的主要问题 - 为什么OpenCV没有将第三组像素封闭在轮廓中?谢谢! - leya

1

我觉得你要找的轮廓可能已经被检测到了,但是你没有使用它。相反,你正在使用最大的轮廓。尝试逐个绘制所有找到的轮廓,看看是否在其中。

如果不是,请尝试反转Canny图像并重复该过程。


这正是我所期望的,但我尝试逐个绘制轮廓并更改轮廓模式和轮廓方法(这些都是OpenCV的findContour函数的参数),我对初始阈值进行了实验,但形成的轮廓总是围绕轮廓汇集。我会尝试你的建议。谢谢。 - leya

0

我仍然没有找到无法获取形状轮廓的原因,但我找到了一个解决方法。在进行腐蚀和膨胀之后,我基本上必须在输入图像的最外层像素上绘制边框或矩形,以便背景包围形状,...

rectangle(input,Point(0,0),Point(input.cols-1,input.rows-1),Scalar(0,0,0),1,8,0);

... 因此,让Canny绘制一个封闭的形状轮廓并给我想要的形状轮廓。我仍在尝试成功地反转Canny的输出,就像@dvhamme建议的那样,但它仍然给我错误。如果有人指出如何正确获取或访问形状轮廓,那将更好,但感谢大家的帮助。


1
我重现了你的问题,反转Canny图像并没有帮助。然而,有效的方法是使用threshold()来分割对象,然后运行findContours()。轮廓检测器显然不适用于线检测之后,但在二进制分割图像上可以正常工作,无论对象是否接触边缘。 - dvhamme
感谢您的时间!我会记住在回到这个项目时尝试使用 threshold()。我一直在使用类似于 inRange(src_Mat, min, max, dst_Mat) 的方法,但自从那以后就没有再碰过它了。 - leya

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