EmguCV C#:FindContours() 检测不同的形状

EmguCV C# : FindContours() to detect different shapes

我有这张图片:

我尝试做的是检测它的轮廓。因此,通过查看文档和网络上的一些代码,我做了这个:

Image<Gray, byte> image = receivedImage.Convert<Gray, byte>().ThresholdBinary(new Gray(80), new Gray(255));
        Emgu.CV.Util.VectorOfVectorOfPoint contours = new Emgu.CV.Util.VectorOfVectorOfPoint();
        Mat hier = new Mat();

        CvInvoke.FindContours(image, contours, hier, Emgu.CV.CvEnum.RetrType.External, Emgu.CV.CvEnum.ChainApproxMethod.ChainApproxSimple);

        CvInvoke.DrawContours(receivedImage, contours, 0, new MCvScalar(255, 0, 0), 2);

然后它检测到这个蓝色轮廓:

现在我想检测不同轮廓中的两个矩形。所以结果是这样的:

(用油漆制作)所以现在我想分别检测两个矩形,(蓝色和红色矩形将是两个不同的轮廓)。但我不知道该怎么做!

在此先感谢您的帮助! ;)

问题出在ThresholdBinary的进程中。正如我假设您理解的那样,此方法将 return 二值图像,其中所有高于或等于 threshold 参数的像素将被上拉至 maxValue 参数,以及所有低于该参数的像素,下拉到 0。因此,生成的图像将仅包含两个值(二进制),0maxValue。如果我们按照您的示例使用一些 assumed 灰度值:

Image<Gray, byte> image = receivedImage.Convert<Gray, byte>().ThresholdBinary(new Gray(80), new Gray(255));之后,你会产生:

这实际上是您传递给 CvInvoke.FindContours() 的图像,随后只找到最外面的轮廓。

如果您确实想继续 FindContours,您需要的是一种算法,该算法将 "bin" 或 "bandpass" 您的图像首先生成以下片段,每个片段用于转换为二进制,并独立检测轮廓。

我觉得您当前的示例可能过于简单化了问题,无法为您提供有关如何在此处实现该目标的解决方案。但是,请使用更真实的数据提出另一个问题,我很乐意提供一些建议。

或者寻找更复杂的边缘检测方法,例如 Canny 或 Sobel。这个视频可能是一个很好的起点:Edge Detection