Scikit Image − Niblack and Sauvola Thresholding



Niblack and Sauvola thresholding methods are local thresholding techniques commonly used in image processing, particularly in applications such as text recognition, where the background of the image is non-uniform. In contrast to the conventional approach of determining a single global threshold for the entire image, these methods calculate individual thresholds for each pixel. They achieve this by applying specific formulas that take into account the mean and standard deviation of the local neighborhood, which is defined by a window centered around the pixel.

In the context of image processing, the scikit-image library offers two functions: threshold_niblack() and threshold_sauvola(). These functions are designed for the application of "Niblack" and "Sauvola" local thresholding techniques to image arrays, respectively.

Using the skimage.filters.threshold_niblack() function

The filters.threshold_niblack() fuction is used to apply the Niblack local thresholding method to a grayscale image. This method calculates a threshold value for each pixel in the image using the following formula:

T = m(x,y) - k * s(x,y)

The values m(x,y) and s(x,y) represent the mean and standard deviation of the pixel neighborhood defined by a rectangular window with size w times w centered around the pixel (x, y). And k is a configurable parameter that weights the effect of standard deviation.

Syntax

Following is the syntax of this function −

skimage.filters.threshold_niblack(image, window_size=15, k=0.2)

Parameters

The function accepts the following parameters −

  • image (N, M[, …, P]) ndarray: This is the grayscale input image on which the Niblack thresholding will be applied.
  • window_size (int or iterable of int, optional): This parameter specifies the size of the window. It can be a single odd integer (3, 5, 7, ...) or an iterable of odd integers of length equal to the image.ndim (e.g., (1, 5, 5)).
  • k (float, optional): This is the value of the parameter 'k' in the thresholding formula.
  • This function returns a threshold mask of the same shape as the input image (N, M). All pixels with an intensity higher than this threshold value are assumed to be part of the foreground.

Example

Here's an example of how to apply the filters.threshold_niblack() function to perform Niblack thresholding on an image −

from skimage import io, color, filters
import matplotlib.pyplot as plt

# Load an image
image = io.imread('Images/black rose.jpg')

# Convert the image to grayscale
image_gray = color.rgb2gray(image)

# Apply Niblack thresholding with a window size of 9 and k=0.2
threshold = filters.threshold_niblack(image_gray, window_size=9, k=0.2)

# Use the threshold to segment the image
binary_image = image_gray > threshold

# Plot the original image and the result
fig, axes = plt.subplots(1, 2, figsize=(10, 5))
ax = axes.ravel()

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

# Display the results
ax[1].imshow(binary_image, cmap='gray')
ax[1].set_title('Niblack Threshold')
ax[1].axis('off')

plt.tight_layout()
plt.show()

Output

Niblack and Sauvola Threshold

Using the skimage.filters.threshold_sauvola() function

The filters.threshold_sauvola() function applies the Sauvola local thresholding technique to a grayscale image. This method is a modification of the Niblack technique.

In the original method, a threshold T is calculated for every pixel in the image using the following formula:

T = m(x, y) * (1 + k * ((s(x, y) / R) - 1))

The values m(x,y) and s(x,y) represent the mean and standard deviation of the pixel neighborhood defined by a rectangular window with size w times w centered around the pixel (x, y). And k is a configurable parameter that weights the effect of standard deviation. And R is the maximum standard deviation of a grayscale image.

Syntax

Following is the syntax of this function −

skimage.filters.threshold_sauvola(image, window_size=15, k=0.2, r=None)

Parameters

The function accepts the following parameters −

  • image (N, M[, …, P]) ndarray: This is the grayscale input image on which the Niblack thresholding will be applied.
  • window_size (int or iterable of int, optional): This parameter specifies the size of the window. It can be a single odd integer (3, 5, 7, ...) or an iterable of odd integers of length equal to the image.ndim (e.g., (1, 5, 5)).
  • k (float, optional): This is the value of the parameter 'k' in the thresholding formula.
  • r (float, optional): This parameter represents 'R,' which is the dynamic range of standard deviation. If set to None, it is automatically calculated as half of the image dtype range.

Return value

The function returns a threshold mask(ndarray) of the same shape as the input image (N, M). All pixels with an intensity higher than this threshold value are assumed to be part of the foreground −

Example

Here's an example of how to use the filters.threshold_sauvola() function to perform Sauvola thresholding on an image −

from skimage import io, color, filters
import matplotlib.pyplot as plt

# Load an image
image = io.imread('Images/black rose.jpg')

# Convert the image to grayscale
image_gray = color.rgb2gray(image)

# Apply Sauvola thresholding with a window size of 9, k=0.2, and auto-calculated R
threshold = filters.threshold_sauvola(image_gray, window_size=9, k=0.2)

# Use the threshold to segment the image
binary_image = image_gray > threshold

# Plot the original image and the result
fig, axes = plt.subplots(1, 2, figsize=(10, 5))
ax = axes.ravel()

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

# Display the results
ax[1].imshow(binary_image, cmap='gray')
ax[1].set_title('Sauvola Threshold')
ax[1].axis('off')

plt.tight_layout()
plt.show()

Output

Niblack and Sauvola Threshold

Example

The following example calculates thresholds using both the "Niblack" and "Sauvola" methods and creates binary images based on these thresholds −

import matplotlib.pyplot as plt
from skimage import io, color, data, filters

# Load an image 
image = io.imread('Images/text_image2.jpg')

# Convert the image to grayscale
image_gray = color.rgb2gray(image)

# Define the window size
window_size = 33

# Calculate thresholds using Niblack and Sauvola methods
thresh_niblack = filters.threshold_niblack(image_gray, window_size=window_size, k=0.8)
thresh_sauvola = filters.threshold_sauvola(image_gray, window_size=window_size)

# Generate binary images using the calculated thresholds
binary_niblack = image_gray > thresh_niblack
binary_sauvola = image_gray > thresh_sauvola

# Plot the original image and the results
fig, axes = plt.subplots(1, 3, figsize=(15, 5))
ax = axes.ravel()

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

# Display the Niblack Threshold result
ax[1].imshow(binary_niblack, cmap='gray')
ax[1].set_title('Niblack Threshold')
ax[1].axis('off')

# Display the Sauvola Threshold result
ax[2].imshow(binary_sauvola, cmap='gray')
ax[2].set_title('Sauvola Threshold')
ax[2].axis('off')

plt.tight_layout()
plt.show()

Output

Niblack and Sauvola Threshold
Advertisements