Status: Needs Review
This page has not been reviewed for accuracy and completeness. Content may be outdated or contain errors.
Statistical Nodes¶
This category groups current classical anomaly and spectral analysis nodes.
RX And LAD¶
rx_detector
¶
RX anomaly detection nodes for hyperspectral imaging.
This module implements the Reed-Xiaoli (RX) anomaly detection algorithm, a widely used statistical method for detecting anomalies in hyperspectral images. The RX algorithm computes squared Mahalanobis distance from the background distribution, treating pixels with large distances as potential anomalies.
The module provides two variants:
-
RXGlobal: Uses global statistics (mean, covariance) estimated from training data. Supports two-phase training: statistical initialization followed by optional gradient-based fine-tuning via unfreeze().
-
RXPerBatch: Computes statistics independently for each batch on-the-fly without requiring initialization. Useful for real-time processing or when training data is unavailable.
Reference: Reed, I. S., & Yu, X. (1990). "Adaptive multiple-band CFAR detection of an optical pattern with unknown spectral distribution." IEEE Transactions on Acoustics, Speech, and Signal Processing, 38(10), 1760-1770.
RXBase
¶
RXGlobal
¶
Bases: RXBase
RX anomaly detector with global background statistics.
Uses global mean (μ) and covariance (Σ) estimated from training data to compute Mahalanobis distance scores. Supports two-phase training: statistical initialization followed by optional gradient-based fine-tuning.
The detector computes anomaly scores as:
RX(x) = (x - μ)ᵀ Σ⁻¹ (x - μ)
where x is a pixel spectrum, μ is the background mean, and Σ is the covariance matrix.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
num_channels
|
int
|
Number of spectral channels in input data |
required |
eps
|
float
|
Small constant added to covariance diagonal for numerical stability (default: 1e-6) |
1e-06
|
cache_inverse
|
bool
|
If True, precompute and cache Σ⁻¹ for faster inference (default: True) |
True
|
**kwargs
|
dict
|
Additional arguments passed to Node base class |
{}
|
Attributes:
| Name | Type | Description |
|---|---|---|
mu |
Tensor or Parameter
|
Background mean spectrum, shape (C,). Initially a buffer, becomes Parameter after unfreeze() |
cov |
Tensor or Parameter
|
Background covariance matrix, shape (C, C) |
cov_inv |
Tensor or Parameter
|
Cached pseudo-inverse of covariance (if cache_inverse=True) |
_statistically_initialized |
bool
|
Flag indicating whether statistical_initialization() has been called |
Examples:
>>> from cuvis_ai.anomaly.rx_detector import RXGlobal
>>> from cuvis_ai_core.training import StatisticalTrainer
>>>
>>> # Create RX detector
>>> rx = RXGlobal(num_channels=61, eps=1.0e-6)
>>>
>>> # Phase 1: Statistical initialization
>>> stat_trainer = StatisticalTrainer(pipeline=pipeline, datamodule=datamodule)
>>> stat_trainer.fit() # Computes μ and Σ from training data
>>>
>>> # Inference with frozen statistics
>>> output = rx.forward(data=hyperspectral_cube)
>>> scores = output["scores"] # [B, H, W, 1]
>>>
>>> # Phase 2: Optional gradient-based fine-tuning
>>> rx.unfreeze() # Convert buffers to nn.Parameters
>>> # Now μ and Σ can be updated with gradient descent
See Also
RXPerBatch : Per-batch RX variant without training MinMaxNormalizer : Recommended preprocessing before RX ScoreToLogit : Convert scores to logits for classification docs/tutorials/rx-statistical.md : Complete RX pipeline tutorial
Notes
After statistical_initialization(), mu and cov are stored as buffers (frozen by default). Call unfreeze() to convert them to trainable nn.Parameters for gradient-based optimization.
Source code in cuvis_ai/anomaly/rx_detector.py
statistical_initialization
¶
Initialize mu and Sigma from data iterator.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
input_stream
|
InputStream
|
Iterator yielding dicts matching INPUT_SPECS (port-based format) Expected format: {"data": tensor} where tensor is BHWC |
required |
Source code in cuvis_ai/anomaly/rx_detector.py
update
¶
Update streaming statistics with a new batch.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
batch_bhwc
|
Tensor
|
Input batch in BHWC format, shape (B, H, W, C) |
required |
Source code in cuvis_ai/anomaly/rx_detector.py
finalize
¶
Compute final mean and covariance from accumulated streaming statistics.
This method converts the running accumulators (_mean, _M2) into the final mean (mu) and covariance (cov) matrices. The covariance is regularized with eps * I for numerical stability, and optionally caches the pseudo-inverse.
Returns:
| Type | Description |
|---|---|
RXGlobal
|
Returns self for method chaining |
Raises:
| Type | Description |
|---|---|
ValueError
|
If fewer than 2 samples were accumulated (insufficient for covariance estimation) |
Notes
After finalization, mu and cov are stored as buffers (frozen by default). Call unfreeze() to convert them to nn.Parameters for gradient-based training.
Source code in cuvis_ai/anomaly/rx_detector.py
reset
¶
Reset all statistics and accumulators to empty state.
Clears mu, cov, cov_inv, and all streaming accumulators (_mean, _M2, _n). After reset, the detector must be re-initialized via statistical_initialization() before it can be used for inference.
Notes
Use this method when you need to re-initialize the detector with different training data or when switching between different dataset distributions.
Source code in cuvis_ai/anomaly/rx_detector.py
forward
¶
Forward pass computing anomaly scores.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
Tensor
|
Input tensor in BHWC format |
required |
Returns:
| Type | Description |
|---|---|
dict[str, Tensor]
|
Dictionary with "scores" key containing BHW1 anomaly scores |
Source code in cuvis_ai/anomaly/rx_detector.py
RXPerBatch
¶
Bases: RXBase
Computes μ, Σ per image in the batch on the fly; no fit/finalize.
Source code in cuvis_ai/anomaly/rx_detector.py
forward
¶
Forward pass computing per-batch anomaly scores.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
Tensor
|
Input tensor in BHWC format |
required |
Returns:
| Type | Description |
|---|---|
dict[str, Tensor]
|
Dictionary with "scores" key containing BHW1 anomaly scores |
Source code in cuvis_ai/anomaly/rx_detector.py
lad_detector
¶
Laplacian Anomaly Detector (LAD) for hyperspectral anomaly detection.
This module implements the Laplacian Anomaly Detector, a graph-based approach for detecting spectral anomalies in hyperspectral images. LAD constructs a spectral graph using Cauchy similarity weights and computes anomaly scores based on the graph Laplacian.
The LAD algorithm identifies anomalies by measuring how unusual a pixel's spectral signature is within the spectral manifold learned from background data. Unlike RX detectors that assume Gaussian distributions, LAD captures nonlinear manifold structures through graph construction.
Reference: Gu, Y., Liu, Y., & Zhang, Y. (2008). "A selective KPCA algorithm based on high-order statistics for anomaly detection in hyperspectral imagery." IEEE Geoscience and Remote Sensing Letters, 5(1), 43-47.
LADGlobal
¶
Bases: Node
Laplacian Anomaly Detector (global), variant 'C' (Cauchy), port-based.
This is the new cuvis.ai v3 implementation of the LAD detector. It follows the
same mathematical definition as the legacy v2 LADGlobal, but exposes a
port-based interface compatible with CuvisPipeline, StatisticalTrainer,
and GradientTrainer.
Ports
INPUT_SPECS
data : float32, shape (-1, -1, -1, -1)
Input hyperspectral cube in BHWC format.
OUTPUT_SPECS
scores : float32, shape (-1, -1, -1, 1)
Per pixel anomaly scores in BHW1 format.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
eps
|
float
|
Small epsilon value for numerical stability in Laplacian construction. |
1e-8
|
normalize_laplacian
|
bool
|
If True, applies symmetric normalization: L = D^{-½} (D - A) D^{-½}. If False, uses unnormalized Laplacian: L = D - A. |
True
|
use_numpy_laplacian
|
bool
|
If True, constructs the Laplacian matrix using NumPy (float64, 1e-12 eps) for parity with reference implementations. If False, uses pure PyTorch. |
True
|
Training
After statistical initialization via statistical_initialization(), the node can be made trainable
by calling unfreeze(). This converts the mean M and Laplacian L buffers
to trainable nn.Parameter objects, enabling gradient-based fine-tuning.
Example
lad = LADGlobal(num_channels=61) stat_trainer = StatisticalTrainer(pipeline=pipeline, datamodule=datamodule) stat_trainer.fit() # Statistical initialization lad.unfreeze() # Enable gradient training grad_trainer = GradientTrainer(pipeline=pipeline, datamodule=datamodule, ...) grad_trainer.fit() # Gradient-based fine-tuning
Source code in cuvis_ai/anomaly/lad_detector.py
statistical_initialization
¶
Compute global mean M and Laplacian L from a port-based input stream.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
input_stream
|
InputStream
|
Iterator yielding dicts matching INPUT_SPECS.
Expected format: |
required |
Source code in cuvis_ai/anomaly/lad_detector.py
update
¶
Update running mean statistics from a BHWC batch.
Source code in cuvis_ai/anomaly/lad_detector.py
finalize
¶
Finalize mean and Laplacian from accumulated statistics.
Source code in cuvis_ai/anomaly/lad_detector.py
reset
¶
Reset all statistics and model parameters to initial state.
Clears the streaming mean accumulator (_mean_run), sample count (_count), global mean (M), and Laplacian matrix (L). After reset, the detector must be re-initialized via statistical_initialization() before inference.
Notes
Use this method to re-initialize the detector with different training data or when switching between different spectral distributions.
Source code in cuvis_ai/anomaly/lad_detector.py
forward
¶
Compute LAD anomaly scores for a BHWC cube.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
Tensor
|
Input tensor in BHWC format. |
required |
Returns:
| Type | Description |
|---|---|
dict[str, Tensor]
|
Dictionary with key |
Source code in cuvis_ai/anomaly/lad_detector.py
Spectral Angle Mapper¶
spectral_angle_mapper
¶
Spectral Angle Mapper node.
SpectralAngleMapper
¶
Bases: Node
Compute per-pixel spectral angle against one or more reference spectra.
Source code in cuvis_ai/node/spectral_angle_mapper.py
forward
¶
Run spectral-angle scoring for all references.
Source code in cuvis_ai/node/spectral_angle_mapper.py
Spectral Extraction¶
spectral_extractor
¶
Spectral signature extraction nodes for hyperspectral cubes.
BBoxSpectralExtractor
¶
BBoxSpectralExtractor(
center_crop_scale=0.65,
min_crop_pixels=4,
trim_fraction=0.1,
l2_normalize=True,
aggregation="median",
**kwargs,
)
Bases: Node
Extract per-bbox spectral signatures with trimmed median/mean and std.
Given an HSI cube [B, H, W, C] and detection bboxes [B, N, 4]
(xyxy format), extracts a center-cropped spectral signature for each bbox.
Outputs the per-band aggregated signature, per-band std, and a binary
validity mask.
Source code in cuvis_ai/node/spectral_extractor.py
forward
¶
Extract per-bbox spectral signatures for the first batch element.
Source code in cuvis_ai/node/spectral_extractor.py
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 | |
SpectralSignatureExtractor
¶
SpectralSignatureExtractor(
trim_fraction=0.1,
min_mask_pixels=10,
zero_norm_threshold=1e-08,
**kwargs,
)
Bases: Node
Extract per-object spectral signatures from SAM-style label masks.
Source code in cuvis_ai/node/spectral_extractor.py
forward
¶
Extract per-object signatures for the first batch element.