Image quality#
- kornia.metrics.psnr(image, target, max_val)[source]#
Compute the peak signal-to-noise ratio (PSNR), in dB, between two images.
score = psnr(image, target, max_val)takes two images of the same shape(*)and their data range \(\text{MAX}_I\), and returns the PSNR for the mean squared error over all \(N\) elements:\[\text{PSNR} = 10 \log_{10} \bigg(\frac{\text{MAX}_I^2}{\text{MSE}}\bigg), \quad \text{MSE} = \frac{1}{N}\sum_{k=1}^{N} (I_k - T_k)^2\]- Convention:
One MSE is pooled over every element, batch and channels included, so for a batch the score is the PSNR of the pooled MSE, not the mean of per-image PSNRs: compute per-image values one image at a time. Losses and metrics maps both onto scikit-image and torchmetrics.
max_valis the data range of the images (1.0for[0, 1],255.0for[0, 255]), not the maximum of the tensor; pixel values are not rescaled.The shapes must match, without broadcasting, and the value is symmetric in the images. Identical inputs give an MSE of 0 and
inf, while a batch with one identical pair stays finite.Integer and bool images are converted to float32 before computing the MSE, so an integer image paired with a half-precision image gives a float32 result. Uint8, int8, int16 and int32 tensor data ranges are widened to int64 before squaring to avoid overflow, except when the promoted image dtype is float16 or bfloat16, which uses float32 range arithmetic.
Float16 and bfloat16 inputs are evaluated in float32 and the result keeps their promoted dtype, also promoted with
max_val.dtypefor a tensor range: a float32 tensor range gives a float32 result for half-precision images.
- Parameters:
- Return type:
- Returns:
the PSNR in dB, a 0-d tensor for a scalar range or with the shape of a tensor range.
See also
psnr_loss(): the negative PSNR, to minimise.PSNRLoss: the module form of that loss.ssim(): a structural measure of the same pair, per pixel and bounded.
Examples
>>> ones = torch.ones(1) >>> psnr(ones, 1.2 * ones, 2.) # 10 * log(4/((1.2-1)**2)) / log(10) tensor(20.0000)
- kornia.metrics.ssim(img1, img2, window_size, max_val=1.0, eps=1e-12, padding='same')[source]#
Compute the per-pixel structural similarity (SSIM) map between two images.
ssim_map = ssim(img1, img2, window_size)takes two(B, C, H, W)images and returns the SSIM index at every pixel, channel and sample; average the map for a score.\[\text{SSIM}(x, y) = \frac{(2\mu_x\mu_y+c_1)(2\sigma_{xy}+c_2)} {(\mu_x^2+\mu_y^2+c_1)(\sigma_x^2+\sigma_y^2+c_2)}\]- Convention:
The window is a sampled Gaussian with \(\sigma = 1.5\) whatever
window_size, which sets only the number of taps and must be odd.padding='same'pads with'reflect', the torch mode that Filtering maps onto OpenCV and scipy, and keeps(H, W);'valid'dropswindow_size // 2pixels on every side and equals the'same'map cropped. Reflected borders extend across any positive spatial axis length, including a singleton axis.max_valis the data range \(L\), a Pythonfloat: \(c_1 = (0.01 L)^2\) and \(c_2 = (0.03 L)^2\). Pixel values are not rescaled, so images in[0, 255]needmax_val=255.0.epsis added to the denominator: two identical flat images of value \(\mu\) score \(1 - \text{eps} / ((2\mu^2 + c_1)\, c_2 + \text{eps})\). With the defaulteps=1e-12, black images score about0.99998889atmax_val=1.0; the bias grows to0.1atmax_val=0.1. Useeps=0.0to omit this denominator term when matching reference implementations.The map is symmetric in
img1andimg2, in \([-1, 1]\) in exact arithmetic and negative for anti-correlated content. Losses and metrics maps its mean onto scikit-image, pytorch-msssim and torchmetrics.paddingaccepts'same'and'valid'case-insensitively; unsupported values raiseBaseError.
- Parameters:
img1 (
Tensor) – the first image with shape(B, C, H, W).img2 (
Tensor) – the second image with the shape ofimg1.window_size (
int) – size of the Gaussian window in pixels, a positive odd integer.max_val (
float, optional) – data range \(L\) of the images, as a Python float. Default:1.0eps (
float, optional) – term added to the denominator. Default:1e-12padding (
str, optional) –'same'keeps the spatial size;'valid'keeps only the area where the window fits, as the MATLAB implementation of the SSIM paper does. Default:"same"
- Return type:
- Returns:
the SSIM map with shape
(B, C, H, W), or(B, C, H - 2p, W - 2p)withp = window_size // 2underpadding='valid'.
Note
Integer images are converted to float32 before computing the local moments. Half-precision inputs are evaluated in float32 for numerical stability. A float32/float64 pair is filtered in float64, with the Gaussian window built in that dtype. Filtering runs with autocast disabled; the result uses the promoted input dtype. On the CPU with oneDNN, when no gradient is recorded, two contiguous images computed in float32 are filtered in channels-last layout, which oneDNN convolves without first copying the image into blocks of 8 or 16 channels. The map agrees with the NCHW convolutions to rounding and is returned contiguous. Builds without oneDNN, such as the macOS arm64 wheels, oneDNN switched off with
torch.backends.mkldnn,torch.functransforms, and exported and traced graphs keep the NCHW convolutions.See also
SSIM: the module form.ssim3d(): the same map for volumes.ssim_loss(): the dissimilarity \((1 - \text{SSIM}) / 2\), clamped to \([0, 1]\).psnr(): a pixel-error measure of the same pair, as one score in dB.
Examples
>>> input1 = torch.rand(1, 4, 5, 5) >>> input2 = torch.rand(1, 4, 5, 5) >>> ssim_map = ssim(input1, input2, 5) # 1x4x5x5
- kornia.metrics.ssim3d(img1, img2, window_size, max_val=1.0, eps=1e-12, padding='same')[source]#
Compute the per-voxel structural similarity (SSIM) map between two volumes.
ssim_map = ssim3d(img1, img2, window_size)takes two(B, C, D, H, W)volumes and returns the SSIM index at every voxel, channel and sample; average the map for a score. The formula is that ofssim(), with an isotropic Gaussian window over(D, H, W).- Convention:
See the Convention block of
ssim()for the window, reflected border,paddingandmax_val;'valid'crops every axis. A volume of identical slices reproduces the 2-D map up to floating-point roundoff.
- Parameters:
img1 (
Tensor) – the first volume with shape(B, C, D, H, W).img2 (
Tensor) – the second volume with the shape ofimg1.window_size (
int) – size of the Gaussian window in voxels, a positive odd integer.max_val (
float, optional) – data range \(L\) of the volumes, as a Python float. Default:1.0eps (
float, optional) – term added to the denominator. Default:1e-12padding (
str, optional) –'same'keeps the spatial size;'valid'keeps only the area where the window fits. Default:"same"
- Return type:
- Returns:
the SSIM map with shape
(B, C, D, H, W), or(B, C, D - 2p, H - 2p, W - 2p)withp = window_size // 2underpadding='valid'.
Note
The volume is reflected at its faces for
padding='same', askornia.metrics.ssim()does for images, across any positive spatial size, includingD = 1. The Gaussian window is built on the device of the inputs, in the dtype they are filtered in. Integer images are converted to float32 before computing the local moments. Half-precision inputs are evaluated in float32 for numerical stability. Filtering runs with autocast disabled; the result uses the promoted input dtype. On CUDA the float32 filtering followstorch.backends.cudnn.allow_tf32, which PyTorch enables by default. cuDNN can then filter a single-channel volume with a TF32 kernel, which rounds the inputs of the local moments to 10 mantissa bits. The variances are differences of those moments, so in flat regions the map can be off by more than1e-2. Settorch.backends.cudnn.allow_tf32 = Falsewhen float32 accuracy matters.See also
SSIM3D: the module form.ssim(): the same map for images.ssim3d_loss(): the dissimilarity \((1 - \text{SSIM}) / 2\), clamped to \([0, 1]\).
Examples
>>> input1 = torch.rand(1, 4, 5, 5, 5) >>> input2 = torch.rand(1, 4, 5, 5, 5) >>> ssim_map = ssim3d(input1, input2, 5) # 1x4x5x5x5
- class kornia.metrics.SSIM(window_size, max_val=1.0, eps=1e-12, padding='same')[source]#
Compute the per-pixel structural similarity (SSIM) map between two images (module form).
criterion = SSIM(window_size, ...)stores its arguments, andssim_map = criterion(img1, img2)isssim()on two(B, C, H, W)images.- Convention:
See the Convention block of
ssim().
- Parameters:
window_size (
int) – size of the Gaussian window in pixels, a positive odd integer.max_val (
float, optional) – data range \(L\) of the images, as a Python float. Default:1.0eps (
float, optional) – term added to the denominator. Default:1e-12padding (
str, optional) –'same'or'valid', as inssim(). Default:"same"
- Shape:
img1:
(B, C, H, W).img2:
(B, C, H, W).Output:
(B, C, H, W), or(B, C, H - 2p, W - 2p)withp = window_size // 2underpadding='valid'.
See also
Examples
>>> input1 = torch.rand(1, 4, 5, 5) >>> input2 = torch.rand(1, 4, 5, 5) >>> ssim = SSIM(5) >>> ssim_map = ssim(input1, input2) # 1x4x5x5
- class kornia.metrics.SSIM3D(window_size, max_val=1.0, eps=1e-12, padding='same')[source]#
Compute the per-voxel structural similarity (SSIM) map between two volumes (module form).
criterion = SSIM3D(window_size, ...)stores its arguments, andssim_map = criterion(img1, img2)isssim3d()on two(B, C, D, H, W)volumes.- Convention:
See the Convention block of
ssim3d().
- Parameters:
window_size (
int) – size of the Gaussian window in voxels, a positive odd integer.max_val (
float, optional) – data range \(L\) of the volumes, as a Python float. Default:1.0eps (
float, optional) – term added to the denominator. Default:1e-12padding (
str, optional) –'same'or'valid', as inssim3d(). Default:"same"
- Shape:
img1:
(B, C, D, H, W).img2:
(B, C, D, H, W).Output:
(B, C, D, H, W), or(B, C, D - 2p, H - 2p, W - 2p)withp = window_size // 2underpadding='valid'.
See also
ssim3d(): the one-call form.SSIM: the same map for images.SSIM3DLoss: the dissimilarity loss built on this map.
Examples
>>> input1 = torch.rand(1, 4, 5, 5, 5) >>> input2 = torch.rand(1, 4, 5, 5, 5) >>> ssim = SSIM3D(5) >>> ssim_map = ssim(input1, input2) # 1x4x5x5x5