Histogram Equalization

Histogram equalization

This method usually increases the global contrast of many images, especially when the usable data of the image is represented by close contrast values. Through this adjustment, the intensities can be better distributed on the histogram. This allows for areas of lower local contrast to gain a higher contrast. Histogram equalization accomplishes this by effectively spreading out the most frequent intensity values. The method is useful in images with backgrounds and foregrounds that are both bright or both dark. In particular, the method can lead to better views of bone structure in x-ray images, and to better detail in photographs that are over or under-exposed. A key advantage of the method is that it is a fairly straightforward technique and an invertible operator. So in theory, if the histogram equalization function is known, then the original histogram can be recovered. The calculation is not computationally intensive. A disadvantage of the method is that it is indiscriminate. It may increase the contrast of background noise, while decreasing the usable signal.

In scientific imaging where spatial correlation is more important than intensity of signal (such as separating DNA fragments of quantized length), the small signal to noise ratio usually hampers visual detection. Histogram equalization often produces unrealistic effects in photographs; however it is very useful for scientific images like thermal, satellite or x-ray images, often the same class of images that user would apply false-color to. Also histogram equalization can produce undesirable effects (like visible image gradient) when applied to images with low color depth. For example, if applied to 8-bit image displayed with 8-bit gray-scale palette it will further reduce color depth (number of unique shades of gray) of the image. Histogram equalization will work the best when applied to images with much higher color depth than palette size, like continuous data or 16-bit gray-scale images.

There are two ways to think about and implement histogram equalization, either as image change or as palette change. The operation can be expressed as P(M(I)) where I is the original image, M is histogram equalization mapping operation and P is a palette. If we define a new palette as P'=P(M) and leave image I unchanged then histogram equalization is implemented as palette change. On the other hand if palette P remains unchanged and image is modified to I'=M(I) then the implementation is by image change. In most cases palette change is better as it preserves the original data.

Image Enhancement by Histogram Equalization

Algorithm
The Histogram Equalization algorithm enhances the contrast of images by transforming the values in an intensity image so that the histogram of the output image is approximately flat.
I = imread('pout.tif');
J = histeq(I);
subplot(2,1,1);
imhist(I)
subplot(2,1,2);
imhist(J)


MATLAB Design
design_name = 'mlhdlc_heq.m';
testbench_name = 'mlhdlc_heq_tb.m';
Let us take a look at the MATLAB design
type(design_name);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% heq.m
% Histogram Equalization Algorithm
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [x_out y_out pixel_out] = ...
    mlhdlc_heq(x_in, y_in, pixel_in, width, height)

persistent histogram
persistent transferFunc
persistent histInd
persistent cumSum

if isempty(histogram)
    histogram = zeros(1, 2^14);
    transferFunc = zeros(1, 2^14);
    histInd = 0;
    cumSum = 0;
end

% Figure out indexes based on where we are in the frame
if y_in < height && x_in < width % valid pixel data
    histInd = pixel_in + 1;
elseif y_in == height && x_in == 0 % first column of height+1
    histInd = 1;
elseif y_in >= height % vertical blanking period
    histInd = min(histInd + 1, 2^14);
elseif y_in < height % horizontal blanking - do nothing
    histInd = 1;
end

%Read histogram (must be outside conditional logic)
histValRead = histogram(histInd);

%Read transfer function (must be outside conditional logic)
transValRead = transferFunc(histInd);

%If valid part of frame add one to pixel bin and keep transfer func val
if y_in < height && x_in < width
    histValWrite = histValRead + 1; %Add pixel to bin
    transValWrite = transValRead; %Write back same value
    cumSum = 0;
elseif y_in >= height %In blanking time index through all bins and reset to zero
    histValWrite = 0;
    transValWrite = cumSum + histValRead;
    cumSum = transValWrite;
else
    histValWrite = histValRead;
    transValWrite = transValRead;
end

%Write histogram (must be outside conditional logic)
histogram(histInd) = histValWrite;

%Write transfer function (must be outside conditional logic)
transferFunc(histInd) = transValWrite;

pixel_out = transValRead;
x_out = x_in;
y_out = y_in;

type(testbench_name);
%Test bench for Histogram Equalization

testFile = 'mlhdlc_img_drive1.tif';
imgOrig = imread(testFile);
[height width] = size(imgOrig);
imgOut = zeros(height,width);
hBlank = 20;
% make sure we have enough vertical blanking to filter the histogram
vBlank = ceil(2^14/(width+hBlank));

for frame = 1:2
    disp(['working on frame: ', num2str(frame)]);
    for y_in = 0:height+vBlank-1
        %disp(['frame: ', num2str(frame), ' of 2, row: ', num2str(y_in)]);
        for x_in = 0:width+hBlank-1
            if x_in < width && y_in < height
                pixel_in = double(imgOrig(y_in+1, x_in+1));
            else
                pixel_in = 0;
            end
            
            [x_out y_out pixel_out] = ...
                mlhdlc_heq(x_in, y_in, pixel_in, width, height);
                       
            if x_out < width && y_out < height
                imgOut(y_out+1,x_out+1) = pixel_out;
            end
        end
    end
    
    figure(1)
    subplot(2,2,1); imshow(imgOrig, []);
    title('Original Image');
    subplot(2,2,2); imshow(imgOut, []);
    title('Equalized Image');
    subplot(2,2,3); hist(double(imgOrig(:)),2^14-1);
    title('Histogram of original Image');
    subplot(2,2,4); hist(double(imgOut(:)),2^14-1);
    title('Histogram of equalized Image');
end
Simulate the Design
It is always a good practice to simulate the design with the testbench prior to code generation to make sure there are no runtime errors.
mlhdlc_heq_tb
working on frame: 1
working on frame: 2

Setup for the Example
Executing the following lines copies the necessary files into a temporary folder
mlhdlc_demo_dir = fullfile(matlabroot, 'toolbox', 'hdlcoder', 'hdlcoderdemos', 'matlabhdlcoderdemos');
mlhdlc_temp_dir = [tempdir 'mlhdlc_heq'];

% create a temporary folder and copy the MATLAB files
cd(tempdir);
[~, ~, ~] = rmdir(mlhdlc_temp_dir, 's');
mkdir(mlhdlc_temp_dir);
cd(mlhdlc_temp_dir);

% copy files to the temp dir
copyfile(fullfile(mlhdlc_demo_dir, design_name), mlhdlc_temp_dir);
copyfile(fullfile(mlhdlc_demo_dir, testbench_name), mlhdlc_temp_dir);
copyfile(fullfile(mlhdlc_demo_dir, 'mlhdlc_img_drive1.tif'), mlhdlc_temp_dir);
Create a New HDL Coder™ Project
coder -hdlcoder -new mlhdlc_heq_prj
Next, add the file 'mlhdlc_heq.m' to the project as the MATLAB Function and 'mlhdlc_heq_tb.m' as the MATLAB Test Bench.
You can refer to Getting Started with MATLAB to HDL Workflow tutorial for a more complete tutorial on creating and populating MATLAB HDL Coder projects.
Run Fixed-Point Conversion and HDL Code Generation
Launch HDL Advisor and right click on the 'Code Generation' step and choose the option 'Run to selected task' to run all the steps from the beginning through the HDL code generation.
Examine the generated HDL code by clicking on the hyperlinks in the Code Generation Log window.
Clean up the Generated Files
You can run the following commands to clean up the temporary project folder.
mlhdlc_demo_dir = fullfile(matlabroot, 'toolbox', 'hdlcoder', 'hdlcoderdemos', 'matlabhdlcoderdemos');
mlhdlc_temp_dir = [tempdir 'mlhdlc_heq'];
clear mex;
cd (mlhdlc_demo_dir);
rmdir(mlhdlc_temp_dir, 's');

 Example

An unequalized image
Corresponding histogram (red) and cumulative histogram (black)
The same image after histogram equalization
 
 

 

References

  • Acharya and Ray, Image Processing: Principles and Applications, Wiley-Interscience 2005 ISBN 0-471-71998-6
  • Russ, The Image Processing Handbook: Fourth Edition, CRC 2002 ISBN 0-8493-2532-3


 
Corresponding histogram (red) and cumulative histogram (black)