SSIM¶
SSIM captures the perceptual similarity of two images. It is used, for
example, to test out the quality of image compression or denoising algorithms.
Given two images x and y, SSIM(x, y) is defined as:
where:
\(\mu_x\) and \(\mu_y\) are the local luminance of x and y.
\(\sigma_x\) and \(\sigma_y\) are the local contrast of x and y.
\(\sigma_{xy}\) is the joint variation of x and y, which carries how far their local structures agree.
\(C_1 = (k_1 L)^2\) and \(C_2 = (k_2 L)^2\) are stabilization constants that keep the fractions well-defined where their denominators come close to zero. Both \(k_1\) and \(k_2\) are exposed as parameters.
window_sizeandsigmaare the side length and the standard deviation of the Gaussian window that defines the neighborhood of a pixel.
With \(C_3 = C_2 / 2\), the three components collapse into one fraction:
Here, \(L\) is the dynamic range of the pixel values. In pyvisim, it is fixed at
255 (every input is normalized to the [0, 255] range).
Identical images score 1, unrelated images score near 0, and inverted structures score below 0.
Usage¶
from pyvisim.dense.structural import SSIM
ssim = SSIM()
scores = ssim.similarity_score(image1, image2) # (1, 1) matrix
Benchmark¶
Important
This file was generated by the script
docs/dense/structural/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.structural_similarity(win_size=11, gaussian_weights=True, sigma=1.5, use_sample_covariance=False, 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 pyvisim score and the baseline score.
Image |
pyvisim |
Baseline |
Abs. error |
|---|---|---|---|
|
0.334296 |
0.334297 |
7.47e-07 |
|
0.334991 |
0.334990 |
3.06e-07 |
|
0.432977 |
0.432975 |
1.32e-06 |
|
0.550576 |
0.550576 |
1.91e-07 |
|
0.361865 |
0.361864 |
7.84e-07 |
|
0.448853 |
0.448853 |
3.91e-07 |
|
0.351737 |
0.351736 |
4.60e-07 |
|
0.442485 |
0.442485 |
1.91e-07 |
Runtime¶
Median wall-clock time per full scoring call (SSIM of every image in the first gallery against every image in the second). For a fair comparison, GPU is disabled.
Scenario |
Images |
pyvisim (ms) |
Baseline (ms) |
Speed-up |
|---|---|---|---|---|
1 pair (512x512), 512x512 |
|
8.1 |
71.3 |
8.8x |
1 expanded pair (1024x1024), 1024x1024 |
|
52.7 |
376 |
7.1x |
batch of 4 (16 pairs), 256x256 |
|
27.6 |
176 |
6.4x |
batch of 8 (64 pairs), 256x256 |
|
110 |
659 |
6.0x |

API reference¶
- class pyvisim.dense.structural.SSIM(window_size=11, sigma=1.5, k1=0.01, k2=0.03, batch_size=16, num_workers=None)[source]¶
Bases:
DenseMetricBaseStructural Similarity index (Wang et al., 2004) between image batches.
For more information, see the documentation:
https://mechacritter.github.io/Python-Visual-Similarity/dense/structural/ssim/ssim.html.NOTE¶
Windows are applied in “valid” mode with population statistics, and the final score is the mean over the whole SSIM map (all channels pooled)
- param window_size:
Side length of the Gaussian window, an odd integer >= 3.
- param sigma:
Standard deviation of the Gaussian window.
- param k1:
Luminance stabilization constant.
- param k2:
Contrast stabilization constant.
- param batch_size:
Maximum number of image pairs processed in a single batch. Set to
-1to process all images as a single batch.- param num_workers:
Number of threads to use for the computation. If
None, thePYVISIM_NUM_THREADSenvironment variable decides, which can also be changed throughos.environ["PYVISIM_NUM_THREADS"].- raises ValueError:
If any parameter is outside its valid range.
- 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
-1to process all images as a single batch.- Raises:
ValueError – If
batch_sizeis neither-1nor 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:
image1 (_Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes] | Iterable[_Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]]) – First (batch of) image(s) as
MatLike(NumPy array, torch tensor or array-like).image2 (_Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes] | Iterable[_Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]]) – Second (batch of) image(s) as
MatLike.dims (str) – Axis-label string, one character per array axis in order:
"H"= height (rows),"W"= width (columns),"C"= channels (e.g. RGB),"B"= batch size. For example,"HWC"is height × width × channels (NumPy/OpenCV single-image layout);"CHW"is channels × height × width (PyTorch single-image layout);"BCHW"is batch × channels × height × width (PyTorch batched layout). Seepyvisim.typing.value_range (tuple[float, float]) – The
(low, high)range the input values live in; converted into the canonical[0, 255]range.
- Returns:
A
(N, M)matrix scoring every image ofimage1against every image ofimage2.- 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: