Ask Your Question
2

OpenCV 3.0 CLAHE with 16bit images

asked 2015-02-11 08:46:31 -0600

gghelli gravatar image

Hello, I'm trying to use the openCV CLAHE implementation on 16 bits medical images and the results are not what I expected, it looks like the algorithm overlflows, resulting in a very dark image. If I convert the original image to CV_8U using cv::Mat:: convertTo() with an alpha value = 1.0 / (1 << (BitsStored - 8)), this is because images are really 10 or 12 bit unsigned int images, the result is correct and what I expect, see the examples below.

Original image
image description

8 bits CLAHE
image description

16 bits CLAHE
image description

The code is very simpe

int main(int argc, char *argv[])  
{
   QApplication a(argc, argv);

   // Load DICOM Image
   DcmObject raw;
   if( !raw.load("rawimage.dcm") )
       qCritical(qPrintable(QString("Error loading rawimage.dcm: %1").arg(raw.errorString())));

   // Convert to cv::Mat, internally can covert to 8 bit if wanted
   cv::Mat mat = dcmImageToCvMat(DcmImage(raw));
   cv::imshow("GRAYSCALE", mat);

   cv::Ptr<cv::CLAHE> clahe = cv::createCLAHE(3.0, cv::Size(8,8));
   cv::Mat dst;
   clahe->apply(mat, dst);
   cv::imshow("CLAHE", dst);

   cv::waitKey();
}

Below is the code I use to convert from DICOM to cv::Mat:, it uses a dicom toolkit written by me:

cv::Mat dcmImageToCvMat(const DcmImage &img, bool convertTo8Bits)
{
   cv::Mat mat;
   switch( img.pixelRepresentation() )
   {
   case DcmImage::PixelUInt8:
       mat = cv::Mat(img.rows(), img.columns(), CV_8U);
       break;
   case DcmImage::PixelInt8:
       mat = cv::Mat(img.rows(), img.columns(), CV_8S);
       break;
   case DcmImage::PixelUInt16:
       mat = cv::Mat(img.rows(), img.columns(), CV_16U);
       break;
   case DcmImage::PixelInt16:
       mat = cv::Mat(img.rows(), img.columns(), CV_16S);
       break;
   case DcmImage::PixelInt32:
   case DcmImage::PixelUInt32:
       mat =cv::Mat(img.rows(), img.columns(),  CV_32S);
       break;
   }

   // Get RAW Pixel data
   img.raw(mat.data, 0, 0, img.columns(), img.rows(), mat.step);

   // Invert if Photometric interpretation is MONOCHROME1 (white is 0)
   if( img.photometricInterpretation()==DcmImage::PmiMonochrome1 )
   {
       cv::Mat max(mat.size(), mat.type());
       max.setTo(img.maxPossibleValue());
       mat = max - mat;
   }

   // Convert to CV_16U with correct scaling of values
   switch( img.pixelRepresentation() )
   {
   case DcmImage::PixelInt8:
       mat.convertTo(mat, CV_8U, 1.0, -img.minPossibleValue());
       break;
   case DcmImage::PixelInt16:
       mat.convertTo(mat, CV_16U, 1.0, -img.minPossibleValue());
       break;
   case DcmImage::PixelInt32:
   case DcmImage::PixelUInt32:
       mat.convertTo(mat, CV_16U, 1.0 / double(1 << (img.bitsStored() - 16)), -img.minPossibleValue());
       break;
   }

   // Converts to 8 bits if wanted
   if( convertTo8Bits )
   {
       cv::Mat mat8;
       float scale = 1 << (img.bitsStored() - 8);
       float shift = img.isSigned() ? 127.0 : 0.0;
       cv::convertScaleAbs(mat, mat8, 1.0 / scale, shift);
       return mat8;
   }
   else
       return mat;
}

Thank you very much,

Gianluca Ghelli

edit retag flag offensive close merge delete

Comments

1

unfortunately, your images are all 8bit jpegs. can you at least upload your 16bit one somewhere (as png or tif), so folks here can actually try things with it ?

berak gravatar imageberak ( 2015-02-12 11:58:09 -0600 )edit

I'm sorry I didn't answer before. You can find a 16 bit png image at the following link:

link raw16.png

Thank you

gghelli gravatar imagegghelli ( 2015-02-22 04:01:56 -0600 )edit

did it have to be that huge ? ;(

berak gravatar imageberak ( 2015-02-22 09:06:02 -0600 )edit
1

:), that's the kind of image we use, for mammographies it's also more than double that size! If you want I can resize it.

gghelli gravatar imagegghelli ( 2015-02-23 03:36:48 -0600 )edit

2 answers

Sort by ยป oldest newest most voted
1

answered 2015-02-12 10:44:09 -0600

Guanta gravatar image

I think the problem has been fixed, see https://github.com/Itseez/opencv/pull/3033 .

edit flag offensive delete link more

Comments

No, the commit only enables CLAHE processing of CV_16UC1 images, but doesn't solve the problem I'm having.

gghelli gravatar imagegghelli ( 2015-02-22 04:06:21 -0600 )edit

Sorry to hear that! Maybe you could fill out an issue report at http://code.opencv.org/projects/openc... . Good luck!

Guanta gravatar imageGuanta ( 2015-02-22 11:38:39 -0600 )edit
2

Yes, I should file in a BUG. I reimplemented the algorithm copying it from Graphics Gems IV and ImageJ, they use a different approach, but it would be nice if I could use OpenCV. If I can in the future I will try to have a look at the OpenCV code which it's a little bit less straightforward having to deal also with OpenCL. Thanks!

gghelli gravatar imagegghelli ( 2015-02-23 03:40:17 -0600 )edit

Encountered the same problem, version 3.0.0 Is there any news regarding this?

blackpainter gravatar imageblackpainter ( 2015-10-19 05:09:31 -0600 )edit
0

answered 2016-10-24 05:39:12 -0600

pvt.peter gravatar image
edit flag offensive delete link more

Question Tools

2 followers

Stats

Asked: 2015-02-11 08:46:31 -0600

Seen: 7,967 times

Last updated: Oct 24 '16