Scikit Image − Removing Small Holes from an Image



Removing Small Holes from an Image" is a common image processing operation that is used to eliminate small holes (represented by value 0) within objects (represented by any other single value, typically 1) in binary images or segmentation masks. This process involves filling or removing small holes within objects. It improves the quality of the image and makes it suitable for further analysis or visualization.

Scikit-image (skimage) has a remove_small_holes() function in the morphology module that identifies and either fills or removes small holes within objects based on specified size.

Using the skimage.morphology.remove_small_holes() function

The remove_small_holes() function is used to remove small contiguous holes within connected components in a binary image.

Syntax

Following is the syntax of this function −

skimage.morphology.remove_small_holes(ar, area_threshold=64, connectivity=1, *, out=None)

Parameters

The function accepts the following parameters −

  • ar (ndarray): This parameter expects an array, which can be of arbitrary shape and should typically be of integer or boolean type. It is the input image containing the connected components of interest.
  • area_threshold (int, optional, default: 64): This parameter specifies the maximum area, in pixels, that a contiguous hole can have and still be removed. If a hole is smaller than this threshold, it will be filled.
  • connectivity (int, optional, default: 1): This parameter defines the connectivity of the neighborhood of a pixel.
  • out (ndarray, optional): An optional parameter that specifies an ndarray of the same shape as ar and bool data type where the output will be placed. By default, if not provided, an out parameter, a new ndarray is created to store the output.

Return value

The function returns an ndarray of the same shape and type as the input ar. This array will have small holes within connected components removed.

It's important to note that if the input array is of type int, it is assumed that it contains already-labeled objects. However, the labels are not preserved in the output image; the function always outputs a binary (bool) image. If you need to preserve labels, it is suggested that you perform labeling after using this function.

Additionally, the function may raise a TypeError if the input array is of an invalid type (e.g., float or string), and a ValueError if the input array contains negative values, as this function expects only a binary image with 0s and 1s.

Example 1

The following example demonstrates how to remove small holes from an input array using scikit-image morphology.remove_small_holes() function −

import numpy as np
from skimage import morphology, segmentation

# Input array
arr = np.array([
[1, 1, 1, 0, 0],
[1, 0, 1, 0, 0],
[1, 1, 1, 0, 0],
[0, 0, 0, 0, 2],
])
print('Input array:')
print(arr)

# Convert the object image to binary/boolean
binary_array = arr.astype(bool)

# Remove small holes (holes with area < 2) from the binary image
filled_arr = morphology.remove_small_holes(binary_array, 2)

# Use watershed to get objects back, preserving their original IDs
result_arr = segmentation.watershed(filled_arr, arr, mask= filled_arr)

# Print the result
print('Array after removing the holes:')
print(result_arr)

Output

Input array:
[[1 1 1 0 0]
[1 0 1 0 0]
[1 1 1 0 0]
[0 0 0 0 2]]

Array after removing the holes:
[[1 1 1 0 0]
[1 1 1 0 0]
[1 1 1 0 0]
[0 0 0 0 2]]

Example 2

import numpy as np
from skimage import morphology, segmentation, io
import matplotlib.pyplot as plt

# Load an input image
image = np.array([[1, 1, 1, 1, 1, 1],
   [1, 1, 1, 0, 1, 0],
   [1, 1, 1, 1, 1, 0],
   [1, 0, 0, 1, 1, 0],
   [1, 1, 1, 1, 1, 0]], bool)

# Convert the object image to binary/boolean
binary_image = image.astype(bool)

# Remove small holes (holes with area < 2) from the binary image
filled_image = morphology.remove_small_holes(binary_image, 4)

# Use watershed to get objects back, preserving their original IDs
result_image = segmentation.watershed(filled_image, image, mask=filled_image)

# Create subplots for displaying the input and output images
fig, axes = plt.subplots(1, 2, figsize=(10, 5))
ax = axes.ravel()

# Display the input image
ax[0].imshow(image)
ax[0].axis('off')
ax[0].set_title('Input Image')

# Display the resultant image
ax[1].imshow(result_image)
ax[1].axis('off')
ax[1].set_title('resultant image after removing the holes')

plt.tight_layout()
plt.show()

Output

Removing small holes from images
Advertisements