RGB в LAB и обратно ошибка

0

У меня возникают проблемы с преобразованием из RGB в LAB и обратно. Я стараюсь изо всех сил экспериментировать с цветовым пространством LAB, но хочу, чтобы я смог преобразовать его из RGB в XYZ в LAB и обратно.

Сначала все получилось хорошо, но только если я использовал тестовое изображение Лены, как только я начал использовать другие изображения, я увидел, что блюз и зелень были полностью отрезаны, и я не уверен, где именно ошибка.

Я тестировал изображение со многими цветами и после преобразования RGB в LAB и обратно получил искаженные цвета.

Вот мой код:

{
    double fcolorspace = 255.0f;

    double* image1temp=new double[nWidth * nHeight * 4]; // this is our tempory buffer to hold image 1

    // convert to RGB to LAB
    for (int y = 0; y< nHeight; y++)
    {
        for (int x = 0; x< nWidth; x++)
        {
            int nIdx = x*4+y*4*nWidth;

            double red1;
            double green1;
            double blue1;

            double xyzX1;
            double xyzY1;
            double xyzZ1;

            double var_X1;
            double var_Y1;
            double var_Z1;

            double refX;
            double refY;
            double refZ;

            double var_X11;
            double var_Y12;
            double var_Z13;

            //read in image from array
            red1   = double(pBGRA_in1[nIdx + CHANNEL_R]) / fcolorspace;
            green1 = double(pBGRA_in1[nIdx + CHANNEL_G]) / fcolorspace;
            blue1  = double(pBGRA_in1[nIdx + CHANNEL_B]) / fcolorspace;

            //adjust gamma on image 1
            if (red1 > 0.04045f)
            {
                red1 = powf((red1 + 0.055f) / 1.055f, 2.4f);
            }
            else
            {
                red1 = red1 / 12.92f;
            }
            if (green1 > 0.04045f)
            {
                green1 = powf((green1 + 0.055f) / 1.055f, 2.4f);
            }
            else
            {
                green1 = green1 / 12.92f;
            }
            if (blue1 > 0.04045f)
            {
                blue1 = powf((blue1 + 0.055f) / 1.055f, 2.4f);
            }
            else
            {
                blue1 = blue1 / 12.92f;
            }

            //scale
            red1   = red1   * 100.0f;
            green1 = green1 * 100.0f;
            blue1  = blue1  * 100.0f;

            //first we will convert the RGB image to XYZ
            xyzX1 = (0.4124f * red1) + (0.3576f * green1) + (0.1805f * blue1);
            xyzY1 = (0.2126f * red1) + (0.7152f * green1) + (0.0722f * blue1);
            xyzZ1 = (0.0193f * red1) + (0.1192f * green1) + (0.9505f * blue1);

            //reference white
            refX = 95.047f; // Observer= 2°, Illuminant= D65
            refY = 100.000f;
            refZ = 108.883f;

            //adjust LAB to reference white
            var_X1 = xyzX1 / refX;
            var_Y1 = xyzY1 / refY;
            var_Z1 = xyzZ1 / refZ;

            //LAB Conversion
            if (var_X1 > 0.008856f)
            {
                var_X11 = powf(var_X1 , 1.0f/3.0f);
            }
            else
            {
                var_X11 = (7.787f * var_X1) + (16.0f/116.0f);
            }

            if (var_Y1 > 0.008856f)
            {
                var_Y12 = powf(var_Y1 , 1.0f/3.0f);
            }
            else
            {
                var_Y12 = (7.787f * var_Y1) + (16.0f/116.0f);
            }

            if (var_Z1 > 0.008856f)
            {
                var_Z13 = powf(var_Z1 , 1.0f/3.0f);
            }
            else
            {
                var_Z13 = (7.787f * var_Z1) + (16.0f/116.0f);
            }

            //adjust LAB scale
            double cieL1 = (116.0f * var_Y12) - 16.0f;
            double cieA1 = 500.0f * (var_X11 - var_Y12);
            double cieB1 = 200.0f * (var_Y12 - var_Z13);

            //we are now in the LAB colorspace
            f_outred   = CLAMP255(cieL1);
            f_outgreen = CLAMP255(cieA1);
            f_outblue  = CLAMP255(cieB1);

            //place LAB image in temp array
            image1temp[nIdx + CHANNEL_R] = int(f_outred);
            image1temp[nIdx + CHANNEL_G] = int(f_outgreen);
            image1temp[nIdx + CHANNEL_B] = int(f_outblue);
        }
    }

    //convert from LAB to XYZ
        for (int x = 0; x< nWidth; x++)
        {
            for (int y = 0; y< nHeight; y++)
            {
                int nIdx = x * 4 + y * 4 * nWidth;

                double refX;
                double refY;
                double refZ;

                double var_X;
                double var_Y;
                double var_Z;

                double cieX;
                double cieY;
                double cieZ;

                double red;
                double green;
                double blue;

                //reference white
                refX = 95.047f; // Observer= 2°, Illuminant= D65
                refY = 100.000f;
                refZ = 108.883f;

                double cieL = image1temp [nIdx + CHANNEL_R];
                double cieA = image1temp [nIdx + CHANNEL_G];
                double cieB = image1temp [nIdx + CHANNEL_B];

                var_Y = (cieL + 16.0f) / 116.0f;
                var_X = cieA / 500.0f + var_Y;
                var_Z = var_Y - cieB / 200.0f;

                if (powf(var_Y, 3.0f) > 0.008856)
                {
                    var_Y = powf(var_Y, 3.0f);
                }
                else
                {
                    var_Y = (var_Y - 16.0f / 116.0f) / 7.787f;
                }
                if (powf(var_X , 3.0f) > 0.008856f)
                {
                    var_X = powf(var_X, 3.0f);
                }
                else
                {
                    var_X = (var_X - 16.0f / 116.0f) / 7.787f;
                }
                if (powf(var_Z, 3.0f) > 0.008856)
                {
                    var_Z = powf(var_Z, 3.0f);
                }
                else
                {
                    var_Z = (var_Z - 16.0f / 116.0f) / 7.787f;
                }

                cieX = refX * var_X;
                cieY = refY * var_Y;
                cieZ = refZ * var_Z;

                var_X = cieX / 100.0f;
                var_Y = cieY / 100.0f;
                var_Z = cieZ / 100.0f;

                red   = var_X * 3.2406f  + var_Y * -1.5372f + var_Z * -0.4986f;
                green = var_X * -0.9689f + var_Y * 1.8758f  + var_Z * 0.0415f;
                blue  = var_X * 0.0557f  + var_Y * -0.2040f + var_Z * 1.0570f;

                if (red > 0.0031308f)
                {
                    red = 1.055f * powf(red , (1.0f / 2.4f)) - 0.055f;
                }
                else
                {
                    red = 12.92f * red;
                }
                if (green > 0.0031308f)
                {
                    green = 1.055f * powf(green , (1.0f / 2.4f)) - 0.055f;
                }
                else
                {
                    green = 12.92f * green;
                }
                if (blue > 0.0031308f)
                {
                    blue = 1.055f * powf(blue , (1.0f / 2.4f)) - 0.055f;
                }
                else
                {
                    blue = 12.92f * blue;
                }

                red = CLAMP255(red * fcolorspace);
                green = CLAMP255(green * fcolorspace);
                blue = CLAMP255(blue * fcolorspace);

                pBGRA_out[nIdx + CHANNEL_R] = red;
                pBGRA_out[nIdx + CHANNEL_G] = green;
                pBGRA_out[nIdx + CHANNEL_B] = blue;
            }
        }

    delete [] image1temp;//delete the array
    delete [] image2temp;//delete the array

}
  • 0
    Вы создали оптимизированную версию SSE?
Теги:
image-processing
image
color-space

1 ответ

1
Лучший ответ

Вы не показываете источник для CLAMP255, но я предполагаю, что он зажимает значения от 0 до 255. Для вывода Lab это было бы совершенно неправильно, поскольку они используют другой диапазон; Я знаю, что a и b идут ниже нуля.

  • 0
    Спасибо. Это именно то, что проблема была, как только я удалил CLAMP255 из формулы LAB, все работает отлично.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню