用OpenCV进行形状检测 - 轮廓近似

15

我正在编写一个用于形状检测的小应用程序。首先需要做的是在图像上找到最显著的形状。我从一些预处理开始,包括将图像转换为灰度图像、阈值处理和边缘检测。下面展示了这些操作前后的图像:

操作前

enter image description here

操作后

enter image description here

因此,您可以看到主要的形状已经可见(虽然有点分散),还有一些噪声(小树等)。我需要做的是提取出最显著的形状(最大的那个),在这种情况下它是一座塔。我想做的是使用OpenCV中的轮廓查找函数,然后以某种方式用多边形逼近找到的轮廓。然后我会(以某种方式)计算轮廓的面积并仅选择最大的那个。

到目前为止,我只能找到轮廓:

cvFindContours(crated,g_storage,&contours);

我知道有一种

cvApproxPoly

我使用了一个函数,但是无法获得有用的信息来描述这个函数的结果。请问是否有可能计算轮廓的面积或者用多边形逼近轮廓?也许你有更好的想法来提取只有最显著的形状?

4个回答

8

这里不需要进行边缘检测。只需将图像阈值化为二进制图像,然后在其上找到斑点(使用cvFindContours)。您可以对每个返回的CvSeq使用cvContourArea来找到其面积。


7
如果您的背景是可控的,我建议按照以下步骤进行操作(也被@damian建议):
  1. 二值化,即创建一张图像,其中背景=0,对象区域=1(或255)。之后,您将在图像上拥有几个白色区域。有几种方法可以做到这一点,但如果您的背景是可控的,则可以使用固定阈值。请注意,此时您已经去除了对象内部的噪声。在二进制图像中,您始终可以使用形态学开/闭来平滑对象。
  2. 使用cvFindContours查找所有对象:现在应该更容易了。
  3. 通过使用cvFloodFill将较小的轮廓填充为背景颜色。

作为二值化过程的补充。很难找到一个好阈值。我总是计算直方图并寻找“低点”。通常在那里,您会得到一个不错的阈值。 如果您使用JPEG,则此方法可能效果不佳。 - Arndt Bieberstein

5
你面临的主要问题是塔轮轮廓分散。从这些小片段中重新创建整个轮廓将很困难。优化你的边缘检测阶段(尝试使用cvAdaptiveThreshold),或者使用不同的方法(也许像物体分割)。
在将轮廓拼接成一个整体后,你可以像这样检查其面积:
CvSeq* convex_hull=cvConvexHull2( contour, storage, CV_CLOCKWISE, 2 );
CvSeq* quad=cvApproxPoly(convex_hull, sizeof(CvContour), storage, CV_POLY_APPROX_DP, cvContourPerimeter(contour)*0.02, 0);
float size=fabs(cvContourArea( quad,CV_WHOLE_SEQ,0 ));

您需要调整参数。它被用于检测矩形。


2
你可以使用形态学操作来抑制“轮廓噪声”(在你的情况下是膨胀)。但是你必须记住,形态学操作的可用性取决于当前任务。例如,如果你有两个靠得很近的对象,膨胀可以将它们中的一个变为一个对象。

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