Multilevel image thresholds using Otsu's method


  • thresh = multithresh(A) example
  • thresh = multithresh(A,N) example
  • [thresh,metric] = multithresh(___) example



thresh = multithresh(A) returns the single threshold value thresh computed for image A using Otsu's method. You can use thresh as an input argument to imquantize to convert an image into a two-level image.

This function supports code generation (see Tips).


thresh = multithresh(A,N) returns thresh a 1-by-N vector containing N threshold values using Otsu's method. You can use thresh as an input argument to imquantize to convert image A into an image with N + 1 discrete levels.


[thresh,metric] = multithresh(___) returns metric, a measure of the effectiveness of the computed thresholds. metric is in the range [0 1] and a higher value indicates greater effectiveness of the thresholds in separating the input image into N + 1 regions based on Otsu's objective criterion.


expand all

Segment Image Into Two Regions

Read image and display it.

I = imread('coins.png');

Calculate a single threshold value for the image.

level = multithresh(I);

Segment the image into two regions using imquantize , specifying the threshold level returned by multithresh .

seg_I = imquantize(I,level);

Segment Image into Three Levels using Two Thresholds

Read image and display it.

I = imread('circlesBrightDark.png');
axis off
title('Original Image')

Calculate two threshold levels.

thresh = multithresh(I,2);

Segment the image into three levels using imquantize .

seg_I = imquantize(I,thresh);

Convert segmented image into color image using label2rgb and display it.

RGB = label2rgb(seg_I);
axis off
title('RGB Segmented Image')

Compare Thresholding Entire Image versus Plane-by-plane Thresholding

Read truecolor (RGB) image and display it.

I = imread('peppers.png');
axis off
title('RGB Image');

Generate thresholds for seven levels from the entire RGB image.

threshRGB = multithresh(I,7);

Generate thresholds for each plane of the RGB image.

threshForPlanes = zeros(3,7);

for i = 1:3
    threshForPlanes(i,:) = multithresh(I(:,:,i),7);

Process the entire image with the set of threshold values computed from entire image.

value = [0 threshRGB(2:end) 255];
quantRGB = imquantize(I, threshRGB, value);

Process each RGB plane separately using the threshold vector computed from the given plane. Quantize each RGB plane using threshold vector generated for that plane.

quantPlane = zeros( size(I) );

for i = 1:3
    value = [0 threshForPlanes(i,2:end) 255];
    quantPlane(:,:,i) = imquantize(I(:,:,i),threshForPlanes(i,:),value);

quantPlane = uint8(quantPlane);

Display both posterized images and note the visual differences in the two thresholding schemes.

axis off
title('Full RGB Image Quantization        Plane-by-Plane Quantization')

To compare the results, calculate the number of unique RGB pixel vectors in each output image. Note that the plane-by-plane thresholding scheme yields about 23% more colors than the full RGB image scheme.

dim = size( quantRGB );
quantRGBmx3   = reshape(quantRGB,   prod(dim(1:2)), 3);
quantPlanemx3 = reshape(quantPlane, prod(dim(1:2)), 3);

colorsRGB   = unique(quantRGBmx3,   'rows' );
colorsPlane = unique(quantPlanemx3, 'rows' );

disp(['Unique colors in RGB image            : ' int2str(length(colorsRGB))]);
disp(['Unique colors in Plane-by-Plane image : ' int2str(length(colorsPlane))]);
Unique colors in RGB image            : 188
Unique colors in Plane-by-Plane image : 231

Check Results Using the metric Output Argument

Read image.

I = imread('circlesBrightDark.png');

Find all unique grayscale values in image.

uniqLevels = unique(I(:));

disp(['Number of unique levels = ' int2str( length(uniqLevels) )]);
Number of unique levels = 148

Compute a series of thresholds at monotonically increasing values of N .

Nvals = [1 2 4 8];
for i = 1:length(Nvals)
    [thresh, metric] = multithresh(I, Nvals(i) );
    disp(['N = ' int2str(Nvals(i)) '  |  metric = ' num2str(metric)]);
N = 1  |  metric = 0.54767
N = 2  |  metric = 0.98715
N = 4  |  metric = 0.99648
N = 8  |  metric = 0.99902

Apply the set of 8 threshold values to obtain a 9-level segmentation using imquantize .

seg_Neq8 = imquantize(I,thresh);
uniqLevels = unique( seg_Neq8(:) )
uniqLevels =


seg_Neq8 is input to multithresh and N is set to equal to 8 which is 1 less than the number of levels in this segmented image. metric is 1.

[thresh, metric] = multithresh(seg_Neq8,8)
thresh =

  Columns 1 through 7

    1.8784    2.7882    3.6667    4.5451    5.4549    6.3333    7.2118

  Column 8


metric =


Note what happens when N is increased by 1 and now equals the number of levels in the image. Here the input was degenerate because the number of levels in the image was too few for the number of requested thresholds. Hence metric is 0.

[thresh, metric] = multithresh(seg_Neq8,9)
Warning: No solution exists because the number of unique levels in the image are
too few to find 9 thresholds. Returning an arbitrarily chosen solution. 

thresh =

     1     2     3     4     5     6     7     8     9

metric =


Input Arguments

expand all

A — Image to be thresholdednon-sparse numeric array of any dimension

Image to be thresholded, specified as a non-sparse numeric array of any dimension. multithresh finds the thresholds based on the aggregate histogram of the entire array. multithresh considers an RGB image a 3-D numeric array and computes the thresholds for the combined data from all three color planes.

multithresh uses the range of the input A [min(A(:)) max(A(:))] as the limits for computing the histogram which is used in subsequent computations. Any NaNs are ignored in computation. Any Infs and -Infs are counted in the first and last bin of the histogram, respectively.

For degenerate inputs where the number of unique values in A is less than or equal to N, there is no viable solution using Otsu's method. For such inputs, thresh contains all the unique values from A and possibly some extra values that are chosen arbitrarily.

Data Types: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64

N — Number of threshold values1 (default) | scalar

Number of threshold values, specified as a scalar value. For N > 2, multithresh uses search-based optimization of Otsu's criterion to find the thresholds. The search-based optimization guarantees only locally optimal results. Since the chance of converging to local optimum increases with N, it is preferable to use smaller values of N, typically N < 10. The maximum allowed value for N is 20.

Data Types: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64

Output Arguments

expand all

thresh — Set of threshold values used to quantize an image1xN vector

Set of threshold values used to quantize an image, returned as a 1-by-N vector, whose data type is the same as image A.

These thresholds are in the same range as the input image A, unlike the graythresh function which returns a normalized threshold in the range [0, 1].

metric — Measure of the effectiveness of the thresholdsscalar

Measure of the effectiveness of the thresholds, returned as a scalar value. Higher values indicates greater effectiveness of the thresholds in separating the input image into N+1 classes based on Otsu's objective criterion. For degenerate inputs where the number of unique values in A is less than or equal to N, metric equals 0.

Data Types: double

More About

expand all


  • This function supports the generation of C code using MATLAB® Coder™. The code generated for this function uses a precompiled, platform-specific shared library. Use of a shared library preserves performance optimizations but limits the target platforms for which code can be generated. For more information, see Code Generation Using a Shared Library.


[1] Otsu, N., "A Threshold Selection Method from Gray-Level Histograms," IEEE Transactions on Systems, Man, and Cybernetics, Vol. 9, No. 1, 1979, pp. 62-66.

Was this topic helpful?