在c#中查找图像中的颜色

发布于 2024-09-24 18:45:14 字数 631 浏览 4 评论 0原文

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

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

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

谢谢,

-R。

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

I stumbled across this youtube video here http://www.youtube.com/watch?v=Ha5LficiSJM that demonstrates someone doing color detection using the AForge.NET framework. I'd like to duplicate what that author has done but I'm not sure how to do some image processing.

It would appear that the AForge.NET framework allows you to pull down from the video source the image in a Bitmap format. My questions is could anyone point me in the direction or provide some guidance on how to interrogate a Bitmap object to find specific colors in it? (for example - if there is 'Red' or 'Purple' in the image for X seconds, I'd like to raise an event 'ColorDetected' or so...)

Does anyone have any suggestions on where to start?

Thanks,

-R.

EDIT: Would I need to walk the entire Bitmap object and interrogate each pixel for the color? Like so: http://msdn.microsoft.com/en-us/library/system.drawing.bitmap.getpixel.aspx

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

李白 2024-10-01 18:45:14

好吧,您始终可以使用 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 属性到达每个新行的开头(否则您将读取一些垃圾,并且您的偏移量将变得混乱) 。

Well, you can always use the GDI+ method.

Bitmap b = new Bitmap( "some path" );
Color x = b.GetPixel( x, y );

However, GetPixel is actually pretty slow. Try it that way first, but if you need to scan many relatively large images it may not work for you. In that case, use LockBits to get a pointer to a contiguous memory chunk. You can then loop through the image quickly, but you have to know how to manipulate pointers, though it's not terribly complicated.

EDIT: Using LockBits to look at each pixel:

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);

If your images are padded at the end you can use the BitmapData.Stride property to get to the start of each new row (otherwise you will be reading some junk and your offsets will be screwy).

除了 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); 

现在您可以使用像素进行常规数组扫描,而无需指针。这段代码已有几年历史,来自我开发自己的 AmbiLight 解决方案的项目,因此速度非常快。同样,这已经有几年的历史了,因此像 WriteableBitmap 等新类可能会更好并且避免数组复制。在我最初的解决方案中,我使用了指针,但当我发现没有必要时,我就切换了。

In addition to Ed Swangren´s answer with LockBits you can avoid pointers all together. If you are using the WPF (or have access to) you can do something like this:

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); 

And now you can just do a regular array-scan with pixels without pointers. This snippet is a few years old and from a project where I developed my own AmbiLight solution so it can be pretty fast. Again, this is a few years old, so new classes like WriteableBitmap etc. may be better and avoid a array-copy. In my initially solution I used pointers, but when I figured out that it wasn't necessary I switched.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文