У меня возникли проблемы с преобразованием из RGB в LAB и обратно. Я пытаюсь поэкспериментировать с цветовым пространством LAB, но хочу убедиться, что смогу преобразовать его из RGB в XYZ в LAB и обратно.
Сначала все выглядело хорошо, но только если я использовал тестовое изображение Lena, как только я начал использовать другие изображения, я увидел, что синие и зеленые цвета были полностью отрезаны, и я не уверен, где именно ошибка.
Я проверял изображение с множеством цветов и после преобразования 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
}
Вы не показываете источник для CLAMP255, но я предполагаю, что он ограничивает значения от 0 до 255. Для вывода Lab это было бы совершенно неправильно, так как они используют другой диапазон; я знаю это a
а также b
опуститься ниже нуля.
Других решений пока нет …