1

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.

H.Neo
  • 85
  • 1
  • 8
  • Do you guarantee that there are exactly 2 colors in the image ? – Youssef13 Dec 09 '19 at 13:26
  • 1
    Can you give a real-life example? Is it really a mono-chromatic image and one single rectangle area? – Fildor Dec 09 '19 at 13:27
  • @Youssef13 yes , I need inside color in the image. – H.Neo Dec 09 '19 at 13:27
  • 3
    Can't understand what you trying to achieve. You said "the result should be red of the above image" and then you asking for "How can I get exact position to crop?". So... What you really want? You must to know at least **something** to work with – picolino Dec 09 '19 at 13:28
  • I want to give real example, assume I have one box , on box there is label is different color. I scanned box, so my image is box. On that box I should find label and say this label color is red , blue etc.. – H.Neo Dec 09 '19 at 13:30
  • label on the box can be start any position which I do not know. If I know the position and size , then I crop the image and get exactly color of this label. – H.Neo Dec 09 '19 at 13:32
  • If that, you need to "scan" your source image pixel-by-pixel and collect/compare they for finding different colors. It wouldn't so hard if you guarantee that image has only two colors. – picolino Dec 09 '19 at 13:32
  • 1
    Do all boxes have a "typical" color? Or can they have different colors, too? Do labels have an average size-range? or can they be anything from 0 to 100% of image? – Fildor Dec 09 '19 at 13:43
  • How far apart are the possible label colors? – Fildor Dec 09 '19 at 13:53
  • 1
    [Find the rectangle area of image to Crop](https://stackoverflow.com/a/24594209/7444103) -- By difference: [How to find the difference between two images?](https://stackoverflow.com/a/26225153/7444103) -- [Black points recognition from a photo](https://stackoverflow.com/a/50282882/7444103). Many more answers. – Jimi Dec 09 '19 at 14:12

2 Answers2

2

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/

LPLN
  • 475
  • 1
  • 6
  • 20
1

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;
}
Youssef13
  • 3,836
  • 3
  • 24
  • 41