Scikit Image − Otsu Thresholding



Otsu's method is an automatic image thresholding technique used in computer vision and image processing, which is named after its creator Nobuyuki Otsu. The algorithm determines a single intensity threshold that effectively divides pixels into two distinct classes: foreground and background.

This calculates an optimal threshold by maximizing the variance between the two classes of pixels that are separated by the threshold.

The scikit image library provides the threshold_otsu() function within its filters module to compute the threshold value based on Otsu's method.

Using the skimage.filters.threshold_otsu() function

The filters.threshold_otsu() function is used to calculate a threshold value based on Otsu's method. It requires either the image or hist parameter to be provided. If hist is provided, it uses the provided histogram to determine the thresholds. If the image is provided, it computes the histogram from the image.

Syntax

Following is the syntax of this function −

skimage.filters.threshold_otsu(image=None, nbins=256, *, hist=None)

Parameters

Here are the details about the function parameters −

  • Image (N, M[, …, P]) ndarray: An optional grayscale input image.
  • nbins (int): An optional integer specifying the number of bins used to calculate the histogram. This value is ignored for integer arrays.
  • hist (array, or 2-tuple of arrays): An optional input histogram from which to determine the threshold, and optionally, a corresponding array of bin center intensities. If no histogram is provided, the function will compute it from the image.

Return value

The function returns the calculated upper threshold value (float). All pixels in the image with an intensity higher than this threshold are assumed to be foreground.

Note: It is important to note that the input image must be a grayscale image.

Example

Here is an example of using Otsu's thresholding method to separate an image into foreground and background based on pixel intensities −

import matplotlib.pyplot as plt
from skimage import io
from skimage.filters import threshold_otsu

# Load the image in grayscale
image = io.imread('Images/black rose.jpg', as_gray=True)

# Calculate the Otsu threshold
thresh = threshold_otsu(image)

# Create a binary image using the threshold
binary = image > thresh

# Create subplots for original image, histogram, and thresholded image
fig, axes = plt.subplots(ncols=3, figsize=(12, 2.5))
ax = axes.ravel()

# Display the original image
ax[0].imshow(image, cmap=plt.cm.gray)
ax[0].set_title('Original')
ax[0].axis('off')

# Plot the histogram with the Otsu threshold marked in red
ax[1].hist(image.ravel(), bins=256)
ax[1].set_title('Histogram')
ax[1].axvline(thresh, color='r')

# Display the thresholded image
ax[2].imshow(binary, cmap=plt.cm.gray)
ax[2].set_title('Thresholded')
ax[2].axis('off')

# Show the subplots
plt.show()

Output

Otsu Threshold

Example

Here is another example of applying Otsu's thresholding method to separate an image into foreground and background using a 3D image −

import matplotlib.pyplot as plt
from skimage import exposure, data
from skimage.morphology import ball
from skimage.filters import threshold_otsu

# Load the brain image and rescale intensity
brain = exposure.rescale_intensity(data.brain().astype(float))

# Calculate the Otsu threshold for the brain image
thresh = threshold_otsu(brain)

# Create a binary image using the Otsu threshold
binary = brain >= thresh

# Create subplots for original and thresholded images
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(10, 5),
                         sharex=True, sharey=True)
ax = axes.ravel()

# Choose a slice index for visualization
slice_index = 3

# Display the original image 
ax[0].imshow(brain[slice_index], cmap=plt.cm.gray)
ax[0].set_title('Original')
ax[0].axis('off')

# Display the Otsu thresholded image
ax[1].imshow(binary[slice_index], cmap=plt.cm.gray)
ax[1].set_title(f'Otsu ($t={thresh}$)')
ax[1].axis('off')

fig.tight_layout()
plt.show()

Output

Otsu Threshold
Advertisements