Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Opencv color mapping with direct pixel access

Tags:

c++

opencv

I have a gray scale image that I want to display in color by mapping the gray scale values with a color palette (like colormap in Matlab).

I managed to do it by using OpenCV cvSet2D function, but I would like to access to the pixels directly for performance reasons.

But when I do that the image has strange colors. I tried to set the colors in different orders (RGB, BGR,…) but can’t seem to get around it.

There is my code:

    IplImage* temp = cvCreateImage( cvSize(img->width/scale,img->height/scale), IPL_DEPTH_8U, 3 );
for (int y=0; y<temp->height; y++)
{
    uchar* ptr1 = (uchar*) ( temp->imageData + y * temp->widthStep );
    uchar* ptr2 = (uchar*) ( img->imageData + y * img->widthStep );

    for (int x=0; x<temp->width; x++)
    {
        CvScalar v1;

        int intensity = (int)ptr2[x];
        int b=0, g=0, r=0;
        r = colormap[intensity][0];
        g = colormap[intensity][1];
        b = colormap[intensity][2];

        if (true)
        {
            ptr1[3*x]   = b;
            ptr1[3*x+1] = g;
            ptr1[3*x+2] = r;
        }
        else
        {
            v1.val[0] = r;
            v1.val[1] = g;
            v1.val[2] = b;
            cvSet2D(temp, y, x, v1);
        }
    }
}

Change the if (true) to if (false) for different pixel access.

The correct result is with cvSet2D:

enter code here

The wrong result with the direct memory access:

enter image description here

Thank you for your help

like image 983
david Avatar asked Jul 13 '11 23:07

david


1 Answers

I have done something similar for coloring depth maps from Microsoft Kinect Sensor. The code I used for converting a grayscale depth map into color image will work for what you are trying to do. You may require slight modifications as in my case the depth values were in the range 500 to 2000, and I had to rescale them.

The function for colouring a grayscale image into colour image is:

void colorizeDepth( const Mat& gray, Mat& rgb)
{
        double maxDisp= 255;
        float S=1.f;
        float V=1.f ;

        rgb.create( gray.size(), CV_8UC3 );
        rgb = Scalar::all(0);

    if( maxDisp < 1 )
            return;

    for( int y = 0; y < gray.rows; y++ )
        {
            for( int x = 0; x < gray.cols; x++ )
            {
                uchar d = gray.at<uchar>(y,x);
                unsigned int H = 255 - ((uchar)maxDisp - d) * 280/ (uchar)maxDisp;    
            unsigned int hi = (H/60) % 6;

            float f = H/60.f - H/60;
                float p = V * (1 - S);
                float q = V * (1 - f * S);
                float t = V * (1 - (1 - f) * S);

            Point3f res;

                if( hi == 0 ) //R = V,  G = t,  B = p
                    res = Point3f( p, t, V );
                if( hi == 1 ) // R = q, G = V,  B = p
                    res = Point3f( p, V, q );
                if( hi == 2 ) // R = p, G = V,  B = t
                    res = Point3f( t, V, p );
                if( hi == 3 ) // R = p, G = q,  B = V
                    res = Point3f( V, q, p );
                if( hi == 4 ) // R = t, G = p,  B = V
                    res = Point3f( V, p, t );
                if( hi == 5 ) // R = V, G = p,  B = q
                    res = Point3f( q, p, V );

                uchar b = (uchar)(std::max(0.f, std::min (res.x, 1.f)) * 255.f);
                uchar g = (uchar)(std::max(0.f, std::min (res.y, 1.f)) * 255.f);
                uchar r = (uchar)(std::max(0.f, std::min (res.z, 1.f)) * 255.f);

                rgb.at<Point3_<uchar> >(y,x) = Point3_<uchar>(b, g, r);     

        }
        }
}

For an input image which looks like this:

enter image description here

Output of this code is:

enter image description here

like image 120
masad Avatar answered Sep 30 '22 18:09

masad