8

我在这里http://www.youtube.com/watch?v=Ha5LficiSJM偶然发现了这个 youtube 视频,该视频演示了有人使用 AForge.NET 框架进行颜色检测。我想复制那个作者所做的,但我不确定如何进行一些图像处理。

看起来 AForge.NET 框架允许您从视频源中提取位图格式的图像。我的问题是任何人都可以指出我的方向或提供一些关于如何询问位图对象以找到其中特定颜色的指导吗?(例如 - 如果图像中有“红色”或“紫色”持续 X 秒,我想引发一个事件“ColorDetected”左右......)

有人对从哪里开始有任何建议吗?

谢谢,

-R。

编辑:我需要遍历整个 Bitmap 对象并询问每个像素的颜色吗?像这样:http: //msdn.microsoft.com/en-us/library/system.drawing.bitmap.getpixel.aspx

4

2 回答 2

21

好吧,您总是可以使用 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 属性来获取每个新行的开头(否则您将读取一些垃圾并且您的偏移量会很糟糕)。

于 2010-09-25T19:41:21.470 回答
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 解决方案的项目,因此它可以非常快。同样,这已经有几年历史了,所以像WriteableBitmapetc. 这样的新类可能会更好并且避免数组复制。在我最初的解决方案中,我使用了指针,但是当我发现没有必要时,我切换了。

于 2010-09-25T19:54:56.650 回答