find a color in an image in c#

后端 未结 2 1032
轮回少年
轮回少年 2020-12-01 17:37

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 lik

相关标签:
2条回答
  • 2020-12-01 17:49

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

    0 讨论(0)
  • 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.

    0 讨论(0)
提交回复
热议问题