Main Content

imhistmatch

Adjust histogram of 2-D image to match histogram of reference image

Description

example

J = imhistmatch(I,ref) adjusts the histogram of the 2-D grayscale or truecolor image I such that the histogram approximately matches the histogram of the reference image ref.

  • If both I and ref are truecolor images, then imhistmatch matches each color channel of I independently to the corresponding color channel of ref.

  • If I is a truecolor RGB image and ref is a grayscale image, then imhistmatch matches each channel of I against the single histogram derived from ref.

  • If I is a grayscale image, then ref must also be a grayscale image.

Images I and ref need not be equal in size.

example

J = imhistmatch(I,ref,nbins) uses nbins equally spaced bins within the appropriate range for the given image data type. The returned image J has no more than nbins discrete levels.

  • If the data type of the image is either single or double, then the histogram range is [0, 1].

  • If the data type of the image is uint8, then the histogram range is [0, 255].

  • If the data type of the image is uint16, then the histogram range is [0, 65535].

  • If the data type of the image is int16, then the histogram range is [-32768, 32767].

example

J = imhistmatch(___,Method=method) also specifies whether to use a uniform or polynomial mapping technique

example

[J,hgram] = imhistmatch(___) returns the histogram of the reference image ref used for matching in hgram.

Examples

collapse all

These aerial images, taken at different times, represent overlapping views of the same terrain in Concord, Massachusetts. This example demonstrates that input images A and Ref can be of different sizes and image types.

Load an RGB image and a reference grayscale image.

A = imread("westconcordaerial.png");
Ref = imread("westconcordorthophoto.png");

Get the size of A.

size(A)
ans = 1×3

   394   369     3

Get the size of Ref.

size(Ref)
ans = 1×2

   366   364

Note that image A and Ref are different in size and type. Image A is a truecolor RGB image, while image Ref is a grayscale image. Both images are of data type uint8.

Generate the histogram matched output image. The example matches each channel of A against the single histogram of Ref. Output image B takes on the characteristics of image A - it is an RGB image whose size and data type is the same as image A. The number of distinct levels present in each RGB channel of image B is the same as the number of bins in the histogram built from grayscale image Ref. In this example, the histogram of Ref and B have the default number of bins, 64.

B = imhistmatch(A,Ref);

Display the RGB image A, the reference image Ref, and the histogram matched RGB image B. The images are resized before display.

imshow(A)
title("RGB Image with Color Cast")

Figure contains an axes object. The axes object with title RGB Image with Color Cast contains an object of type image.

imshow(Ref)
title("Reference Grayscale Image")

Figure contains an axes object. The axes object with title Reference Grayscale Image contains an object of type image.

imshow(B)
title("Histogram Matched RGB Image")

Figure contains an axes object. The axes object with title Histogram Matched RGB Image contains an object of type image.

Read a color image and a reference image. To demonstrate the polynomial method, assign the reference image to be the darker of the two images.

I = imread('office_4.jpg');
ref = imread('office_2.jpg');
montage({I,ref})
title('Input Image (Left) vs Reference Image (Right)');

Figure contains an axes object. The axes object with title Input Image (Left) vs Reference Image (Right) contains an object of type image.

Use the polynomial method to adjust the intensity of image I so that it matches the histogram of reference image ref. For comparison, also adjust the intensity of image I using the uniform method.

J = imhistmatch(I,ref,'method','polynomial');
K = imhistmatch(I,ref,'method','uniform');
montage({J,K})
title('Histogram-Matched Image Using Polynomial Method (Left) vs Uniform Method (Right)');

Figure contains an axes object. The axes object with title Histogram-Matched Image Using Polynomial Method (Left) vs Uniform Method (Right) contains an object of type image.

The histogram-matched image using the uniform method introduces false colors in the sky and road. The histogram-matched image using the polynomial method does not exhibit this artifact.

This example shows how you can vary the number of bins in the target histogram to improve histogram equalization.

Load two images of data type uint8 into the workspace. The images were taken with a digital camera and represent two different exposures of the same scene. A is an underexposed image and appears dark. ref is a reference image with good exposure and brightness.

A = imread('office_2.jpg');
ref = imread('office_4.jpg');

Display the images in a montage.

montage({A,ref})
title('Dark Image (Left) and Reference Image (Right)')

Figure contains an axes object. The axes object with title Dark Image (Left) and Reference Image (Right) contains an object of type image.

Display the histogram of each color channel using 256 bins. You can use the helper function, displayHistogramChannels, that is included with the example.

displayHistogramChannels(A,ref)

Figure contains 6 axes objects. Axes object 1 with title Histograms of Input Image contains an object of type histogram. Axes object 2 with title Histograms of Reference Image contains an object of type histogram. Axes object 3 contains an object of type histogram. Axes object 4 contains an object of type histogram. Axes object 5 contains an object of type histogram. Axes object 6 contains an object of type histogram.

Image A, being the darker image, has most of its pixels in the lower bins. The reference image, ref, fully populates all 256 bins values in all three RGB channels.

Count the number of unique 8-bit level values for each color channel of the dark and reference image. You can use the helper function, countUniqueValues, that is included with the example.

numVals = countUniqueValues(A,ref);
table(numVals(:,1),numVals(:,2),numVals(:,3), ...
  'VariableNames',["Red" "Green" "Blue"], ...
  'RowNames',["A" "ref"])
ans=2×3 table
           Red    Green    Blue
           ___    _____    ____

    A      205     193     224 
    ref    256     256     256 

Equalize the histogram of the dark image using three different values of nbins: 64, 128 and 256. 64 is the default number of bins and 256 is the maximum number of bins for uint8 pixel data.

[B64,hgram64]   = imhistmatch(A,ref,64);   
[B128,hgram128] = imhistmatch(A,ref,128);
[B256,hgram256] = imhistmatch(A,ref,256);

figure
montage({B64,B128,B256},'Size',[1 3])
title('Output Image B64  |  Output Image B128  |  Output Image B256')

Figure contains an axes object. The axes object with title Output Image B64 | Output Image B128 | Output Image B256 contains an object of type image.

Display the histogram of each color channel using 256 bins. You can use the helper function, displayThreeHistogramChannels, that is included with the example.

displayThreeHistogramChannels(B64,B128,B256)

Figure contains 9 axes objects. Axes object 1 with title Histograms of Output Image B64 contains an object of type histogram. Axes object 2 with title Histograms of Output Image B128 contains an object of type histogram. Axes object 3 with title Histograms of Output Image B256 contains an object of type histogram. Axes object 4 contains an object of type histogram. Axes object 5 contains an object of type histogram. Axes object 6 contains an object of type histogram. Axes object 7 contains an object of type histogram. Axes object 8 contains an object of type histogram. Axes object 9 contains an object of type histogram.

Count the number of unique 8-bit level values for each color channel of the three histogram equalized images. As nbins increases, the number of levels in each RGB channel of output image B also increases.

numVals = countUniqueValues(B64,B128,B256);
table(numVals(:,1),numVals(:,2),numVals(:,3), ...
  'VariableNames',["Red" "Green" "Blue"], ...
  'RowNames',["B64" "B128" "B256"])
ans=3×3 table
            Red    Green    Blue
            ___    _____    ____

    B64      57      60      58 
    B128    101     104     104 
    B256    134     135     136 

This example shows how to perform histogram matching with different numbers of bins.

Load a 16-bit DICOM image of a knee imaged via MRI.

K = dicomread('knee1.dcm');   % read in original 16-bit image
LevelsK = unique(K(:));       % determine number of unique code values
disp(['image K: ',num2str(length(LevelsK)),' distinct levels']);
image K: 448 distinct levels
disp(['max level = ' num2str( max(LevelsK) )]);
max level = 473
disp(['min level = ' num2str( min(LevelsK) )]);
min level = 0

All 448 discrete values are at low code values, which causes the image to look dark. To rectify this, scale the image data to span the entire 16-bit range of [0, 65535].

Kdouble = double(K);                  % cast uint16 to double
kmult = 65535/(max(max(Kdouble(:)))); % full range multiplier
Ref = uint16(kmult*Kdouble);   % full range 16-bit reference image

Darken the reference image Ref to create an image A that can be used in the histogram matching operation.

%Build concave bow-shaped curve for darkening |Ref|.
ramp = [0:65535]/65535;
ppconcave = spline([0 .1 .50  .72 .87 1],[0 .025 .25 .5 .75 1]);
Ybuf = ppval( ppconcave, ramp);
Lut16bit = uint16( round( 65535*Ybuf ) );
% Pass image |Ref| through a lookup table (LUT) to darken the image.
A = intlut(Ref,Lut16bit);

View the reference image Ref and the darkened image A. Note that they have the same number of discrete code values, but differ in overall brightness.

subplot(1,2,1)
imshow(Ref)
title('Ref: Reference Image')
subplot(1,2,2)
imshow(A)
title('A: Darkened Image');

Figure contains 2 axes objects. Axes object 1 with title Ref: Reference Image contains an object of type image. Axes object 2 with title A: Darkened Image contains an object of type image.

Generate histogram-matched output images using histograms with different number of bins. First use the default number of bins, 64. Then use the number of values present in image A, 448 bins.

B16bit64 = imhistmatch(A(:,:,1),Ref(:,:,1));  % default: 64 bins

N = length(LevelsK);     % number of unique 16-bit code values in image A.
B16bitUniq = imhistmatch(A(:,:,1),Ref(:,:,1),N);

View the results of the two histogram matching operations.

figure
subplot(1,2,1)
imshow(B16bit64)
title('B16bit64: 64 bins')
subplot(1,2,2)
imshow(Ref)
title(['B16bitUniq: ',num2str(N),' bins'])

Figure contains 2 axes objects. Axes object 1 with title B16bit64: 64 bins contains an object of type image. Axes object 2 with title B16bitUniq: 448 bins contains an object of type image.

Input Arguments

collapse all

Input image to be transformed, specified as a 2-D truecolor or grayscale image.

Data Types: single | double | int16 | uint8 | uint16

Reference image whose histogram is the reference histogram, specified as a 2-D truecolor or grayscale image. The reference image provides the equally spaced nbins bin reference histogram which output image J is trying to match.

Data Types: single | double | int16 | uint8 | uint16

Number of equally spaced bins in reference histogram, specified as a positive integer. In addition to specifying the number of equally spaced bins in the histogram for image ref, nbins also represents the upper limit of the number of discrete data levels present in output image J.

Mapping technique used to map the histogram of ref to image I, specified as one of these values:

  • "uniform" — Use a histogram-based intensity function and histogram equalization.

  • "polynomial" — Calculate a cubic Hermite polynomial mapping function from the cumulative histograms of the source and reference images. The polynomial method is useful when the reference image is darker than the input image. In this situation, the polynomial method gives a smoother color transition than the uniform method.

Output Arguments

collapse all

Output image, returned as a 2-D truecolor or grayscale image. The output image is derived from image I whose histogram is an approximate match to the histogram of input image ref built with nbins equally-spaced bins. Image J is of the same size and data type as input image I. Input argument nbins represents the upper limit of the number of discrete levels contained in image J.

Data Types: single | double | int16 | uint8 | uint16

Histogram counts derived from reference image ref, specified as a vector or matrix. When ref is a truecolor image, hgram is a 3-by-nbins matrix, and each row stores the histogram of a single color channel of ref. When ref is a grayscale image, hgram is a 1-by-nbins vector.

Data Types: double

Algorithms

The objective of imhistmatch is to transform image I such that the histogram of image J matches the histogram derived from image ref. It consists of nbins equally spaced bins which span the full range of the image data type. A consequence of matching histograms in this way is that nbins also represents the upper limit of the number of discrete data levels present in image J.

An important behavioral aspect of this algorithm to note is that as nbins increases in value, the degree of rapid fluctuations between adjacent populated peaks in the histogram of image J tends to increase. This can be seen in the following histogram plots taken from the 16–bit grayscale MRI example.

An optimal value for nbins represents a trade-off between more output levels (larger values of nbins) while minimizing peak fluctuations in the histogram (smaller values of nbins).

Version History

Introduced in R2012b