Updated by Alexander Shishkov about 13 years ago

The code in the Lab2RGB_f struct (in modules/imgproc/src/color.cpp) does not calculate the inverse of the RGB-LAB mapping equations described in the documentation. The following code snippet demonstrates the result of generating an BGR image, converting it to LAB, converting it back to BGR, and then writing the results to disk.

<pre>
const int sz=100;
const int szm=sz-1;
float pi2=2*3.1415f;
cv::Mat orig(sz,sz,CV_32FC3);

// Generate a pretty test image
for(int i=0; i<sz; i++) {
for(int j=0; j<sz; j++) {
float b=(1+cos((szm-i)*(szm-j)*pi2/(10*float(szm))))/2;
float g=(1+cos((szm-i)*j*pi2/(10*float(szm))))/2;
float r=(1+sin(i*j*pi2/(10*float(szm))))/2;

// The following lines aren't necessary, but just to prove that
// the BGR values all lie in [0,1]...
if(b<0) b=0; else if(b>1) b=1;
if(g<0) g=0; else if(g>1) g=1;
if(r<0) r=0; else if(r>1) r=1;
orig.at<cv::Vec3f>(i,j)=cv::Vec3f(b,g,r);
}
}

// Convert test image to LAB
cv::Mat lab;
cv::cvtColor(orig,lab,CV_BGR2Lab);
// Convert LAB image back to BGR
cv::Mat recons;
cv::cvtColor(lab,recons,CV_Lab2BGR);

// Write original test image
cv::Mat orig8u;
orig.convertTo(orig8u,CV_8U,255);
cv::imwrite("orig.tiff",orig8u);
cv::Mat recons8u;
// Write image converted back to RGB from LAB space
recons.convertTo(recons8u,CV_8U,255);
cv::imwrite("recons.tiff",recons8u);

</pre>

I have written my own code that correctly inverts the equations in the documentation, but I have not spent enough time studying the OpenCV [[OpenCV]] code to work out how to incorporate it. Nonetheless, here it is (it assumes that the template arguments are float or double):

<pre>
template<class S,class T>
void lab2rgb(
const S li,
const S ai,
const S bi,
T& ro,
T& go,
T& bo)
{
const S lThresh=0.008856*903.3;

S y, fy;
if(li<=lThresh) {
y=li/903.3;
fy=7.787*y+16.0/116.0;
} else {
fy=(li+16.0)/116.0;
y=fy*fy*fy;
}
S fxz[]={S(ai/500.0+fy),S(bi/-200.0+fy)};
S xzUnnormr2;
const S fThresh=7.787*0.008856+16.0/116.0;

for(int i=0; i<2; i++) {
S f=fxz[i];
if(f<=fThresh) {
xzUnnorm[i]=(f-16.0/116.0)/7.787;
} else {
xzUnnorm[i]=f*f*f;
}
}

S x=xzUnnormr0*0.950456, z=xzUnnormr1*1.088754;
ro=3.240479*x-1.53715*y-0.498535*z;
go=-0.969256*x+1.875991*y+0.041556*z;
bo=0.055648*x-0.204043*y+1.057311*z;
}
</pre>

Back