# Improve contrast of a 16U image

Hello, I'm very new to OpenCV. My question is: I need to enhance contrast of an IR image. I tried to use the cvEqualizeHist C function and the equalizeHist C++ function, but I understood they both work on 8 bit data, whilst my pixel data (one channel) are 16 bit (CV_16UC1). Is it possible to improve contrast in my image in some other way? Thanks a lot Andrea

Update: Thanks a lot, I followed the suggestion but still I've some problems. The source matrix had all values in a very small interval (so the results was an almost gray image). I expected that after applying the normalize function, the values were scaled between the min and max, but the result was similar to the source matrix: the values are still in a very small interval (shifted at a higher value respect the original matrix); the result is a similar image but a little bit brighter. Where am I wrong?

edit retag close merge delete

Sort by » oldest newest most voted

If I am not mistaken image normalization in OpenCV is not limited to 8 bit data. See its description here. In your case call to function should look like:

normalize(src_image, dst_image, 0, 65535, NORM_MINMAX);


Anyway, if you are trying to improve contrast of image first try normalization and only if this is not working try equalization. Normalization is faster and less destructive.

more

It's worth noting that equalizeHist() takes advantage of the limited char resolution and greatly improves the processing time. normalize() does the same thing on any image depth, but it's significantly slower.

( 2012-10-16 01:00:51 -0500 )edit

Thanks a lot, I followed the suggestion but still I've some problems. The source matrix had all values in a very small interval (so the results was an almost gray image). I expected that after applying the normalize function, the values were scaled between the min and max, but the result was similar to the source matrix: the values are still in a very small interval (shifted at a higher value respect the original matrix); the result is a similar image but a little bit brighter.
Where am I wrong?

( 2012-10-16 02:30:42 -0500 )edit
1

I guess your original image is not in small interval but also have values near 0 or 65535. Thus normalization can't stretch it too much. Check borders of your image, because they are often set to zero by many cameras.

( 2012-10-16 04:20:35 -0500 )edit
1

I solved the problem providing a simple algorithm: most of the data where in a very narrow interval but very few pixels outside the interval, as you correctly supposed. I set two threshold, min and max, and for every pixel below min I set the value to zero, and for every pixel upper than max I set the value to max (just to increase the dynamic of image). After this process only pixel between min and max are present. After that, I scaled their values between 0 and 65535. I put also two sliders to set up min and max, and the results was really fantastic....For sure there is some automatic functio in openCv to do that....I wiil learn it in the future, but openCV is really superb. It allowed me with a minimum trainig to achieve a real valuable results

( 2012-10-16 10:13:39 -0500 )edit

If the image looks very grey, you could also try applying the equalizeHist on YUV image - Y channel, note that this will change the colours of the image but it might make it visually/computationally better (in some sense). A code snippet to try quickly (all _ptr are pointers to IplImage):

cvCvtColor( RGB_image_ptr, YUV_image_ptr, CV_RGB2YUV );
cvSplit( YUV_image_ptr, Ychannel_image_ptr, Uchannel_image_ptr, Vchannel_image_ptr, NULL);

cvEqualizeHist(Ychannel_image_ptr, Ychannel_image_ptr);

cvMerge( Ychannel_image_ptr, Uchannel_image_ptr, Vchannel_image_ptr, NULL, YUV_image_ptr);
cvCvtColor( YUV_image_ptr, RGB_image_ptr, CV_YUV2RGB );

more

Official site

GitHub

Wiki

Documentation