# false coloring of grayscale image

Hello,

I have a grayscale image to which I want to apply false coloring.

Below is a chunk of my code where I loop through all rows and cols of my matrix (matProcessed). For each pixel value, I lookup the desired RGB values from the user's pre-defined lookup table, and then overwrite the pixel in matProcessed accordingly. This all works just fine, except that all underlying intensity information in the original grayscale image is lost when a range of intensity values is simply replaced with a color. I think what I need is more like what the hue/saturation/colorize function in Photoshop would do, where I can colorize a range of grayscale pixels while retaining the underlying variation in intensity of the grayscale values. So how do I do that?

   // I first convert to BGR to colorize:
cvtColor(matProcessed, matProcessed, CV_GRAY2BGR);

int iPxVal=0;
int index;
int R=0;
int G=0;
int B =0;
for(int i=0; i<matProcessed.rows; i++){
for(int j=0; j<matProcessed.cols; j++){
index = matProcessed.channels()*(matProcessed.cols*i + j);

// grab the grayscale pixel value:
iPxVal = matProcessed.data[index + 0];

// lookup user defined RGB value:
GetColorFromLUT(iPxVal, &R, &G, &B);

// R, G and B now hold my RGB values the user desires.

matProcessed.data[index + 0] = color.blue();
matProcessed.data[index + 1] = color.green();
matProcessed.data[index + 2] = color.red();

}
}


Thanks!

edit retag close merge delete

Sort by » oldest newest most voted

To transform a grayscale image to false color first I would recommend to copy it, i.e. cvtColor(matProcessed, matFalseColor, CV_GRAY2BGR); instead of cvtColor(matProcessed, matProcessed, CV_GRAY2BGR);

To apply a custom colormap you can use either a "manual" method like you described (btw, you have a bug: matProcessed.data[index+0]=B instead of color.blue()), or with the LUT function (http://docs.opencv.org/modules/core/doc/operations_on_arrays.html#lut).

To construct a lookup table (a vector of 256 RGB elements (CV_U8C3 or CV_U16C3)), you have to take some "basic" colors interpolate the values between to get a nice color palette.

Some examples (notation: index1 [R,G,B] -> index2 [R,G,B]->...):

• shades of blue: 0 [0,0,0] -> 255 [0,0,255].
• ice: 0 [0,0,0] -> 128 [0,0,255] -> 255 [255,255,255].
• fire: 0 [0,0,0] -> 85 [255,0,0]-> 170 [255,255,0] ->255 [255,255,255].

To get a color spectrum, build a HSV lookup table: 0 [0,0,0] ->255 [360,0,0], transform it to RGB (cvtColor) and apply it to the image.

more

That is essentially what I am doing (right?). I guess my question goes more to how to calculate the colormap. I know there is cv::applyColorMap and there are some predefined ones. As far as I can tell, I cannot define my own, and would still then have the question of how to calculate it.

In essence, my users may ask that all grayscale values between 90 and 150 should turn "blue" but how can I calculate the proper "shade of blue" per incoming grayscale pixel intensity? To simply make them all RGB(0,0,255) would lose the information about the grayscale intensity differences in the raw data.

( 2014-11-13 12:47:31 -0500 )edit

Okay, now I understand your question. To apply a custom colormap you can use either a "manual" method like you described (btw, you have a bug: matProcessed.data[index+0]=Binstead of color.blue()), or with the LUT function (http://docs.opencv.org/modules/core/doc/operations_on_arrays.html#lut).

To construct a lookup table, you have to take some "basic" colors interpolate the values between to get a nice color palette.

Some examples(index1 [R,G,B] -> index2 [R,G,B]->...):

• shades of blue: 0 [0,0,0] -> 255 [0,0,255].
• ice: 0 [0,0,0] -> 128 [0,0,255] -> 255 [255,255,255].
• fire: 0 [0,0,0] -> 85 [255,0,0]-> 170 [255,255,0] ->255 [255,255,255].

To get a color spectrum, build a HSV lookup table: 0 [0,0,0] ->255 [360,0,0], transform it to RGB (cvtColor) and apply it to the image.

( 2014-11-14 04:27:50 -0500 )edit

Thanks I think I understand. I tried another approach which seemed to do what I want though I'm not sure if it's "correct".

if I have 8bit gray, and create a new empty 24bit RGB, I can copy the entire 8bit gray into one of the BGR channels (say, R), leaving the others black, and that effectively colorizes the pixels in a range of red. Similar, if the user wants to make it, say, RGB(80,100,120) then I can set each of the RGB channels to the source grayscale intensity multiplied by (R/255) or (G/255) or (B/255) respectively. This seems to work visually. It does need to be a per-pixel operation though cause the color applies only to a user-defined range of grayscale intensities.

( 2014-11-14 07:13:45 -0500 )edit

I would advise to add this comment in the main body of your answer as an edit, it provides useful info and I'ld gladly give a +1 for that ;)

( 2014-11-14 07:27:57 -0500 )edit

I'm having a heck of a time doing so.. I try but then get an internal server error.. Is this site fully recovered from the recent hack?

Anyway, it is useful info, and what's more interesting is that a colleague and I went through the exercise of understanding and implementing the math to convert from gray through YCbCr colorspace

int r = (int) (Y + 1.40200 * (Cr)); int g = (int) (Y - 0.34414 * (Cb) - 0.71414 * (Cr)); int b = (int) (Y + 1.77200 * (Cb );

and visually the results were exactly the same as my approach described above which I stumbled upon in my experimenting and believed to be a complete hack. Now I'm even more curious!

( 2014-11-14 15:01:45 -0500 )edit

Answer updated based on the discussion....

( 2014-11-17 02:09:36 -0500 )edit

Official site

GitHub

Wiki

Documentation