linumpy.intensity.normalization#
Intensity normalization functions for OCT volumes.
This module provides functions for normalizing OCT volume intensities based on agarose background detection.
Functions#
|
Normalize volume intensities based on agarose background. |
|
Compute agarose mask using Otsu thresholding on a mean projection. |
|
Compute per-Z-plane linear scale factors for percentile-based normalization. |
|
Apply per-section histogram matching to a global reference distribution. |
|
Remove residual per-Z-plane intensity jitter via a smoothed scalar gain. |
Module Contents#
- linumpy.intensity.normalization.normalize_volume(vol, agarose_mask, percentile_max=99.9)[source]#
Normalize volume intensities based on agarose background.
Each z-slice is clipped at its per-slice percentile cap and agarose-median floor, then the agarose floor is subtracted per slice (so background goes to exactly 0). The entire volume is then divided by a single global divisor (the maximum per-slice tissue span across all slices), so relative inter-section brightness is preserved.
- Parameters:
vol (np.ndarray) – Input volume with shape (Z, Y, X).
agarose_mask (np.ndarray) – 2D binary mask indicating agarose regions (shape Y, X).
percentile_max (float) – Values above this percentile will be clipped per slice. Default 99.9.
- Returns:
(normalized_volume, background_thresholds) - normalized_volume: float32 volume in [0, 1] with agarose at 0. - background_thresholds: Array of agarose-median per slice.
- Return type:
- linumpy.intensity.normalization.get_agarose_mask(vol, smoothing_sigma=1.0)[source]#
Compute agarose mask using Otsu thresholding on a mean projection.
The agarose is the low-intensity background surrounding the tissue. Uses a Gaussian-smoothed mean projection through Z to get a robust 2D estimate, then thresholds with Otsu.
- Parameters:
vol (np.ndarray) – 3D volume with shape (Z, Y, X).
smoothing_sigma (float) – Gaussian smoothing sigma applied before Otsu thresholding.
- Returns:
agarose_mask (np.ndarray) – 2D boolean mask (Y, X) – True where agarose is present.
threshold (float) – The Otsu threshold used.
- Return type:
- linumpy.intensity.normalization.compute_scale_factors(vol, n_serial_slices, smooth_sigma, percentile, min_scale, max_scale)[source]#
Compute per-Z-plane linear scale factors for percentile-based normalization.
Corrects slow acquisition drift (focus changes, laser power) between serial sections while preserving genuine anatomical intensity differences.
- Parameters:
vol (np.ndarray) – Input volume (Z, Y, X) in [0, 1].
n_serial_slices (int or None) – Number of serial sections. None = operate at individual Z-plane level.
smooth_sigma (float) – Gaussian smoothing sigma in serial-section units.
percentile (float) – Percentile of non-zero voxels used as intensity reference per chunk.
min_scale (float) – Clamping range for scale factors.
max_scale (float) – Clamping range for scale factors.
- Returns:
scale_factors (np.ndarray, shape (n_z,))
raw_metrics (np.ndarray)
smoothed (np.ndarray)
boundaries (list of int)
- Return type:
- linumpy.intensity.normalization.apply_histogram_matching(vol, n_serial_slices, n_bins, tissue_threshold=0.0, use_gpu=False)[source]#
Apply per-section histogram matching to a global reference distribution.
Corrects section-to-section intensity drift while preserving relative contrast within each section. Voxels at or below tissue_threshold are left unchanged.
- Parameters:
vol (np.ndarray) – Input volume (Z, Y, X).
n_serial_slices (int or None) – Number of serial sections. None = per Z-plane.
n_bins (int) – Number of histogram bins.
tissue_threshold (float) – Minimum intensity to classify as tissue (default 0.0).
use_gpu (bool) – If True, run the per-chunk matching loop on GPU via CuPy. Falls back to CPU silently if CuPy is unavailable. The volume itself is moved to GPU one chunk at a time, so memory usage stays bounded.
- Returns:
Histogram-matched volume.
- Return type:
np.ndarray
- linumpy.intensity.normalization.apply_zprofile_smoothing(vol, mask, sigma, min_tissue_voxels=100)[source]#
Remove residual per-Z-plane intensity jitter via a smoothed scalar gain.
For each Z-plane, computes the tissue mean (over mask), smooths the Z-mean profile with a Gaussian (sigma in Z-plane units), then applies a per-Z multiplicative gain target / observed to align each plane’s tissue mean to the smoothed trend. Background voxels (~mask) are left unchanged.
The correction is bounded in magnitude by the smoothed-vs-observed ratio and acts only on the high-frequency component of the Z-profile, so the smooth depth attenuation and large-scale anatomical variation are preserved. Best applied after apply_histogram_matching to clean up the residual ~1-2% inter-slice step that HM cannot remove.
- Parameters:
vol (np.ndarray) – Input volume (Z, Y, X).
mask (np.ndarray) – Tissue mask (Z, Y, X), bool.
sigma (float) – Gaussian smoothing sigma in Z-plane units. Larger = preserves more depth structure but removes less jitter. 2.0-4.0 works well in practice.
min_tissue_voxels (int) – Z-planes with fewer tissue voxels are left unchanged (no reliable mean).
- Returns:
Volume with per-Z gain applied to tissue voxels.
- Return type:
np.ndarray