【问题标题】:How to get color from specific area in an Image in C#如何在C#中从图像中的特定区域获取颜色
【发布时间】:2019-12-09 21:57:05
【问题描述】:

我正在尝试从图像中的特定区域获取颜色。

假设,这是图像,我想得到图像内部的颜色。(结果应该是上图的红色)这个颜色可能在图像中的不同位置。因为我不知道颜色开始的确切位置,所以我无法得到准确的结果。

到目前为止,我裁剪图像,手动给出 x 和 y 的位置,然后裁剪图像,得到裁剪图像的平均颜色。但我知道,这不是确切的颜色。

我尝试了什么:

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

如何获得精确的裁剪位置?可能我可以将图像转换为字节数组,然后我可以找到不同的颜色并对其进行定位然后裁剪。但我不知道如何做到这一点。

【问题讨论】:

  • 你保证图片中正好有2种颜色吗?
  • 你能举个真实的例子吗?真的是单色图像和一个矩形区域吗?
  • 无法理解您想要达到的目标。你说“结果应该是上面图像的红色”,然后你问“我怎样才能得到精确的裁剪位置?”。所以... 你真正想要什么?你必须至少知道一些事情才能使用
  • 所有盒子都有“典型”颜色吗?或者它们也可以有不同的颜色?标签是否有平均尺寸范围?或者它们可以是图像的 0% 到 100% 的任何内容吗?

标签: c# image


【解决方案1】:

您可以使用这种扩展方法来获取图像区域中的主色,以防它们不完全相同

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

你可以像这样使用它

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

还有改进的余地,比如使用点和大小,甚至是矩形

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

并点击此链接: https://www.c-sharpcorner.com/UploadFile/0f68f2/color-detecting-in-an-image-in-C-Sharp/

【讨论】:

    【解决方案2】:

    如果您想获得图像颜色,则根本不需要进行任何裁剪。只需循环图像像素并找到两种不同的颜色。 (假设您已经知道图像将具有 2 种颜色,正如您在 cmets 中所说的那样)。我写了一个小函数来做到这一点。但是,我没有在 IDE 中对其进行测试,所以预计会出现一些小错误:

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

    【讨论】:

      猜你喜欢
      • 2012-02-06
      • 2015-12-14
      • 2021-04-30
      • 2012-03-25
      • 2015-12-15
      • 2020-08-07
      • 2020-07-01
      • 1970-01-01
      相关资源
      最近更新 更多