Filtering data
The qim3d library provides a set of methods for filtering volumes.
qim3d.filters.Pipeline
Orchestrates a sequential chain of image processing operations.
This class allows you to build a reproducible workflow (or pipeline) by stacking multiple filters or functions together.
The output of one step becomes the input to the next. It supports standard Python callables (functions, lambdas) and qim3d.filters.Filter objects. It is particularly useful for automating preprocessing routines, such as applying denoising, followed by thresholding, and finally morphological operations.
Key Features:
- Flexibility: Accepts any callable that takes a single argument (the image) and returns a modified result.
- Intermediate Results: Access data from specific steps in the middle of the chain using the
save_output=Trueflag on supported filters. - Extensibility: Add steps dynamically using the
.append()method.
Example
import qim3d
from qim3d.filters import Pipeline, Filter, Sobel, Threshold
from scipy import ndimage
# Get data
vol = qim3d.examples.bone_128x128x128.astype('int64')
# Show original
qim3d.viz.slices_grid(vol, num_slices=5)
# Create filter pipeline
pipeline = Pipeline(
Sobel(save_output = True),
Threshold(600),
)
# Add another filter to the pipeline
pipeline.append(Filter(ndimage.binary_opening))
# Apply the filter pipeline
filtered_vol = pipeline(vol)
# Show middle step
qim3d.viz.slices_grid(pipeline.saved_outputs[0], num_slices=5)
# Show filtered result
qim3d.viz.slices_grid(filtered_vol, num_slices=5)
Source code in qim3d/filters/_common_filter_methods.py
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 | |
qim3d.filters.Pipeline.append
Adds a new processing step to the end of the pipeline.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fn
|
FilterBase or Callable
|
The filter or function to append. |
required |
Example
Source code in qim3d/filters/_common_filter_methods.py
qim3d.filters.gaussian
Applies a Gaussian blur to smooth the 3D volume and reduce noise.
This function acts as a low-pass filter, effectively attenuating high-frequency noise (denoising) while blurring edges. The function wraps scipy.ndimage.gaussian_filter for standard processing and dask_image.ndfilters.gaussian_filter for parallelized, memory-efficient computation on large datasets.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
volume
|
ndarray
|
The input 3D image stack. |
required |
sigma
|
float or sequence of floats
|
The standard deviation for the Gaussian kernel. This controls the amount of blurring; higher values result in a smoother image. Can be a single float (isotropic) or a sequence (anisotropic) for each axis. |
required |
dask
|
bool
|
If |
False
|
chunks
|
int, tuple, or str
|
The chunk size for Dask processing (e.g., 'auto'). Only used if |
'auto'
|
**kwargs
|
Any
|
Additional keyword arguments passed to the underlying Gaussian filter function (e.g., |
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
filtered_vol |
ndarray
|
The smoothed volume. |
Example
import qim3d
# Apply filter
vol = qim3d.examples.shell_225x128x128
vol_filtered = qim3d.filters.gaussian(vol, sigma=3, dask=True)
# Show original and filtered volumes
qim3d.viz.slices_grid(vol, n_slices=5, display_figure=True)
qim3d.viz.slices_grid(vol_filtered, n_slices=5, display_figure=True)
Source code in qim3d/filters/_common_filter_methods.py
qim3d.filters.median
Applies a median filter to remove impulse noise (salt-and-pepper) while preserving edges.
This non-linear filter replaces each voxel with the median value of its neighbors. Unlike Gaussian blurring, which can fuzzy boundaries, the median filter is particularly effective at despeckling images (removing isolated bright or dark outliers) without blurring sharp transitions or structural details. It supports both standard in-memory processing and parallelized execution via Dask for large datasets.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
volume
|
ndarray
|
The input 3D image stack or 2D image. |
required |
size
|
int or tuple
|
The shape of the neighborhood (kernel) used for the median calculation. Can be a single integer (e.g., |
None
|
footprint
|
ndarray
|
A boolean array defining a custom neighborhood shape. Only elements where |
None
|
dask
|
bool
|
If |
False
|
chunks
|
int, tuple, or str
|
The chunk size for Dask processing. Defaults to 'auto'. |
'auto'
|
**kwargs
|
Any
|
Additional keyword arguments passed to the underlying filter function (e.g., |
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
filtered_vol |
ndarray
|
The denoised volume. |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If neither |
Example
import qim3d
# Generate a noisy volume
vol = qim3d.generate.volume(noise_scale = 0.015)
noisy_vol = qim3d.generate.background(background_shape = vol.shape, max_noise_value = 80, apply_method = 'add', apply_to = vol)
# Apply filter
vol_filtered = qim3d.filters.median(noisy_vol, size=5, dask=True)
# Show original and filtered volumes
qim3d.viz.slices_grid(noisy_vol, n_slices=5, slice_positions = [10, 31, 63, 95, 120], display_figure=True)
qim3d.viz.slices_grid(vol_filtered, n_slices=5, slice_positions = [10, 31, 63, 95, 120], display_figure=True)
Source code in qim3d/filters/_common_filter_methods.py
qim3d.filters.sobel
Computes the magnitude of the intensity gradient using the Sobel operator to detect edges.
This function approximates the gradient of the image intensity function. It applies the Sobel filter along each axis independently (Gx, Gy, Gz) and computes the Euclidean magnitude (sqrt(Gx^2 + Gy^2 + Gz^2)). High values in the output correspond to regions with sharp intensity changes, effectively highlighting boundaries and edges within the volume.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
vol
|
ndarray
|
The input image or volume. |
required |
dask
|
bool
|
If |
False
|
Returns:
| Name | Type | Description |
|---|---|---|
filtered_vol |
ndarray
|
The gradient magnitude map. |
Note
Data Type Warning: The Sobel operator can produce negative values and large magnitudes. If the input vol is of an unsigned integer type (e.g., uint8, uint16), arithmetic overflow or wrapping may occur during calculation. It is strongly recommended to cast the input to a float or signed integer type (e.g., int64 or float32) before applying this filter.
Example
import qim3d
# Cast to int64 to prevent overflow during gradient calculation
vol = qim3d.examples.bone_128x128x128.astype('int64')
filtered_vol = qim3d.filters.sobel(vol)
qim3d.viz.slices_grid(vol, num_slices=5)
qim3d.viz.slices_grid(filtered_vol, num_slices=5)
Source code in qim3d/filters/_common_filter_methods.py
qim3d.filters.maximum
Applies a maximum filter (grayscale dilation) to the input volume.
This operation replaces the value of each voxel with the maximum value found within its defined neighborhood. It results in the expansion (dilation) of bright regions and the erosion of dark regions. It is commonly used for finding local peaks, reducing salt noise (dark spots in bright regions), or as the first step in morphological gradients.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
volume
|
ndarray
|
The input image or volume. |
required |
size
|
int or tuple
|
The size of the neighborhood window (kernel). Must be provided if |
None
|
footprint
|
ndarray
|
A boolean array defining the specific shape of the neighborhood. Elements where |
None
|
dask
|
bool
|
If |
False
|
chunks
|
int, tuple, or str
|
The chunk size for Dask arrays. Defaults to 'auto'. |
'auto'
|
**kwargs
|
Any
|
Additional keyword arguments passed to the underlying filter function (e.g., |
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
filtered_vol |
ndarray
|
The filtered volume with the same shape as the input. |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If neither |
Example
import qim3d
vol = qim3d.examples.fly_150x256x256
vol_filtered = qim3d.filters.maximum(vol, size=6, dask=True)
# Show original and filtered volumes
qim3d.viz.slices_grid(vol, n_slices=5, display_figure=True)
qim3d.viz.slices_grid(vol_filtered, n_slices=5, display_figure=True)
Source code in qim3d/filters/_common_filter_methods.py
qim3d.filters.minimum
Applies a minimum filter (grayscale erosion) to the input volume.
This operation replaces the value of each voxel with the minimum value found within its defined neighborhood. It results in the erosion of bright regions and the expansion (dilation) of dark regions. It is commonly used to remove salt noise (isolated bright pixels), darken the overall image, or separate touching objects in bright foregrounds.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
volume
|
ndarray
|
The input image or volume. |
required |
size
|
int or tuple
|
The size of the neighborhood window (kernel). Must be provided if |
None
|
footprint
|
ndarray
|
A boolean array defining the specific shape of the neighborhood. Elements where |
None
|
dask
|
bool
|
If |
False
|
chunks
|
int, tuple, or str
|
The chunk size for Dask arrays. Defaults to 'auto'. |
'auto'
|
**kwargs
|
Any
|
Additional keyword arguments passed to the underlying filter function. |
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
filtered_vol |
ndarray
|
The filtered volume with the same shape as the input. |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If neither |
Example
import qim3d
vol = qim3d.examples.shell_225x128x128
vol_filtered = qim3d.filters.minimum(vol, size=3, dask=True)
qim3d.viz.slices_grid(vol, n_slices=5, slice_positions = [10, 31, 63, 95, 120], display_figure=True)
qim3d.viz.slices_grid(vol_filtered, n_slices=5, slice_positions = [10, 31, 63, 95, 120], display_figure=True)
Source code in qim3d/filters/_common_filter_methods.py
qim3d.filters.tophat
Applies a morphological opening (or closing) to estimate the background or smooth features.
Despite the name, this function uses the Top-Hat transform intermediate to perform a Morphological Opening (for dark backgrounds) or Closing (for bright backgrounds).
- Dark Background (Bright Objects): Performs an Opening. This removes bright features smaller than the
radius(e.g., noise, small particles), effectively estimating the underlying background intensity. - Bright Background (Dark Objects): Performs a Closing. This fills in dark features smaller than the
radius, estimating the background in inverted contrast.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
volume
|
ndarray
|
The input image or volume. |
required |
dask
|
bool
|
Not currently supported for this filter; defaults to SciPy implementation. |
False
|
**kwargs
|
Any
|
|
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
filtered_vol |
ndarray
|
The processed volume (the background estimation). |
Example
import qim3d
vol = qim3d.examples.cement_128x128x128
vol_filtered = qim3d.filters.tophat(vol, radius = 7, background = 'bright')
qim3d.viz.slices_grid(vol, n_slices=5, slice_positions = [10, 31, 63, 95, 120], display_figure=True)
qim3d.viz.slices_grid(vol_filtered, n_slices=5, slice_positions = [10, 31, 63, 95, 120], display_figure=True)