# multithresh

Multilevel image thresholds using Otsu’s method

## Description

returns
the single threshold value `thresh`

= multithresh(`A`

)`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.

returns `thresh`

= multithresh(`A`

,`N`

)`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.

## Examples

### Segment Image Into Two Regions

Read and display an image.

```
I = imread("coins.png");
imshow(I)
```

Calculate a single threshold value for the image.

level = multithresh(I);

Segment the image into two regions using the `imquantize`

function, specifying the threshold level returned by the `multithresh`

function. Display the result.

seg_I = imquantize(I,level); imshow(seg_I,[])

### Segment Image into Three Levels Using Two Thresholds

Read an image, convert it to grayscale, and display the result.

I = imread("foggysf2.jpg"); I = rgb2gray(I); imshow(I) title("Grayscale Image")

Calculate two threshold levels.

thresh = multithresh(I,2);

Segment the image into three levels using the `imquantize`

function.

labels = imquantize(I,thresh);

Convert the segmented image into a color image using the `label2rgb`

function, and display the image.

```
labelsRGB = label2rgb(labels);
imshow(labelsRGB)
title("Segmented Image")
```

### Compare Thresholding Entire Image Versus Plane-by-Plane Thresholding

Read and display an RGB image.

I = imread("peppers.png"); imshow(I) 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); end

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); end quantPlane = uint8(quantPlane);

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

```
montage({quantRGB,quantPlane})
title("Full RGB Image Quantization vs. 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"); disp("Unique colors in RGB image: "+length(colorsRGB));

Unique colors in RGB image: 188

colorsPlane = unique(quantPlanemx3,"rows"); disp("Unique colors in plane-by-plane image: "+length(colorsPlane));

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)]); end

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 = `*9×1*
1
2
3
4
5
6
7
8
9

Threshold the image using `seg_Neq8`

as an input to `multithresh`

. Set `N`

equal to 8, which is 1 less than the number of levels in this segmented image. `multithresh`

returns a `metric`

value of 1.

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

`thresh = `*1×8*
1.8784 2.7882 3.6667 4.5451 5.4549 6.3333 7.2118 8.1216

metric = 1

Threshold the image again, this time increasing the value of `N`

by 1. This value now equals the number of levels in the image. Note how the input is degenerate because the number of levels in the image is too few for the number of requested thresholds. Hence, `multithresh`

returns a `metric`

value of 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×9*
1 2 3 4 5 6 7 8 9

metric = 0

## Input Arguments

`A`

— Image to be thresholded

numeric array

Image to be thresholded, specified as a numeric array of any dimension.
`multithresh`

finds the thresholds based on the aggregate histogram of the
entire array. `multithresh`

considers an RGB image as 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
image `A`

, `[min(A(:)) max(A(:))]`

,
as the limits for computing the histogram used in subsequent computations. `multithresh`

ignores
any `NaNs`

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, the return value `thresh`

contains
all the unique values from `A`

and possibly some
extra values that are chosen arbitrarily.

**Data Types: **`single`

| `double`

| `int16`

| `uint8`

| `uint16`

`N`

— Number of threshold values

`1`

(default) | positive integer

Number of threshold values, specified as a positive integer. 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

`thresh`

— Set of threshold values

1-by-`N`

numeric vector

Set of threshold values used to quantize an image, returned as a
1-by-`N`

numeric 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 effectiveness

number in the range [0, 1]

Measure of the effectiveness of the thresholds, returned as a number in the range [0, 1].
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`

## References

[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.

## Extended Capabilities

### C/C++ Code Generation

Generate C and C++ code using MATLAB® Coder™.

Usage notes and limitations:

`multithresh`

supports the generation of C code (requires MATLAB^{®}Coder™). Note that if you choose the generic`MATLAB Host Computer`

target platform,`multithresh`

generates code that 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 Types of Code Generation Support in Image Processing Toolbox.The input argument

`N`

must be a compile-time constant.

### GPU Code Generation

Generate CUDA® code for NVIDIA® GPUs using GPU Coder™.

Usage notes and limitations:

The input argument

`N`

must be a compile-time constant.

## Version History

**Introduced in R2012b**

## See Also

`graythresh`

| `imquantize`

| `im2bw`

| `rgb2ind`

## Open Example

You have a modified version of this example. Do you want to open this example with your edits?

## MATLAB Command

You clicked a link that corresponds to this MATLAB command:

Run the command by entering it in the MATLAB Command Window. Web browsers do not support MATLAB commands.

Select a Web Site

Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .

You can also select a web site from the following list:

## How to Get Best Site Performance

Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.

### Americas

- América Latina (Español)
- Canada (English)
- United States (English)

### Europe

- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)

- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)