Julia Images adaptive histogram equalization vs MATLAB's implementation

I’m hoping to get an expert’s opinion on this matter.

In MATLAB:

>> img = imread('cameraman.tif');
>> class(img)

ans =

    'uint8'

>> sum(img(:))

ans =

     7780728

>> img_eq = adapthisteq(img, Range="original", NBins=256, NumTiles=[8 8], ClipLimit=0.01);
>> figure; imshow(cat(2,img,img_eq));

The images look like this (original on left):
image

For the same workflow in Julia I exported cameraman from MATLAB to a file to read in (the one in TestImages is not the same for some reason) but for the illustration below we’ll stick to the one from TestImages

using Images, ImageContrastAdjustment, TestImages
img = testimage("cameraman")
img = Int64.(img .* 255) # converting to ints as `load` produces eltype Gray{N0f8} and the algo doesn't like that
maxval, minval = maximum(img), minimum(img)

algo = AdaptiveEqualization(minval=minval, maxval=maxval, nbins=256, rblocks=8, cblocks=8, clip=0.01)
img_adjusted = adjust_histogram(img, algo)
Gray.(hcat(img, img_adjusted) / 255) # for the visualization

You get this:
image

As you can see the image is exceedingly oversharpened. Is there something I am overlooking? I noticed the default values of (minval, maxval) are set to (0, 1) which seem low for uint8 images. However, I converted the input image to gray with Gray.(img / 255) using those default values and got the same effect still.

2 Likes

It has been a while since I implemented this, so I don’t immediately recall all of the details. I’m not sure what how MATLAB has interpreted the parameters, but it looks like my parameter clip and MATLABs ClipLimit are not exactly the same. At first glance, it looks like clip ≈ 1 - ClipLimit. So if you try

using Images, ImageContrastAdjustment, TestImages
img = testimage("cameraman")
algo = AdaptiveEqualization(minval=minval, maxval=maxval, nbins=256, rblocks=8, cblocks=8, clip=0.99)
img_adjusted = adjust_histogram(img, algo)

you should get something similar to your MATLAB result.


You don’t need to convert the image to Int64. The algorithm will work on the Gray{N0f8} input. All images are represented on a [0…1] intensity scale, so 0 is black and 1 is white. The rationale for this representation is explained in the docmentation: Quickstart · JuliaImagesJuliaImages Quickstart