Ask Your Question

Converting RGB into LMS model using C++ and OpenCV

asked 2018-01-27 08:18:27 -0600

raisa_ gravatar image

I'm trying to convert image with RGB colorspace into LMS model. The transformation matrix value I got from this paper. I read this Question : RGB to LMS color space conversion with OpenCV, we referred to the same paper and I already followed all the instructions in the answer.

To make sure my codes do well, I convert the original RGB into LMS, then convert the LMS back into RGB using inverse matrix of the first matrix, and see if the output matches the original image.

image description

But the output doesn't match the original image source. Here's my code :

void test(const Mat &original, Mat &pic, int rows, int cols)
    for (int i = 0; i < original.rows; i++) {
        for (int j = 0; j < original.cols; j++) {
        //RGB into LMS
  <Vec3b>(i, j)[0] =<Vec3b>(i, j)[0] * 1.4671 + 
                              <Vec3b>(i, j)[1] * 0.1843 + 
                              <Vec3b>(i, j)[2] * 0.003;   //B-->S
  <Vec3b>(i, j)[1] =<Vec3b>(i, j)[0] * 3.8671 + 
                              <Vec3b>(i, j)[1] * 27.1554 + 
                              <Vec3b>(i, j)[2] * 3.4557;   //G-->M
  <Vec3b>(i, j)[2] =<Vec3b>(i, j)[0] * 4.1194 + 
                              <Vec3b>(i, j)[1] * 43.5161 + 
                              <Vec3b>(i, j)[2] * 17.8824;  //R-->L

            //LMS back into RGB
  <Vec3b>(i, j)[0] =<Vec3b>(i, j)[0] * 0.6935 + 
                              <Vec3b>(i, j)[1] * -0.0041 + 
                              <Vec3b>(i, j)[2] * -0.0004;   //S-->B
 <Vec3b>(i, j)[1] =<Vec3b>(i, j)[0] * -0.1136 + 
                              <Vec3b>(i, j)[1] * 0.0540 + 
                              <Vec3b>(i, j)[2] * -0.0102;   //M-->G
 <Vec3b>(i, j)[2] =<Vec3b>(i, j)[0] * 0.1167 + 
                              <Vec3b>(i, j)[1] * -0.1305 + 
                              <Vec3b>(i, j)[2] * 0.0809;   //L-->R



int main(int argv, char** argc){
Mat original= imread("original.png", CV_LOAD_IMAGE_COLOR);
int rows = original.rows;
int cols = original.cols;

Mat pic(rows, cols, CV_8UC3);

test(original, pic, rows, cols);
imwrite("pic.png", pic);

Any suggestion ? Any help will be appreciated.

edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted

answered 2018-01-29 03:02:22 -0600

updated 2018-01-29 03:10:03 -0600

Hi Please note that conversion from one color space to another color space is not always reversible. i.e You cannot expect to get back the original image after conversion.

Here is a Sample code for Transforming an Image using 3x3 Color Transformation Matrix. You have to find correct transformation matrix for your color Space.

Note: Please refrain from using loops in your code and try to use existing OpenCV functions as much as possible.

void imshow_RGB(string WindowName,Mat mSrc)
    Mat mSrc_BGR;
    cvtColor(mSrc, mSrc_BGR, CV_RGB2BGR);
    imshow(WindowName, mSrc_BGR);

int main(int argc, const char** argv)
    cv::Mat mSrc = cv::imread("C:\\Users\\Public\\Pictures\\Sample Pictures\\Koala.jpg", 1);
    cv::Mat mDst;
    if (mSrc.empty())
        cout << "Invalid input image";
        return 0;

    cvtColor(mSrc, mSrc, CV_BGR2RGB);
    imshow_RGB("Source Image", mSrc);

    Mat mRGB2LMS_Matrix= Mat::eye(3,3,CV_32FC1);
    Mat mLMS2RGB_Matrix = Mat::eye(3, 3, CV_32FC1);

    //Fill your 3x3 Transformation Matrix here!!
    /*mRGB2LMS_Matrix = (Mat_<float>(3, 3) << 17.8824, 43.5161, 4.1194,
                                        3.4557, 27.1554, 3.8671,
                                        0.0300, 0.1843, 1.4671);

mLMS2RGB_Matrix = (Mat_<float>(3, 3) << 0.0809, -0.1305, 0.1167,
                                        -0.0102, 0.0540, -0.1136,
                                        -0.0004, -0.0041, 0.6935);*/

    //Forward Transformation from RGB -> Destination Color Space
    transform(mSrc, mDst, mRGB2LMS_Matrix);
    imshow_RGB("Forward Transformation", mDst);

    //Inverse Transformation from Destination Color Space -> RGB Color Space 
    transform(mDst, mSrc, mLMS2RGB_Matrix);
    imshow_RGB("Inverse Transformation Image", mSrc);

    return 0;
edit flag offensive delete link more


Hi, thanks for the explanation and sample code ! Very helpful. Also about the reversible, I follow these steps according to this paper I mentioned before. In case it's not reversible, how would we know if the transformation is correct ? If you wouldn't mind.. any reference for that will be a huge help for me.

raisa_ gravatar imageraisa_ ( 2018-01-30 10:43:17 -0600 )edit

As I've mentioned before you cannot expect to get back the original image when you reduce the number of colors in it! So there is no way to verify it with only one image. Common practice is to use a color chart which has all the possible(as much as) colors and compare it with the Target Color Model. You can refer this answer if you want to know How to compare two colors.

Balaji R gravatar imageBalaji R ( 2018-01-30 22:42:44 -0600 )edit

Converting matrices are correct. This is a LINEAR transform so is reversible. In my opinion problems arises because here are used uchar data types instead of float data types. LMS value are out of uchar range and cannot be visualized without rescaling. Inverse transform then uses wrong values. Input matrix should be converted in CV_32FC3 type before all computations and then converted in CV_8UC3 type for visualization.

Guidot gravatar imageGuidot ( 2019-05-11 07:06:24 -0600 )edit

Question Tools

1 follower


Asked: 2018-01-27 08:18:27 -0600

Seen: 1,239 times

Last updated: Jan 29 '18