c++opencvimage-processingrgbcielab

Accessing elements in a multi-channel OpenCV Mat


this is my first post on stackoverflow, so I hope to do everything right, sorry if I don't.

I'm writing code for a function to convert a single RGB value into CIE L*a*b* color space. The function is supposed to take a 3 floats array (RGB channels with values in [0-255]) and to give in output a 3 floats array with the L*a*b* values. To do so, I'm using the cvtColor function available with OpenCV.

As suggested on the openCV website I'm creating the Mat structures (needed by cvtColor) by contructor.

My problem is that, although I think the code runs properly and performs the conversion, I'm unable to get the values contained in the Mat structure back.

Here's my code:

float * rgb2lab(float rgb[3]) {
    // bring input in range [0,1]
    rgb[0] = rgb[0] / 255;
    rgb[1] = rgb[1] / 255;
    rgb[2] = rgb[2] / 255;

    // copy rgb in Mat data structure and check values
    cv::Mat rgb_m(1, 1, CV_32FC3, cv::Scalar(rgb[0], rgb[1], rgb[2]));
    std::cout << "rgb_m = " << std::endl << " " << rgb_m << std::endl;
    cv::Vec3f elem = rgb_m.at<cv::Vec3f>(1, 1);
    float R = elem[0];
    float G = elem[1];
    float B = elem[2];
    printf("RGB =\n [%f, %f, %f]\n", R, G, B);

    // create lab data structure and check values
    cv::Mat lab_m(1, 1, CV_32FC3, cv::Scalar(0, 0, 0));
    std::cout << "lab_m = " << std::endl << " " << lab_m << std::endl;

    // convert
    cv::cvtColor(rgb_m, lab_m, CV_RGB2Lab);

    // check lab value after conversion
    std::cout << "lab_m2 = " << std::endl << " " << lab_m << std::endl;
    cv::Vec3f elem2 = lab_m.at<cv::Vec3f>(1, 1);
    float l = elem2[0];
    float a = elem2[1];
    float b = elem2[2];
    printf("lab =\n [%f, %f, %f]\n", l, a, b);

    // generate the output and return
    static float lab[] = { l, a, b };
    return lab;
}

As you can see, I'm extracting all channels from the Mat structure by the at function and then accessing them individually from the vector. This is proposed as the solution in many places (one of them).

But if I run this code (input vector was {123,10,200}), on cout I correctly get the outputs of the Mat structures (from which I get the algorithm is converting correctly), but as you can see the extracted values are wrong:

rgb_m = 
 [0.48235294, 0.039215688, 0.78431374]
RGB =
 [0.000000, 0.000000, -5758185472.000000]
lab_m = 
 [0, 0, 0]
lab_m2 = 
 [35.198029, 70.120964, -71.303688]
lab =
 [0.000000, 0.000000, 4822177514157213323960797626368.000000]

Anyone have an idea of what I'm doing wrong?

Thank you so much for all your help!


Solution

  • The first element of a cv::Mat is always at (0, 0), so just correct cv::Vec3f elem = rgb_m.at<cv::Vec3f>(1, 1); by cv::Vec3f elem = rgb_m.at<cv::Vec3f>(0, 0); and cv::Vec3f elem2 = lab_m.at<cv::Vec3f>(1, 1); by cv::Vec3f elem2 = lab_m.at<cv::Vec3f>(0, 0);