我偶然发现了这个youtube视频http://www.youtube.com/watch?v=Ha5LficiSJM,它演示了使用AForge.NET框架进行颜色检测的人。我想复制作者所做的但我不知道如何进行图像处理。
似乎AForge.NET框架允许您从Bitmap格式的视频源下拉图像。我的问题是,有人能指出我的方向或提供一些指导如何询问Bitmap对象,以找到其中的特定颜色? (例如 - 如果图像中有“红色”或“紫色”持续X秒,我想提出一个事件'ColorDetected'或者左右......)
有没有人对从哪里开始有任何建议?
谢谢,
-R
编辑:我是否需要遍历整个Bitmap对象并询问每个像素的颜色?像这样:http://msdn.microsoft.com/en-us/library/system.drawing.bitmap.getpixel.aspx
答案 0 :(得分:15)
好吧,你总是可以使用GDI +方法。
Bitmap b = new Bitmap( "some path" );
Color x = b.GetPixel( x, y );
然而,GetPixel实际上非常慢。首先尝试这种方式,但如果您需要扫描许多相对较大的图像,它可能不适合您。在这种情况下,使用LockBits获取指向连续内存块的指针。然后你可以快速遍历图像,但你必须知道如何操作指针,尽管它并不是非常复杂。
编辑:使用LockBits查看每个像素:
Bitmap b = new Bitmap( "some path" );
BitmapData data = b.LockBits( new Rectangle( 0, 0, b.Width, b.Height ),
ImageLockMode.ReadOnly, b.PixelFormat ); // make sure you check the pixel format as you will be looking directly at memory
unsafe
{
// example assumes 24bpp image. You need to verify your pixel depth
// loop by row for better data locality
for( int y = 0; y < data.Height; ++y )
{
byte* pRow = (byte*)data.Scan0 + y * data.Stride;
for( int x = 0; x < data.Width; ++x )
{
// windows stores images in BGR pixel order
byte r = pRow[2];
byte g = pRow[1];
byte b = pRow[0];
// next pixel in the row
pRow += 3;
}
}
}
b.UnlockBits(data);
如果您的图像在最后填充,您可以使用BitmapData.Stride属性到达每个新行的开头(否则您将读取一些垃圾并且您的偏移将会变得棘手)。
答案 1 :(得分:5)
除了Ed Swangren对LockBits
的回答之外,您还可以避免使用指针。如果您正在使用WPF(或有权访问),您可以执行以下操作:
var bitmap = new BitmapImage(uri);
//Pixel array
byte[] pixels = new byte[width * height * 4]; //account for stride if necessary
bitmap.CopyPixels(..size, pixels, fullStride, 0);
现在,您可以使用pixels
进行常规阵列扫描而不使用指针。这个片段已有几年历史了,我开发了自己的AmbiLight解决方案,因此它可以非常快。同样,这已经有几年了,所以像WriteableBitmap
等新类可能会更好,避免使用数组副本。在我最初的解决方案中,我使用了指针,但是当我发现没有必要切换时。