【问题标题】:C# Normalizing RGB and creating a new imageC# 标准化 RGB 并创建新图像
【发布时间】:2013-10-23 14:47:06
【问题描述】:

我正在尝试创建一个程序来接受图像,递归遍历每个像素,标准化像素并重新创建一个看起来与原始图像相同但具有标准化像素的新图像。

    public void parseJpeg(String jpegPath)
    {
        var normalizedRed = 0.0;
        var normalizedGreen = 0.0;
        var normalizedBlue = 0.0;
        Bitmap normalizedImage = null;

        var image = new Bitmap(jpegPath);
        normalizedImage = new Bitmap(image.Width, image.Height);
        for (int x = 0; x < image.Width; ++x)
        {
            for (int y = 0; y < image.Height; ++y)
            {
                Color color = image.GetPixel(x, y);

                double exponent = 2;
                double redDouble = Convert.ToDouble(color.R);
                double blueDouble = Convert.ToDouble(color.B);
                double greenDouble = Convert.ToDouble(color.G);

                double redResult = Math.Pow(redDouble, exponent);
                double blueResult = Math.Pow(blueDouble, exponent);
                double greenResult = Math.Pow(greenDouble, exponent);

                double totalResult = redResult + blueResult + greenResult;                    

                normalizedRed = Convert.ToDouble(color.R) / Math.Sqrt(totalResult);
                normalizedGreen = Convert.ToDouble(color.G) / Math.Sqrt(totalResult);
                normalizedBlue = Convert.ToDouble(color.B) / Math.Sqrt(totalResult);


                Color newCol = Color.FromArgb(Convert.ToInt32(normalizedRed), Convert.ToInt32(normalizedGreen), Convert.ToInt32(normalizedBlue));

                normalizedImage.SetPixel(x, y, newCol);                                                                
            }                
        }

        normalizedImage.Save("C:\\Users\\username\\Desktop\\test1.jpeg"); 
        resultsViewBox.AppendText("Process completed.\n");
    }

使用上面的代码会产生所有黑色像素,我不明白为什么。当它归一化时,它设置 RGB = 1。归一化后,如何使用新的归一化值设置像素?

当我执行下面的代码时,我在预览中看到了一个黑色和蓝色的图像,但是当我打开文件时它是空白的。这比我之前得到的要好,之前都是黑色像素。但这仅适用于一张图像。所以我不确定它向前迈进了多少。

public void parseJpeg(String jpegPath)
    {
        Bitmap normalizedImage = null;           

        var image = new Bitmap(jpegPath);
        normalizedImage = new Bitmap(image.Width, image.Height);
        for (int x = 0; x < image.Width; ++x)
        {
            for (int y = 0; y < image.Height; ++y)
            {
                Color color = image.GetPixel(x, y);

                float norm = (float)System.Math.Sqrt(color.R * color.R + color.B * color.B + color.G * color.G);

                Color newCol = Color.FromArgb(Convert.ToInt32(norm));

                normalizedImage.SetPixel(x, y, newCol);
            }
        }

        normalizedImage.Save("C:\\Users\\username\\Desktop\\test1.jpeg");
        resultsViewBox.AppendText("Process completed.\n");
    }

我找到了我想要做的事情的代码: http://www.lukehorvat.com/blog/normalizing-image-brightness-in-csharp/

    public void parseJpeg(String jpegPath)
    {
        var image = new Bitmap(jpegPath);
        normalizedImage = new Bitmap(image.Width, image.Height);


        for (int x = 0; x < image.Width; ++x)
        {
            for (int y = 0; y < image.Height; ++y)
            {
                float pixelBrightness = image.GetPixel(x, y).GetBrightness();
                minBrightness = Math.Min(minBrightness, pixelBrightness);
                maxBrightness = Math.Max(maxBrightness, pixelBrightness);
            }
        }

        for (int x = 0; x < image.Width; x++)
        {
            for (int y = 0; y < image.Height; y++)
            {
                Color pixelColor = image.GetPixel(x, y);
                float normalizedPixelBrightness = (pixelColor.GetBrightness() - minBrightness) / (maxBrightness - minBrightness);
                Color normalizedPixelColor = ColorConverter.ColorFromAhsb(pixelColor.A, pixelColor.GetHue(), pixelColor.GetSaturation(), normalizedPixelBrightness);

                normalizedImage.SetPixel(x, y, normalizedPixelColor);
            }
        }

        normalizedImage.Save("C:\\Users\\username\\Desktop\\test1.jpeg");
        resultsViewBox.AppendText("Process completed.\n");
    }

【问题讨论】:

  • 我还没有通读所有的代码,但是你不需要用字符串解析来做所有这些体操。 GetPixel 返回一个Color 对象,该对象具有R、G 和B 属性。
  • 我不知道你的代码是从哪里得到的,但字符串的使用只会让我的脑细胞变得混乱。如果您想要像素操作,您应该将数据转换为字节/整数数组,具体取决于分辨率。看看this 和this。
  • 是的,请使用R、G、B 属性,但更重要的是,您是否真的要为中的每个像素重写相同的图像test1.jpeg(仅设置一个像素)原始文件?想想看,如果输入是800x600,你会重写test1.jpeg 480,000次。
  • @acfrancis:希望他没有使用 SSD!

标签: c# image rgb brightness normalizing


【解决方案1】:

您正在创建一个新的位图并为图像中的每个像素保存文件。移动

normalizedImage = new Bitmap(image.Width, image.Height);

循环之前的行,以及

normalizedImage.Save("C:\\Users\\username\\Desktop\\test1.jpeg");

循环之后的行。

您的标准化算法似乎不正确。假设你的原始颜色是红色 (255,0,0) 那么你的 totalResult 将是 65025,你的 normalizedRed 将是 255/sqrt(65025),即 1,给你一个新的标准化颜色 (1 ,0,0),它本质上是黑色的。

【讨论】:

  • @user2216791 请不要编辑其他人的答案。如果您认为答案不正确,请在答案下方留言。他们会解决的。
  • @Win:不改变答案实质的编辑很好。这仅将路径更正为上述问题中所写的内容。这就是每个人都可以使用编辑按钮的原因。
  • 我知道标准化算法不对,但我不知道该怎么做。有什么建议吗?
【解决方案2】:

请注意,如果您在外观之外定义所有双精度,然后在循环中分配它们,而不是在每次迭代中定义和删除 8 个双精度中的每一个,您的代码将运行得更快一些

【讨论】:

    【解决方案3】:

    您应该使用亮度或亮度因子来实现标准化,而不是弄乱颜色。这是一个可以帮助您的已回答问题的链接。您可以将每个 RGB 像素转换为 HSL 并计算 L 因子:

    How do I normalize an image?

    您分享的代码实际上是 HSL 操作的精简版。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-12
      • 1970-01-01
      • 1970-01-01
      • 2020-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多