H.Neo
H.Neo

Reputation: 85

How to get color from specific area in an Image in C#

I am trying to get color from specific area in an Image. enter image description here

Assume that , this is image , and I want to get color inside image.(the result should be red of the above image) This color may be different position in image. Because I don't know exact position of color where it starting, so I can't get exact result.

Until now, I cropped image giving manually position of x and y, and then cropped image and I got average color of cropped image. But I know , this is not exact color.

What I tried :

private RgbDto GetRGBvalueCroppedImage(Image croppedImage)
        {
        var avgRgb = new RgbDto();
        var bm = new Bitmap(croppedImage);


        BitmapData srcData = bm.LockBits(
            new Rectangle(0, 0, bm.Width, bm.Height),
            ImageLockMode.ReadOnly,
            PixelFormat.Format32bppArgb);

        int stride = srcData.Stride;

        IntPtr Scan0 = srcData.Scan0;

        long[] totals = new long[] { 0, 0, 0 };

        int width = bm.Width;
        int height = bm.Height;

        unsafe
        {
            byte* p = (byte*)(void*)Scan0;

            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    for (int color = 0; color < 3; color++)
                    {
                        int idx = (y * stride) + x * 4 + color;

                        totals[color] += p[idx];
                    }
                }
            }
        }

        avgRgb.avgB = (int)totals[0] / (width * height);
        avgRgb.avgG = (int)totals[1] / (width * height);
        avgRgb.avgR = (int)totals[2] / (width * height);

        return avgRgb;
    }

How can I get exact position to crop? May be I can convert image to byte array, then I can find different color and take position of it and then crop. But I have no clue how do this.

Upvotes: 1

Views: 1619

Answers (2)

LPLN
LPLN

Reputation: 473

You can use something this extension method to get dominant color in a region of an image in case they are not all the same

public static Color GetDominantColor(this Bitmap bitmap, int startX, int startY, int width, int height) {

    var maxWidth = bitmap.Width;
    var maxHeight = bitmap.Height;

    //TODO: validate the region being requested

    //Used for tally
    int r = 0;
    int g = 0;
    int b = 0;
    int totalPixels = 0;

    for (int x = startX; x < (startX + width); x++) {
        for (int y = startY; y < (startY + height); y++) {
            Color c = bitmap.GetPixel(x, y);

            r += Convert.ToInt32(c.R);
            g += Convert.ToInt32(c.G);
            b += Convert.ToInt32(c.B);

            totalPixels++;
        }
    }

    r /= totalPixels;
    g /= totalPixels;
    b /= totalPixels;

    Color color = Color.FromArgb(255, (byte)r, (byte)g, (byte)b);

    return color;
}

You can then use it like

Color pixelColor = myBitmap.GetDominantColor(xPixel, yPixel, 5, 5); 

there is room for improvement, like using a Point and Size, or even a Rectangle

public static Color GetDominantColor(this Bitmap bitmap, Rectangle area) {
    return bitmap.GetDominantColor(area.X, area.Y, area.Width, area.Height);
}

and following this link: https://www.c-sharpcorner.com/UploadFile/0f68f2/color-detecting-in-an-image-in-C-Sharp/

Upvotes: 2

Youssef13
Youssef13

Reputation: 4944

If you want to get the image colors, you don't need to do any cropping at all. Just loop on image pixels and find the two different colors. (Assuming that you already know the image will have exactly 2 colors, as you said in comments). I've written a small function that will do that. However, I didn't test it in an IDE, so expect some small mistakes:

private static Color[] GetColors(Image image)
{
    var bmp = new Bitmap(image);
    var colors = new Color[2];
    colors[0] = bmp.GetPixel(0, 0);
    for (int i = 0; i < bmp.Width; i++)
    {
        for (int j = 0; j < bmp.Height; j++)
        {
            Color c = bmp.GetPixel(i, j);
            if (c == colors[0]) continue;
            colors[1] = c;
            return colors;
        }   
    }
    return colors;
}

Upvotes: 1

Related Questions