No BSD License  

Highlights from
Contrast Limited Adaptive Histogram Equalization (CLAHE)

from Contrast Limited Adaptive Histogram Equalization (CLAHE) by Leslie Smith
Best to read the reference in "Graphics Gems IV", Academic Press, 1994 pages 474-485

runCLAHE(Image,XRes,YRes,Min,Max,NrX,NrY,NrBins,Cliplimit)
function [CEImage] = runCLAHE(Image,XRes,YRes,Min,Max,NrX,NrY,NrBins,Cliplimit)

%  "Contrast Limited Adaptive Histogram Equalization"
%  by Karel Zuiderveld, karel@cv.ruu.nl
%  in "Graphics Gems IV", Academic Press, 1994 
%  (Ported to Matlab by Leslie Smith)
% 
%   These functions implement Contrast Limited Adaptive Histogram Equalization.
%   The main routine (CLAHE) expects an input image that is stored contiguously in
%   memory;  the CLAHE output image overwrites the original input image and has the
%   same minimum and maximum values (which must be provided by the user).
%   This implementation assumes that the X- and Y image resolutions are an integer
%   multiple of the X- and Y sizes of the contextual regions. A check on various other
%   error conditions is performed.
% 
% 
%    Image - The input/output image
%    XRes - Image resolution in the X direction
%    YRes - Image resolution in the Y direction
%    Min - Minimum greyvalue of input image (also becomes minimum of output image)
%    Max - Maximum greyvalue of input image (also becomes maximum of output image)
%    NrX - Number of contextial regions in the X direction (min 2, max uiMAX_REG_X)
%    NrY - Number of contextial regions in the Y direction (min 2, max uiMAX_REG_Y)
%    NrBins - Number of greybins for histogram ("dynamic range")
%    Cliplimit - Normalized cliplimit (higher values give more contrast)
%  The number of "effective" greylevels in the output image is set by uiNrBins; selecting
%  a small value (eg. 128) speeds up processing and still produce an output image of
%  good quality. The output image will have the same minimum and maximum value as the input
%  image. A clip limit smaller than 1 results in standard (non-contrast limited) AHE.

% [XRes,YRes]=size(Image);
% CEimage = Image;
CEImage = zeros(XRes,YRes);
if Cliplimit == 1
    return
end

NrBins=max(NrBins,128);
XSize = round(XRes/NrX);
YSize = round(YRes/NrY);
NrPixels = XSize*YSize;
XSize2 = round(XSize/2);
YSize2 = round(YSize/2);

if Cliplimit > 0 
    ClipLimit = max(1,Cliplimit*XSize*YSize/NrBins);
else
    ClipLimit = 1E8;
end

LUT=makeLUT(Min,Max,NrBins);
% avgBin = NrPixels/NrBins;
Bin=1+LUT(round(Image));

Hist = makeHistogram(Bin,XSize,YSize,NrX,NrY,NrBins);
if Cliplimit > 0
    Hist = clipHistogram(Hist,NrBins,ClipLimit,NrX,NrY);
end
Map=mapHistogram(Hist,Min,Max,NrBins,NrPixels,NrX,NrY);

% Interpolate
xI = 1;
for i = 1:NrX+1
    if i == 1
        subX = XSize/2;
        xU = 1;
        xB = 1;
    elseif i == NrX+1
        subX = XSize/2;
        xU = NrX;
        xB = NrX;
    else
        subX = XSize;
        xU = i - 1;
        xB = i;
    end
    yI = 1;
    for j = 1:NrY+1
        if j == 1
            subY = YSize/2;
            yL = 1;
            yR = 1;
        elseif j == NrY+1
            subY = YSize/2;
            yL = NrY;
            yR = NrY;
        else
            subY = YSize;
            yL = j - 1;
            yR = j;
        end
        UL = Map(xU,yL,:);
        UR = Map(xU,yR,:);
        BL = Map(xB,yL,:);
        BR = Map(xB,yR,:);
        subImage = Bin(xI:xI+subX-1,yI:yI+subY-1);
        subImage = interpolate(subImage,UL,UR,BL,BR,subX,subY);
        CEImage(xI:xI+subX-1,yI:yI+subY-1) = subImage;
        yI = yI + subY;
    end
    xI = xI + subX;
end

Contact us at files@mathworks.com