title: convert BGR to Lab without OpenCV
body: <p>With little experience in color spaces, I used the following code to convert BGR image (array of unsigned characters where each channel ranges from 0 to 255) to lab color space:</p>
  
  <pre><code>double F(double input) // function f(...), which is used for defining L, a and b changes within [4/29,1]
  {
      if (input &gt; 0.008856)
          return (pow(input, 0.333333333)); // maximum 1
      else
          return ((841/108)*input + 4/29);  //841/108 = 29*29/36*16
  }
  
  // RGB to XYZ
  void RGBtoXYZ(uchar R, uchar G, uchar B, double &amp;X, double &amp;Y, double &amp;Z)
  {
      // RGB Working Space: sRGB 
      // Reference White: D65
      X = 0.412453*R + 0.357580*G + 0.189423*B; // maximum value = 0.959456 * 255 = 244.66128
      Y = 0.212671*R + 0.715160*G + 0.072169*B; // maximum value = 1 * 255 = 255
      Z = 0.019334*R + 0.119193*G + 0.950227*B; //  maximum value = 1.088754 * 255 = 277.63227
  }
  
  // XYZ to CIELab
  void XYZtoLab(double X, double Y, double Z, double &amp;L, double &amp;a, double &amp;b)
  {
      const double Xo = 244.66128; // reference white
      const double Yo = 255.0;
      const double Zo = 277.63227;
      L = 116 * F(Y / Yo) - 16; // maximum L = 100
      a = 500 * (F(X / Xo) - F(Y / Yo)); // maximum 
      b = 200 * (F(Y / Yo) - F(Z / Zo));
  }
  
  // RGB to CIELab
  void RGBtoLab(double R, double G, double B, double &amp;L, double &amp;a, double &amp;b)
  {
      double X, Y, Z;
      RGBtoXYZ(R, G, B, X, Y, Z);
      XYZtoLab(X, Y, Z, L, a, b);
  }
  </code></pre>
  
  <p>I have re-converted the resulting lab image to BGR (using cvtcolor) to display it using OpenCV using the following code (I don't want to do the conversion using OpenCV, I have just used it to display the results. Basically I wanted to understand how color space conversion works):</p>
  
  <pre><code>// Lchannel, Achannel, Bchannel are arrays of type double
  cv::Mat temp64bitL(height, width, CV_64FC1, Lchannel);
  cv::Mat temp32bitL;
  temp64bitL.convertTo(temp32bitL, CV_32F);
  
  cv::Mat temp64bitA(height, width, CV_64FC1, Achannel);
  cv::Mat temp32bitA;
  temp64bitA.convertTo(temp32bitA, CV_32F);
  cv::Mat temp64bitB(height, width, CV_64FC1, Bchannel);
  cv::Mat temp32bitB;
  temp64bitB.convertTo(temp32bitB, CV_32F);
      cv::Mat chan[3] = {
      temp32bitL, temp32bitA, temp32bitB
  };
  cv::Mat merged;
  cv::merge(chan, 3, merged);
  cv::Mat BGRImage;
  cv::cvtColor(merged, BGRImage, CV_Lab2BGR, 3);
  </code></pre>
  
  <p>However, <a href="https://i.stack.imgur.com/MQlPq.jpg" rel="nofollow noreferrer">the computed image</a> is different from <a href="https://i.stack.imgur.com/L1IFm.jpg" rel="nofollow noreferrer">the original image</a>. is that due to a problem in the code?</p>