【问题标题】:Fill the holes in emgu cv填补emgu cv中的漏洞
【发布时间】:2011-11-04 11:36:33
【问题描述】:

如何填补 emgu cv 中二进制图像中的漏洞? 在 Aforge.net 中使用 Fillholes 类很简单。

【问题讨论】:

    标签: c# emgucv


    【解决方案1】:

    认为这个问题有点老了,我想为这个问题提供一个替代解决方案。

    如果您使用以下方法,您可以获得与 Chris' 相同的结果而不会出现内存问题:

    private Image<Gray,byte> FillHoles(Image<Gray,byte> image)
        {
            var resultImage = image.CopyBlank();
            Gray gray = new Gray(255);
            using (var mem = new MemStorage())
            {
                for (var contour = image.FindContours(
                    CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, 
                    RETR_TYPE.CV_RETR_CCOMP, 
                    mem); contour!= null; contour = contour.HNext)
                {
                    resultImage.Draw(contour, gray, -1);
                }
            }
    
            return resultImage;
        }
    

    上述方法的好处是您可以选择性地填充符合您标准的孔。例如,您可能想要填充像素数(blob 内的黑色像素数)低于 50 的孔,等等。

    private Image<Gray,byte> FillHoles(Image<Gray,byte> image, int minArea, int maxArea)
        {
            var resultImage = image.CopyBlank();
            Gray gray = new Gray(255);
    
            using (var mem = new MemStorage())
            {
                for (var contour = image.FindContours(
                    CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, 
                    RETR_TYPE.CV_RETR_CCOMP, 
                    mem); contour!= null; contour = contour.HNext)
                {
                    if ( (contour.Area < maxArea) && (contour.Area > minArea) )
                        resultImage.Draw(contour, gray, -1);
                }
            }
    
            return resultImage;
        }
    

    【讨论】:

    • 我认为这是最好的答案。
    • 我也是。以前经常会导致 OutOfMemory 问题
    【解决方案2】:

    是的,有一种方法,但它基于 cvFloodFill 操作有点混乱。现在,这个算法的设计目的是用一种颜色填充一个区域,直到它达到类似于区域增长算法的边缘。要有效地使用它,您需要使用一些创造性的编码,但我警告您,此代码只是为了让您入门,它可能需要重构以加快速度。就目前而言,循环遍历小于 255 的每个像素应用 cvFloodFill 检查该区域的大小,然后如果它在某个区域以下,则将其填充。

    重要的是要注意,图像的副本是由原始图像制成的,以作为指针提供给 cvFloodFill 操作。如果提供了直接图像,那么您最终将得到一个白色图像。

    OpenFileDialog OpenFile = new OpenFileDialog();
    
    if (OpenFileDialog.ShowDialog() == DialogResult.OK)
    {
        Image<Bgr, byte> image = new Image<Bgr, byte>(OpenFile.FileName);
    
                for (int i = 0; i < image.Width; i++)
                {
                    for (int j = 0; j < image.Height; j++)
                    {
                        if (image.Data[j, i, 0] != 255)
                        {
                            Image<Bgr, byte> image_copy = image.Copy();
                            Image<Gray, byte> mask = new Image<Gray, byte>(image.Width + 2, image.Height + 2);
                            MCvConnectedComp comp = new MCvConnectedComp();
                            Point point1 = new Point(i, j);
                            //CvInvoke.cvFloodFill(
                            CvInvoke.cvFloodFill(image_copy.Ptr, point1, new MCvScalar(255, 255, 255, 255),
                            new MCvScalar(0, 0, 0),
                            new MCvScalar(0, 0, 0), out comp,
                            Emgu.CV.CvEnum.CONNECTIVITY.EIGHT_CONNECTED,
                            Emgu.CV.CvEnum.FLOODFILL_FLAG.DEFAULT, mask.Ptr);
                            if (comp.area < 10000)
                            {
                                image = image_copy.Copy();
                            }
                        }
                    }
                }
    }
    

    “new MCvScalar(0, 0, 0), new MCvScalar(0, 0, 0)”在这种情况下并不重要,因为您只是填写二进制图像的结果。您可以尝试使用其他设置,看看您可以实现什么结果。 "if (comp.area key 常量,要更改的是您要更改方法将填充的孔大小。

    这些是您可以期待的结果:

    原创

    结果

    这种方法的问题是它非常占用内存,它在 200x200 的图像上消耗了 6GB 的内存,当我尝试 200x300 时,它吃掉了我所有的 8GB 内存,并导致一切崩溃。除非你的大部分图像是白色的,并且你想填补微小的空白,否则你可以尽量减少应用我会避免的方法的位置。我建议您编写自己的类来检查不是 255 的每个像素并添加围绕它的像素数。然后,您可以记录不是 255 的每个像素的位置(在一个简单的列表中),如果您的计数低于阈值,则在您的图像中将这些位置设置为 255(通过迭代列表)。

    如果您不想编写自己的 Aforge FillHoles 类,我会坚持使用它,因为它是为此目的而设计的。

    干杯

    克里斯

    【讨论】:

      【解决方案3】:

      您可以使用 FillConvexPoly

      image.FillConvexPoly(externalContours.ToArray(), new Gray(255));
      

      【讨论】:

        猜你喜欢
        • 2010-12-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-03
        • 1970-01-01
        • 2017-11-22
        • 1970-01-01
        相关资源
        最近更新 更多