С# Нормализация RGB и создание нового изображения

Я пытаюсь создать программу, которая принимает изображение, рекурсивно проходит через каждый пиксель, нормализует пиксель и воссоздает НОВОЕ изображение, которое выглядит так же, как оригинал, но вместо этого имеет нормализованные пиксели.

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

person user2216791    schedule 23.10.2013    source источник
comment
Я не читал весь код, но вам не нужно проделывать всю эту гимнастику с разбором строк. GetPixel возвращает объект Color, который имеет свойства R, G и B.   -  person Adam Robinson    schedule 23.10.2013
comment
Я не знаю, откуда вы взяли свой код, но использование строк просто мешает клеткам моего мозга. Если вы хотите манипулировать пикселями, вы должны преобразовать свои данные в массив byte/int, в зависимости от разрешения. Взгляните на это и это.   -  person Andrei V    schedule 23.10.2013
comment
Да, пожалуйста, используйте свойства R, G, B, но, что более важно, вы действительно хотите переписать одно и то же изображение test1.jpeg (только с одним набором пикселей) для каждого пикселя в исходном файле? Подумайте об этом, если ввод 800x600, вы перепишете test1.jpeg 480 000 раз.   -  person acfrancis    schedule 23.10.2013
comment
@acfrancis: Будем надеяться, что он не использует SSD!   -  person Adam Robinson    schedule 23.10.2013


Ответы (3)


Вы создаете новое растровое изображение и сохраняете файл для каждого пикселя изображения. Переместите

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 ), который по существу черный.

person Golden Dragon    schedule 23.10.2013
comment
@user2216791 Пожалуйста, не редактируйте ответы других людей. Если вы считаете, что ответы неверны, напишите в комментариях под ответом. Они это исправят. - person Win; 23.10.2013
comment
@Win: Правки, которые не меняют сути ответа, в порядке. Этот только исправил путь, чтобы он был написан в вопросе выше. Вот почему кнопка редактирования есть у всех. - person Adam Robinson; 23.10.2013
comment
Я знаю, что алгоритм нормализации неверен, но я не знаю, что делать. Какие-либо предложения? - person user2216791; 24.10.2013

Как примечание, ваш код будет работать немного быстрее, если вы один раз определите все двойники вне внешнего вида, а затем назначите их внутри цикла, а не будете определять и удалять каждый из 8 двойников на каждой итерации.

person Jonathan    schedule 23.10.2013

Вместо того, чтобы возиться с цветами, вы должны использовать коэффициент яркости или яркости для достижения нормализации. Вот ссылка на уже отвеченный вопрос, который может вам помочь. вы можете преобразовать каждый пиксель RGB в HSL и уменьшить L-фактор:

Как нормализовать изображение?

Код, которым вы поделились, на самом деле является урезанной версией манипуляции с HSL.

person mathsRuinedme    schedule 13.11.2013