Ask Your Question
1

Result of CLAHE is different on 8 and 16 bit

asked 2016-10-21 08:28:35 -0600

pvt.peter gravatar image

updated 2017-03-21 04:21:10 -0600

Hi,

I have got a remark, problem with CLAHE algorithm on applying 8 bit and 16 bit grayscale image. I use opencv-master build. So if i applying CLAHE algorithm on 8 bit grayscale image (CV_8UC1), the result was very good.

But unfortunately i have to work with 16 bit grayscale images (CV_16UC1).


If i normalized and converted the source 16 bit grayscale image to 8 bit and after that executed CLAHE, the result was beautiful, you can see it in this picture: 2.

If i executed CLAHE on the source 16 bit grayscale image, and after it normalized and converted to 8 bit, the result was very weird. Little grids appeared on the image and it was very unnatural, you can see it in this picture: 3.

I tried to different parametrization on CLAHE, but the point was the same.

I attached different pictures of my problem:

  1. Original 16 bit image normalize to 8 bit [0, 255] and convert to 8 bit (CV_8UC1).
  2. Applying CLAHE algorithm with default parameters (ClipLimit(40.0) and TilesGridSize(Size(8, 8))) on the previous (1.) image.
  3. Applying CLAHE algorithm with default parameters on the original 16 bit image. After executing, normalize CLAHE result to 8 bit [0, 255] and convert to 8 bit (CV_8UC1).

I have got some questions too:

  • Why is limited the histogram bin size to 4096 when a 16 bit image has got (1<<16) == 65536 kinds shade?
  • What do the grids mean on image 3? How can i eliminate them?
edit retag flag offensive close merge delete

2 answers

Sort by ยป oldest newest most voted
2

answered 2016-10-21 18:47:24 -0600

Tetragramm gravatar image

updated 2016-10-21 19:24:09 -0600

So, yeah. The 16-bit CLAHE is broken. I've fixed it once for work, but I can't commit it here.

Working from memory, here are the changes, all in clahe.cpp

Line 215:

 int residualStep = MAX(histSize / residual, 1);
for (int i = 0; i < histSize; i += residualStep)

Line 360:

 int histSize = _src.type() == CV_8UC1 ? 256 : 65536;

Line 417:

 calcLutBody = cv::makePtr<CLAHE_CalcLut_Body<ushort, 65535, 0> >(srcForLut, lut_, tileSize, tilesX_, clipLimit, lutScale);

Line 427:

interpolationBody = cv::makePtr<CLAHE_Interpolation_Body<ushort, 0> >(src, dst, lut_, tileSize, tilesX_, tilesY_);

Then your clip limit should be ~500, is my experience. I'm re-building to test these changes, and downloading an IR dataset. I'll edit once I'm done. I don't suppose I could see the raw 16bit of yours to show?

EDIT: Line 215 also needs a divide by zero check. Use this block of code.

if (residual != 0)
{
   int residualStep = MAX(histSize / residual, 1);
   for (int i = 0; i < histSize; i += residualStep)
         tileHist[i]++;
}

I've tested, and these changes do work. So basically you're changing the final distribution in the histogram slightly (which should improve 8-bit quality as well), using the full 16-bit range, and changing the shift in the template parameters to 0.

edit flag offensive delete link more
0

answered 2016-10-23 09:57:47 -0600

pvt.peter gravatar image

updated 2017-03-21 04:30:12 -0600

Hi Tetragramm,

Thanks for your reply. I did your suggestions, code modifications, and it seems to work.

I uploaded the results too, the scenario is already the same: applying CLAHE algorithm on the original 16 bit image. After executing, normalize CLAHE's result to 8 bit [0, 255] and convert to 8 bit (CV_8UC1):

  1. opencv-master CLAHE (with default parameters)
  2. modified CLAHE via your suggestions (ClipLimit(500.0) and TilesGridSize(Size(8, 8)) parameters)
  3. modified CLAHE via your suggestions (ClipLimit(500.0) and TilesGridSize(Size(3, 3)) parameters)

The modified CLAHE's result is more better and smoother, especially if parameter of clip limit and grid size are set "right".

Parameterization is a good question because of comparison of image 2. and 3. If i decrease the parameter of tiles grid size, no grids appeared on result image but the center of image (part of lung) is less contrasty.

I think it is a good change, fix about CLAHE executing on 16 bit grayscale images (CV_16UC1). Will you commit this modification to clahe.cpp?

If you would like, i can send sample *.raw 16 bit images with little framework which handle this format for you to further experiment. What do you think? If OK, please give me an e-mail address to contact with you.


And now i have a question about this modification of clahe.cpp, according you:

if (residual != 0)
{
    int residualStep = MAX(histSize / residual, 1);
    for (int i = 0; i < histSize; i += residualStep)
        tileHist[i]++;
}

Why this modification is needed?

Are you sure these are all the needed modifications?

edit flag offensive delete link more

Comments

I tested it, and yes, I believe this is everything. You should also try increasing the size of the grid, and it should be somewhat smoother.

I have created a pull request to fix this. It's not quite all, I think I need to change the OpenCL function as well.

The reason for that modification is to change the distribution to be even over the dynamic range, rather than concentrated at the bottom end. Try setting it back to the original and see the difference. It should be much darker than you want.

Tetragramm gravatar imageTetragramm ( 2016-10-23 17:10:38 -0600 )edit

Thanks for your reply and help. :) And yes, i think too that CLAHE via OpenCL requires some modification.

pvt.peter gravatar imagepvt.peter ( 2016-10-24 03:01:09 -0600 )edit

It's been too long. Which part of this did you edit and what was the new question? You can see the pull-request that included this fix HERE.

Tetragramm gravatar imageTetragramm ( 2017-03-21 17:38:42 -0600 )edit

Hi @Tetragramm, I have just updated the links of images only.

pvt.peter gravatar imagepvt.peter ( 2017-03-22 03:18:48 -0600 )edit

Hi Everybody,

Could someone tell me what causes the "living/moving" grids on the next 16 bit image?

http://i.imgur.com/SlCZAcb.gif (~17MB)

Source *.png

I use the next parametrization:

ClipLimit is fix: 400.0

TileGridSize is various: (1,1) -> (2,2) -> (3,3) -> ... -> (56,56) -> (57,57)

BR,

Peter

pvt.peter gravatar imagepvt.peter ( 2017-04-03 11:57:31 -0600 )edit

That would be the grid.... You know, the one the parameter you're adjusting is talking about...

If you're not sure how it works, there's an explanation HERE.

Tetragramm gravatar imageTetragramm ( 2017-04-03 18:17:35 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2016-10-21 08:18:43 -0600

Seen: 3,716 times

Last updated: Mar 21 '17