C# 从Image.Net中排除小块像素
我有带白线的黑色图像。是否可以排除小于特定数字的像素块?例如:将由少于10个像素组成的像素块的颜色从白色更改为黑色。 原始图像: 输出上的图像(删除小面积的白色像素):C# 从Image.Net中排除小块像素,c#,opencv,image-processing,aforge,C#,Opencv,Image Processing,Aforge,我有带白线的黑色图像。是否可以排除小于特定数字的像素块?例如:将由少于10个像素组成的像素块的颜色从白色更改为黑色。 原始图像: 输出上的图像(删除小面积的白色像素): 现在我用AgFoeFrand库为C语言工作,但是C++的解决方法也被接受了(例如,开放的CV)。同时,我们也非常感谢您对如何调用此功能的提示。不用担心您的细节,它看起来确实非常简单 使用32位位图,并使用锁位获取扫描线和对阵列的直接指针访问 用2个循环扫描每个像素 每次你找到一个与你的目标颜色相匹配的颜色时,都要左右上下扫
现在我用AgFoeFrand库为C语言工作,但是C++的解决方法也被接受了(例如,开放的CV)。同时,我们也非常感谢您对如何调用此功能的提示。不用担心您的细节,它看起来确实非常简单
- 每次你找到一个与你的目标颜色相匹配的颜色时,都要左右上下扫描(X)个像素来确定它是否符合你的要求
- 如果有,请保留像素,如果没有,请更改它
- 如果你想要更快的速度,你可以在一个并行的工作负载中处理这一切,你也可以用掩码数组做更多的事情来节省你研究死路的时间(只是一个想法)
// 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);