pixtreme.metrics
metrics
Image quality measurements.
__all__ = ('psnr', 'ssim', 'ssim_map')
module-attribute
psnr(reference, candidate, *, data_range=1.0)
Return full-reference peak signal-to-noise ratio on the GPU.
Exact signature: px.metrics.psnr(reference, candidate, *, data_range=1.0).
Both inputs must be float32 Frame objects whose height, width, channels,
colorspace, gamma, and matrix match literally. data_range is the
caller-declared positive finite signal range and defaults to 1.0; it is not
inferred from pixels, dtype, or metadata. Across all channels and spatial
samples at once, MSE = sum((reference - candidate)**2) / (H * W * C)
and PSNR = 10 * log10(data_range**2 / MSE). Exact finite matches return
+inf. The float32 calculation does not clamp scene values or scan and
replace non-finite inputs.
The result is a private 0D float32 cupy.ndarray with new storage and no
Frame metadata. It is GPU-resident and this call does not mutate either
input. Choosing float(result) or result.item() performs explicit
synchronization to obtain a host scalar. Convert non-float32 storage
according to its meaning with px.values.cast_dtype,
px.values.recode_dtype, or px.values.dequantize. To measure luma,
apply px.color.rgb_to_grayscale to both inputs first; use
px.channel.shuffle for explicit channel selection or routing.
ssim(reference, candidate, *, data_range=1.0)
Return the spatial mean of the valid full-reference SSIM map on the GPU.
Exact signature: px.metrics.ssim(reference, candidate, *, data_range=1.0).
Both inputs must be float32 Frame objects whose height, width, channels,
colorspace, gamma, and matrix match literally. data_range is the
caller-declared positive finite signal range and defaults to 1.0; pixels
are never used to infer it. The metric uses a normalized 11x11 Gaussian
window with sigma=1.5, weighted population variance and covariance,
C1 = (0.01 * data_range)**2, and C2 = (0.03 * data_range)**2.
It evaluates each channel independently, takes the channel mean at each
valid position, then takes the float32 spatial mean over all channels'
local contributions. It does not clamp scene values or replace non-finite
inputs.
The result is a private 0D float32 cupy.ndarray with new storage and no
Frame metadata. It is GPU-resident and this call does not mutate either
input. Choosing float(result) or result.item() performs explicit
synchronization to obtain a host scalar. Convert non-float32 storage
according to its meaning with px.values.cast_dtype,
px.values.recode_dtype, or px.values.dequantize. To measure luma,
apply px.color.rgb_to_grayscale to both inputs first; use
px.channel.shuffle for explicit channel selection or routing.
ssim_map(reference, candidate, *, data_range=1.0)
Return the valid full-reference SSIM response map on the GPU.
Exact signature: px.metrics.ssim_map(reference, candidate, *, data_range=1.0).
Both inputs must be float32 Frame objects whose height, width, channels,
colorspace, gamma, and matrix match literally. data_range is the
caller-declared positive finite signal range and defaults to 1.0; pixels
are never used to infer it. Each valid 11x11 Gaussian window uses
sigma=1.5, weighted population variance and covariance,
C1 = (0.01 * data_range)**2, and C2 = (0.03 * data_range)**2.
The expression is evaluated independently for all channels, followed by a
channel mean. There is no padding: HWC input produces the 2D shape
(H - 10, W - 10). The calculation does not clamp scene values or
replace non-finite inputs.
The result is a private C-contiguous 2D float32 cupy.ndarray with new
storage and no Frame metadata, and this call does not mutate either input.
Convert non-float32 storage according to its meaning with
px.values.cast_dtype, px.values.recode_dtype, or
px.values.dequantize. For visualization, add a length-one channel
dimension and call px.io.from_array with explicit metadata. To measure
luma, apply px.color.rgb_to_grayscale to both inputs first; use
px.channel.shuffle for explicit channel selection or routing.