PSNR

The peak signal-to-noise ratio relates the largest possible pixel value (the peak signal) to the mean squared error between the two images (the noise). It is mainly used to measure reconstruction or compression quality.

Given two images x and y of N pixels each, PSNR(x, y) is defined as:

\[\text{MSE}(x, y) = \frac{1}{N} \sum_{i=1}^{N} \left(x_i - y_i\right)^2 \qquad \text{PSNR}(x, y) = 10 \cdot \log_{10}\!\left(\frac{\text{MAX}^2}{\text{MSE}(x, y)}\right)\]

where \(\text{MAX}\) is the peak value of the pixel range, 255 for the canonical uint8 images pyvisim normalizes every input to. The result is reported in decibels: it grows as the two images move closer together, and identical images give MSE = 0 and therefore inf. Because the logarithm compresses the scale, the usual reading is comparative: 30 dB is better than 25 dB for the same pair of images, and typical values for lossy compression land between 30 and 50 dB.

Usage

from pyvisim.dense.pixelwise import PSNR

psnr = PSNR()
scores = psnr.similarity_score(image1, image2)       # (1, 1) matrix, in decibels

batched = PSNR(batch_size=16)
matrix = batched.similarity_score(gallery, queries)  # (N, M) matrix

Every compared pair must share the same (H, W[, C]) shape. The squared differences are summed by a compiled OpenMP kernel, and the PYVISIM_NUM_THREADS environment variable changes its team size (4 by default). batch_size bounds how many images enter one kernel call, which caps the peak memory of very large galleries.

Benchmark

Important

This file was generated by the script docs/dense/pixelwise/benchmarks/generate_benchmark.py. Do not edit manually!

All images are drawn from the Oxford Flower dataset (train split, seed 0), with a disjoint image subset per experiment and per metric. num_workers=4. 7 timed calls after one warm-up.

Baseline: scikit-image 0.26.0 — skimage.metrics.peak_signal_noise_ratio(data_range=255).

Accuracy

Each image (native resolution) is scored against a copy distorted with Gaussian noise (std 15). The error is the absolute difference between the reference and the pyvisim implementation’s score.

Image

pyvisim

Baseline

Abs. error

image_00112.jpg

24.972672

24.972672

0.00e+00

image_00509.jpg

26.032509

26.032509

0.00e+00

image_01876.jpg

24.777768

24.777768

0.00e+00

image_02153.jpg

25.030464

25.030464

0.00e+00

image_04849.jpg

24.650903

24.650903

0.00e+00

image_05561.jpg

24.698927

24.698927

0.00e+00

image_06377.jpg

25.052963

25.052963

0.00e+00

image_06421.jpg

24.761602

24.761602

0.00e+00

Runtime

Median runtime per full scoring call (PSNR of every image in the first gallery against every image in the second).

Scenario

Images

pyvisim (ms)

Baseline (ms)

Speed-up

1 pair (512x512), 512x512

image_07878.jpg, image_04702.jpg

0.043

1.444

33.6x

1 expanded pair (1024x1024), 1024x1024

image_00275.jpg

0.131

12.380

94.7x

batch of 4 (16 pairs), 256x256

image_01936.jpg, image_07586.jpg, image_04727.jpg, image_03724.jpg

0.285

2.653

9.3x

batch of 8 (64 pairs), 256x256

image_03977.jpg, image_03672.jpg, image_04478.jpg, image_05041.jpg, image_07416.jpg, image_04102.jpg, image_01203.jpg, image_06782.jpg

0.460

9.835

21.4x

PSNR median runtime

API reference

class pyvisim.dense.pixelwise.PSNR(batch_size=16)[source]

Bases: DenseMetricBase

Peak signal-to-noise ratio between two batches of images.

The metric is computed pairwise: for N images in the first batch and M images in the second batch, similarity_score() returns an (N, M) matrix of PSNR values in decibels, where identical pairs yield inf. Every compared pair must share the same (H, W[, C]) shape.

The squared differences are summed by a compiled OpenMP kernel. Set the PYVISIM_NUM_THREADS environment variable to override the team size.

For more information, see the documentation: file:///home/critter_cool_laptop/workspace/Python-Visual-Similarity-parallel/docs/_build/html/pixelwise/psnr/psnr.html.

Parameters:

batch_size (int) – Maximum number of images processed in a single batch. Set to -1 to process all images as a single batch.

Raises:

ValueError – If batch_size is neither -1 nor a positive integer.

Example:

>>> import numpy as np
>>> from pyvisim.dense.pixelwise import PSNR
>>> image = np.random.default_rng(0).integers(0, 256, (32, 32, 3), dtype=np.uint8)
>>> PSNR().similarity_score(image, image)
array([[inf]])
set_batch_size(batch_size)

Sets the number of items processed per batch.

Parameters:

batch_size (int) – Maximum number of images processed in a single batch. Set to -1 to process all images as a single batch.

Raises:

ValueError – If batch_size is neither -1 nor a positive integer.

Return type:

None

similarity_score(image1, image2, *, dims='HWC', value_range=(0.0, 255.0))

Compute the pairwise score matrix between two image batches.

Every image is normalized to the canonical uint8 (H, W[, C]) layout in [0, 255] first, so the metric always operates on the same value scale regardless of the input dtype or range.

Parameters:
Returns:

A (N, M) matrix scoring every image of image1 against every image of image2.

Raises:
  • InvalidImageError – If an input cannot be converted to a numeric array.

  • ValueError – If a batch is empty, the two batches hold images of different shapes, or the images are too small for the metric.

Return type:

ndarray[tuple[int, …], dtype[floating[Any]]]