I am currently trying to convert colors between RGB (red, green, blue) color space and Lαβ color space, Based on the details in the this paper.
My difficulties are in reversing the conversion process. When the result is not as same as initial RGB Mat. I think I missing something in type castings between Mats but I can't tell what is it!
here is my code:
<!-- language: lang-cc -->
Mat DetectTrackFace::RGB2LAlphBeta(Mat &src)
{
Mat dest;
Mat L_AlphBeta(src.rows, src.cols, CV_32FC3);
//cvtColor(src,dest,CV_BGR2XYZ);
float X,Y,Z,L,M,S,_L,Alph,Beta;
int R,G,B;
for(int i = 0; i < src.rows; i++)
{
for(int j = 0; j < src.cols; j++)
{
B = src.at<Vec3b>(i, j)[0];
G = src.at<Vec3b>(i, j)[1];
R = src.at<Vec3b>(i, j)[2];
X = ( 0.4124 * R ) + ( 0.3576 * G ) + ( 0.1805 * B);
Y = ( 0.2126 * R ) + ( 0.7152 * G ) + ( 0.0722 * B);
Z = ( 0.0193 * R ) + ( 0.1192 * G ) + ( 0.9505 * B);
L = (0.3897 * X) + (0.6890 * Y) + (-0.0787 * Z);
M = (-0.2298 * X) + (1.1834* Y) + (0.0464 * Z);
S = (0.0000 * X) + (0.0000 * Y) + (1.0000 * Z);
//for handling log
if(L == 0.0000) L=1.0000;
if(M == 0.0000) M = 1.0000;
if( S == 0.0000) S = 1.0000;
//LMS to Lab
_L = (1.0 / sqrt(3.0)) *((1.0000 * log10(L)) + (1.0000 * log10(M)) + (1.0000 * log10(S)));
Alph =(1.0 / sqrt(6.0)) * ((1.0000 * log10(L)) + (1.0000 * log10(M)) + (-2.0000 * log10(S)));
Beta = (1.0 / sqrt(2.0)) * ((1.0000 * log10(L)) + (-1.0000 * log10(M)) + (-0.0000 * log10(S)));
L_AlphBeta.at<Vec3f>(i, j)[0] = _L;
L_AlphBeta.at<Vec3f>(i, j)[1] = Alph;
L_AlphBeta.at<Vec3f>(i, j)[2] = Beta;
}
}
return L_AlphBeta;
}
Mat DetectTrackFace::LAlphBeta2RGB(Mat &src)
{
Mat XYZ(src.rows, src.cols, src.type());
Mat BGR(src.rows, src.cols, CV_8UC3);
float X,Y,Z,L,M,S,_L,Alph,Beta, B,G,R;
for(int i = 0; i < src.rows; i++)
{
for(int j = 0; j < src.cols; j++)
{
_L = src.at<Vec3f>(i, j)[0]*1.7321;
Alph = src.at<Vec3f>(i, j)[1]*2.4495;
Beta = src.at<Vec3f>(i, j)[2]*1.4142;
/*Inv_Transform_logLMS2lab =
0.33333 0.16667 0.50000
0.33333 0.16667 -0.50000
0.33333 -0.33333 0.00000*/
L = (0.33333*_L) + (0.16667 * Alph) + (0.50000 * Beta);
M = (0.33333 * _L) + (0.16667 * Alph) + (-0.50000 * Beta);
S = (0.33333 * _L) + (-0.33333 * Alph) + (0.00000* Beta);
L = pow(10 , L);
if(L == 1) L=0;
M = pow(10 , M);
if(M == 1) M=0;
S = pow(10 , S);
if(S == 1) S=0;
/*Inv_Transform_XYZ2LMS
1.91024 -1.11218 0.20194
0.37094 0.62905 0.00001
0.00000 0.00000 1.00000*/
X = (1.91024 *L ) + (-1.11218 * M ) +(0.20194 * S);
Y = (0.37094 * L ) + (0.62905 * M ) +(0.00001 * S);
Z = (0.00000 * L) + (0.00000 * M ) +(1.00000 * S);
/*Inv_Transform_RGB2XYZ
3.240625 -1.537208 -0.498629
-0.968931 1.875756 0.041518
0.055710 -0.204021 1.056996*/
R = ( 3.240625 * X) + ( -1.537208 * Y) + ( -0.498629 * Z);
G = ( -0.968931 * X) + ( 1.875756 * Y) + ( 0.041518 * Z);
B = ( 0.055710 * X) + ( -0.204021 * Y) + ( 1.056996 * Z);
if(R>255) R = 255;
if(G>255) G = 255;
if(B>255) B = 255;
if(R<0) R = 0;
if(G<0) G = 0;
if(B<0) B = 0;
if(R > 255 || G > 255 || B > 255 || R < 0 || G < 0 || B<0)
cout<<"R = "<<R<<" G = "<<G <<" B = "<<B<<endl;
BGR.at<Vec3b>(i, j)[0] = (uchar)B;
BGR.at<Vec3b>(i, j)[1] = (uchar)G;
BGR.at<Vec3b>(i, j)[2] = (uchar)R;
}
}
//normalize(BGR,BGR, 255, 0, NORM_MINMAX, CV_8UC3 );
return BGR;
}