Image processing with scipy.ndimage
Filter, label, measure and transform N-dimensional arrays, with an eye on the coordinate convention that trips everyone up once.
Filtering and morphology
import numpy as np
from scipy import ndimage as ndi
img = np.random.default_rng(0).random((200, 200))
blurred = ndi.gaussian_filter(img, sigma=2.0)
edges = ndi.sobel(blurred, axis=0)
mask = blurred > 0.6
opened = ndi.binary_opening(mask, structure=np.ones((3, 3)), iterations=1)
filled = ndi.binary_fill_holes(opened)
dilated = ndi.binary_dilation(filled, iterations=2)- The default
mode="reflect"pads virtually at the boundary; other options areconstant,nearest,wrapandmirror. sigmais in array index units, not physical units. Convert from physical distance yourself.- Morphology operators need a boolean or integer array; passing a float array silently applies a different rule.
Labelling and measuring regions
labels, n = ndi.label(filled, structure=np.ones((3, 3)))
print("components:", n)
sizes = ndi.sum_labels(np.ones_like(labels), labels, index=np.arange(1, n + 1))
coms = ndi.center_of_mass(filled, labels, index=np.arange(1, n + 1))
objects = ndi.find_objects(labels)
for i, sl in enumerate(objects, start=1):
if sizes[i - 1] < 50: # drop specks
labels[sl][labels[sl] == i] = 0
kept = ndi.label(labels > 0)[1]
print("after filtering:", kept)| Function | Returns |
|---|---|
label | Integer labels plus the count of components |
sum / mean | Per-label or per-axis aggregates |
center_of_mass | Centroid coordinates of each labelled region |
find_objects | Bounding-box slices you can index with |
maximum_position | Coordinate of the brightest pixel per label |
Transforms and interpolation
rotated = ndi.rotate(img, angle=30, reshape=True, order=1)
zoomed = ndi.zoom(img, zoom=2.0, order=3)
shifted = ndi.shift(img, shift=(5, -3), mode="nearest")
matrix = np.array([[1, 0.2, 0], [0, 1, 0], [0, 0, 1]])
sheared = ndi.affine_transform(img, matrix, offset=0.0, order=1)
import matplotlib.pyplot as plt
plt.imshow(sheared, cmap="gray", origin="upper")
plt.axis("off")⚠️
ndimage works on plain arrays in
(row, column) order — index 0 is y, index 1 is x. Coordinates from center_of_mass and maximum_position follow the same convention, so plotting them on an imshow chart means swapping the two values.FAQ
Should I use ndimage or scikit-image?
For filtering, labelling, morphology and geometry on arrays, ndimage is compact and fast. For higher-level work — feature detection, segmentation, region properties, colour-space conversion, reading image files — scikit-image has the richer API and often a clearer result.
Why did binary_opening remove my small objects?
Opening erodes then dilates, so any structure thinner than the structuring element disappears. Reduce the element size, or apply closing instead if the real problem is small holes rather than specks.
Related
FFT and spectral analysis with scipy.fft Statistics and signal processing
Last refreshed 2026-09-18.