Question

I am writing a small program to convert an OpenInventor file to a PCD one. To do so I have two files in input, namely the OpenInventor file and a JPEG image. The texture coordinates are float values between 0.0 and 1.0.

I use OpenCV to extract the RGB value and return it in decimal format, but the following function does not seem to work properly...

float get_color(cv::Mat img, float x, float y) {

    int i = x*img.cols;
    int j = y*img.rows;

    unsigned char R = img.ptr<unsigned char>(j)[3*i];
    unsigned char G = img.ptr<unsigned char>(j)[3*i+1];
    unsigned char B = img.ptr<unsigned char>(j)[3*i+2];

    return  R*pow(16,4) +
            G*pow(16,2) +
            B;
}

I load the image with

 cv::imread("filename.jpg", CV_LOAD_IMAGE_COLOR).
Was it helpful?

Solution 2

I found the answer to my own question in a comment found in the PCL's header "point_types.hpp" (PCL version: 1.5.1):

Due to historical reasons (PCL was first developed as a ROS package), the RGB information is packed into an integer and casted to a float. This is something we wish to remove in the near future, but in the meantime, the following code snippet should help you pack and unpack RGB colors in your PointXYZRGB structure:

uint8_t r = 255, g = 0, b = 0;
uint32_t rgb = ((uint32_t)r << 16 | (uint32_t)g << 8 | (uint32_t)b);
p.rgb = *reinterpret_cast<float*>(&rgb);

After refactoring and few other bug fixes, the function has become:

float get_color(cv::Mat img, float s, float t){

        int j = (1.0 - s)*(float)img.cols;
        int i = (1.0 - t)*(float)img.rows;

        uint8_t R = img.at<cv::Vec3b>(i,j)[2];
        uint8_t G = img.at<cv::Vec3b>(i,j)[1];
        uint8_t B = img.at<cv::Vec3b>(i,j)[0];

        uint32_t rgb_32 = ((uint32_t)R << 16 | (uint32_t)G << 8 | (uint32_t)B);

        return *reinterpret_cast<float*>(&rgb_32);
}

OTHER TIPS

Do you mean to return it as a 32-bit integer?

unsigned int get_color(cv::Mat img, float x, float y) 
{

    int i = x*img.cols;
    int j = y*img.rows;

    unsigned char R = img.ptr<unsigned char>(j)[3*i];
    unsigned char G = img.ptr<unsigned char>(j)[3*i+1];
    unsigned char B = img.ptr<unsigned char>(j)[3*i+2];

    return  (R << 16) |
            (G << 8) |
            B;
}

Or perhaps you want to return it as floats in which case you need to do the following

struct FloatColour
{
    float r;
    float g;
    float b;
};

float get_color(cv::Mat img, float x, float y) 
{

    int i = x*img.cols;
    int j = y*img.rows;

    unsigned char R = img.ptr<unsigned char>(j)[3*i];
    unsigned char G = img.ptr<unsigned char>(j)[3*i+1];
    unsigned char B = img.ptr<unsigned char>(j)[3*i+2];

    FloatColour retCol;
    retCol.r = R / 255.0f;
    retCol.g = G / 255.0f;
    retCol.b = B / 255.0f;
    return retCol;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top