Source code for ultrasound_metrics.metrics.snr
"""
Signal-to-Noise Ratio (SNR) metric for ultrasound, commonly used for speckle.
This module provides functions to calculate the Signal-to-Noise Ratio (SNR)
for ultrasound speckle patterns. The SNR is calculated as mean/standard-deviation.
References
----------
.. [1] C. B. Burckhardt, "Speckle in Ultrasound B-mode Scans," in IEEE Transactions
on Sonics and Ultrasonics, vol. 25, no. 1, pp. 1-6, Jan. 1978,
doi: 10.1109/T-SU.1978.30978.
.. [2] D. Perdios, M. Vonlanthen, F. Martinez, M. Arditi and J. -P. Thiran,
"CNN-Based Image Reconstruction Method for Ultrafast Ultrasound Imaging,"
in IEEE Transactions on Ultrasonics, Ferroelectrics, and Frequency Control,
vol. 69, no. 4, pp. 1154-1168, April 2022, doi: 10.1109/TUFFC.2021.3131383.
"""
import warnings
from array_api_compat import array_namespace
from beartype import beartype as typechecker
from jaxtyping import Num, jaxtyped
from .._utils.array_api import ArrayAPIObj
@jaxtyped(typechecker=typechecker)
[docs]
def snr(
values: Num[ArrayAPIObj, " *pixels"],
*,
db: bool = False,
) -> float:
"""
Calculate Signal-to-Noise Ratio (SNR) of an image.
This function computes the Signal-to-Noise Ratio (SNR) for ultrasound speckle
patterns by calculating mean/standard-deviation.
This metric provides a single value per ROI/image.
.. math::
\\text{SNR} = \\frac{\\mathbb{E}[X]}{\\sqrt{\\text{Var}(X)}}
where:
- :math:`\\mathbb{E}[X]` is the mean (average pixel value) across the (post-envelope) image
- :math:`\\text{Var}(X)` is the variance of pixel values across the (post-envelope) image
In ultrasound, the statistics of fully developed speckle signals
(post envelope detection) follow a Rayleigh distribution, and
the SNR of a Rayleigh distribution is equal to:
.. math::
\\text{SNR}_{\\text{Rayleigh}} = \\sqrt{\\frac{\\pi}{4 - \\pi}} \\approx 1.91
Parameters
----------
values : array
Input values.
- spatial dimensions are flattened
- Can be real or complex floating-point data
db : bool, optional
If True, return the SNR in decibels (dB). Default is False.
Returns
-------
float
Signal-to-Noise Ratio (SNR) of the values. If ``db=True``, the SNR is returned in decibels (dB).
Warns
-----
UserWarning
If variance is zero (would cause division by zero).
Notes
-----
- This implementation is an amplitude ratio, not a power ratio.
- Complex data is handled by computing the magnitude (absolute value) before processing
- For Rayleigh-distributed speckle, the theoretical SNR is approximately 1.91
- If ROI is used, it should be applied to the input values before calling this function
"""
xp = array_namespace(values)
if values.ndim < 1:
raise ValueError(f"Values must have at least 1 dimension, got {values.ndim}")
# SNR operates on the envelope of the values
values = xp.abs(values)
mean = xp.mean(values)
std = xp.std(values)
if bool(std == 0):
warnings.warn(
"Standard deviation is zero. This will cause division by zero. Check if your values have sufficient variation.",
UserWarning,
)
snr_value = mean / std
if db:
snr_value = 20.0 * xp.log10(snr_value)
return float(snr_value)