C# 从Image.Net中排除小块像素

C# 从Image.Net中排除小块像素,c#,opencv,image-processing,aforge,C#,Opencv,Image Processing,Aforge,我有带白线的黑色图像。是否可以排除小于特定数字的像素块?例如:将由少于10个像素组成的像素块的颜色从白色更改为黑色。 原始图像: 输出上的图像(删除小面积的白色像素): 现在我用AgFoeFrand库为C语言工作,但是C++的解决方法也被接受了(例如,开放的CV)。同时,我们也非常感谢您对如何调用此功能的提示。不用担心您的细节,它看起来确实非常简单 使用32位位图,并使用锁位获取扫描线和对阵列的直接指针访问 用2个循环扫描每个像素 每次你找到一个与你的目标颜色相匹配的颜色时,都要左右上下扫

我有带白线的黑色图像。是否可以排除小于特定数字的像素块?例如:将由少于10个像素组成的像素块的颜色从白色更改为黑色。 原始图像:

输出上的图像(删除小面积的白色像素):


现在我用AgFoeFrand库为C语言工作,但是C++的解决方法也被接受了(例如,开放的CV)。同时,我们也非常感谢您对如何调用此功能的提示。

不用担心您的细节,它看起来确实非常简单

  • 使用32位位图,并使用锁位获取扫描线和对阵列的直接指针访问
  • 用2个循环扫描每个像素
    • 每次你找到一个与你的目标颜色相匹配的颜色时,都要左右上下扫描(X)个像素来确定它是否符合你的要求
    • 如果有,请保留像素,如果没有,请更改它
    • 如果你想要更快的速度,你可以在一个并行的工作负载中处理这一切,你也可以用掩码数组做更多的事情来节省你研究死路的时间(只是一个想法)
  • 注意,显然你可以把它弄聪明一点

    Exmaple

    // lock the array for direct access
    var bitmapData = bitmap.LockBits(Bounds, ImageLockMode.ReadWrite, Bitmap.PixelFormat);
    // get the pointer
    var  scan0Ptr = (int*)_bitmapData.Scan0;
    // get the stride
    var  stride = _bitmapData.Stride / BytesPerPixel;
    
    // local method
    void Workload(Rectangle bounds)
    {
       // this is if synchronous, Bounds is just the full image rectangle
       var rect = bounds ?? Bounds; 
       var white = Color.White.ToArgb();
       var black = Color.Black.ToArgb();
    
       // scan all x
       for (var x = rect.Left; x < rect.Right; x++)
       {
          var pX = scan0Ptr + x;
    
          // scan all y
          for (var y = rect.Top; y < rect.Bottom; y++)
          {            
             if (*(pX + y * stride ) != white)
             {
                // this will turn it to monochrome
                // so add your threshold here, ie some more for loops
                //*(pX + y * Stride) = black;
             }
          }
       }
    }
    
    // unlock the bitmap
    bitmap.UnlockBits(_bitmapData);
    

    谢谢。也没有必要发布代码片段。但我真的很感激。明天我将练习这个。我实际上认为,已经有一些解决办法了。非常感谢谷歌的“区域开放”。我不知道OpenCV是否包含此过滤器,但它完全满足您的需要。@CrisLuengo非常感谢。它实际上对我的研究有所帮助。我从一个叫做BlobsFiltering的团体那里找到了解决这个问题的现成的解决方案,它解决了我的问题
    public static List<Rectangle> GetSubRects(this Rectangle source, int size)
    {
       var rects = new List<Rectangle>();
    
       for (var x = 0; x < size; x++)
       {
          var width = Convert.ToInt32(Math.Floor(source.Width / (double)size));
          var xCal = 0;
    
          if (x == size - 1)
          {
             xCal = source.Width - (width * size);
          }
          for (var y = 0; y < size; y++)
          {
    
             var height = Convert.ToInt32(Math.Floor(source.Height / (double)size));
             var yCal = 0;
    
             if (y == size - 1)
             {
                yCal = source.Height - (height * size) ;
             }
    
             rects.Add(new Rectangle(width * x, height * y, width+ xCal, height + yCal));
          }
       }
    
       return rects;
    }
    
    private static void DoWorkload(Rectangle bounds, ParallelOptions options, Action<Rectangle?> workload)
    {
       if (options == null)
       {
          workload(null);
       }
       else
       {
          var size = 5 // how many rects to work on, ie 5 x 5
          Parallel.ForEach(bounds.GetSubRects(size), options, rect => workload(rect));
       }
    }
    
    DoWorkload(Bounds, options, Workload);