PSNR-HVS-M, PSNR-HA and PSNR-HMA metrics for NumPy and PyTorch
Accelerated Python package for computing several image metrics based on human perception with backends in NumPy, PyTorch and C++.
This is an implementation of the PSNR-HVS, PSNR-HVS-M, PSNR-HA and PSNR-HMA metrics developed by Nikolay Ponomarenko.
The values produced by this library have been cross-checked against the results
within the
TID2013 dataset.
(See the folder tid2013_results.) The only difference is
that this library follows the common convention that PSNR for identical signals
equals 100.0.
A miniscule discrepancy for PSNR-HMA (<0.01dB on average) is under investigation.
Bibliography
- Egiazarian, Karen, et al. "New full-reference quality metrics based on HVS." Proceedings of the Second International Workshop on Video Processing and Quality Metrics. Vol. 4. 2006.
- Ponomarenko, Nikolay, et al. "On between-coefficient contrast masking of DCT basis functions." Proceedings of the third international workshop on video processing and quality metrics. Vol. 4. 2007.
- Ponomarenko, Nikolay, et al. "Modified image visual quality metrics for contrast change and mean shift accounting." 2011 11th International Conference The Experience of Designing and Application of CAD Systems in Microelectronics (CADSM). IEEE, 2011.
Installation
psnr_hvsm supports Python 3.10-3.15. Packages are distributed on PyPi. Be sure
to have an up-to-date pip to be able to install the correct packages on Linux:
python -m pip install --upgrade pip
pip install psnr_hvsm
With PyTorch support:
pip install psnr_hvsm[torch]
NumPy and PyTorch support policy
The NumPy requirement carries no upper bound. The compiled extension is built
against NumPy 2 headers with a fixed backward-compatible ABI target, so a
single wheel serves both NumPy 1.x and NumPy 2.x runtimes. Installing the
package never forces a downgrade from NumPy 2.x, and its runtime floor is
numpy>=1.19. Note that NumPy 1.x itself
is only installable on Python 3.10-3.12: the last 1.x release ships wheels
only that far, so on Python 3.13 and newer the runtime resolves NumPy 2.x.
PyPI publishes PyTorch wheels for Python 3.10-3.14 only, so the torch extra
is unavailable on 3.15 and the PyTorch backend cannot be installed there.
MSVC runtime on Windows
Linux manylinux wheels bundle libstdc++ via auditwheel. The Windows wheels do
not bundle the MSVC C++ runtime: CMake installs only the FFTW DLLs into the
wheel. On CPython 3.10-3.14 the package
therefore declares msvc-runtime for Windows, which pip installs into the
environment along with the package, so no system-wide Visual C++ runtime is
required. The MSVC or clang toolchain supplies the CRT when the extension is
compiled, which is why it is not a build requirement.
On CPython 3.15 the requirement is not declared. msvc-runtime publishes its
wheels per CPython ABI and has no cp315 wheel, so asking for it there would
leave the newest supported interpreter uninstallable. A CPython install from
python.org brings the C runtime it was built with (its installer updates the
C Runtime Library on the machine when one is needed), so 3.15 works without
anything extra. If an import nevertheless fails with a missing
vcruntime140.dll or msvcp140.dll - a possibility with the minimal layouts
such as the embeddable package, MSYS2 or NuGet-based installs - install the
Microsoft Visual C++ 2015-2022 redistributable for your architecture, or use
CPython 3.10-3.14, where the requirement is declared.
Usage
Command line
Command line support is an extra that pulls imageio:
pip install psnr_hvsm[command_line]
python -m psnr_hvsm original.png distorted.png
Choosing a backend
The backend can be set by setting the PSNR_HVSM_BACKEND environment variable.
Valid backends are:
numpy- pure NumPy usingscipy.fftfor DCTcpp- C++ using FFTW3torch- PyTorch; install aspsnr_hvsm[torch]to install PyTorch as well
export PSNR_HVSM_BACKEND=torch
python -m psnr_hvsm original.png distorted.png
The default device for PyTorch is cuda but it can be changed by setting the
PSNR_HVSM_TORCH_DEVICE environment variable.
As a library
The function psnr_hvs_hvsm accepts images as single-channel floating-point
NumPy arrays. The images need to be normalised, i.e. the values need to be in
the range [0,1]. This can be achieved by converting the image to float and
dividing by the maximum value given the bit depth. For 8 bits per component this
is 255.
The images must be padded to a multiple of 8 in each dimension.
from imageio import imread
from psnr_hvsm import psnr_hvs_hvsm, bt601ycbcr
image1 = imread('tests/baboon.png').astype(float) / 255
image2 = imread('tests/baboon_msk.png').astype(float) / 255
image1_y, *_ = bt601ycbcr(image1)
image2_y, *_ = bt601ycbcr(image2)
psnr_hvs, psnr_hvsm = psnr_hvs_hvsm(image1, image2)
print(psnr_hvs, psnr_hvsm)
34.427054505764424 51.64722121999962
If you need to measure PSNR-HVS and PSNR-HVS-M on an RGB image, you need to convert it to an YUV colorspace and pass in only the luma component.
BT.601 conversion precision
When 8-bit RGB input is converted to the BT.601 YCbCr colorspace, the luma and both chroma components are by default rounded to 8-bit code values. This quantisation matches the 8-bit YCbCr pipeline of the reference implementation and is what reproduces the published TID2013 reference values this library is cross-checked against, which is why it remains the default. Every metric output computed with the default is bit-identical to previous releases.
If you are porting the metrics and want to compare against a non-quantised
reference, pass precision='float' to compute the same BT.601 matrix
arithmetic without the rounding step:
from psnr_hvsm import bt601ycbcr
from psnr_hvsm.compute_all_metrics import compute_all_metrics
image1_y, image1_cb, image1_cr = bt601ycbcr(image1_uint8, precision='float')
psnr_hvs, psnr_hvsm, psnr_ha, psnr_hma, psnr = compute_all_metrics(
image1_uint8, image2_uint8, precision='float')
The precision option ('8-bit' default, 'float') is accepted by
bt601ycbcr in both the NumPy and PyTorch backends with identical
semantics, and by the compute_all_metrics entry point, which threads it
through every metric that depends on the quantised 8-bit BT.601 YCbCr
conversion. It applies only when that conversion runs. For grayscale input or
non-uint8 color input, it has no effect.
On the command line the same choice is exposed as
--precision {8-bit,float} on python -m psnr_hvsm, and the JSON output
(--json) records the requested precision, so batch results are
self-describing. The requested precision is applied wherever the quantised
conversion runs; for grayscale or non-uint8 color input, the field has no
effect.
PyTorch support
The PyTorch backend can be used for use with gradient descent algorithms and
computation on GPUs. In order to use the PyTorch backend, either install the
package with the torch extra:
pip install psnr_hvsm[torch]
If your PyTorch installation was manual, you need
torch-dct in order to use the PyTorch
backend:
pip install "torch-dct>=0.1.6"
An important distinction is that the functions that expect 3-channel input now
expect (...,C,H,W) format in the PyTorch implementation. The PyTorch backend
can be enabled by importing it directly from psnr_hvsm.torch:
import torch
from imageio import imread
from psnr_hvsm.torch import psnr_hvs_hvsm, bt601ycbcr
image1 = imread('tests/baboon.png').astype(float) / 255
image2 = imread('tests/baboon_msk.png').astype(float) / 255
image1 = torch.tensor(image1, device='cuda').moveaxis(-1, -3) # convert to (N,C,H,W) format
image2 = torch.tensor(image2, device='cuda').moveaxis(-1, -3) # convert to (N,C,H,W) format
image1_y, *_ = bt601ycbcr(image1)
image2_y, *_ = bt601ycbcr(image2)
psnr_hvs, psnr_hvsm = psnr_hvs_hvsm(image1_y, image2_y)
Alternatively, set the PSNR_HVSM_BACKEND environment variable to torch:
import os
os.environ['PSNR_HVSM_BACKEND'] = 'torch'
from psnr_hvsm import psnr_hvs_hvsm
# rest of code
# ...
Note on gradients
Some operations in the calculation of the HVS-M MSE lead to problems with the
gradient and therefore a parameter called masking_epsilon (defaulting to 0.0)
has been added to the PyTorch versions of hvs_hvsm_mse_tiles, hvs_hvsm_mse
and psnr_hvs_hvsm. Set it to a small value (determined by your own
experimentation) if you need the result of HVS-M for gradient descent.
Computing metrics for the TID2013 dataset
If you have a copy of the TID2013 dataset, you can re-verify the metrics for yourself:
python -m psnr_hvsm.tid2013_metrics D:\tid2013\ .\tid2013_results\
Other exported functions
hvs_hvsm_mse_tiles- compute HVS and HVS-M scores on all 8x8 tiles in the images, returns an array of numbershvs_hvsm_mse- compute average HVS and HVS-M scores
Building
Dependencies
psnr_hvsm has several dependencies:
FFTW3 is always fetched by CMake at the pinned release listed in
psnr_hvsm/CMakeLists.txt. The remaining, header-only dependencies are
installed at pinned, mutually compatible versions when they are not already
installed, so a C++ compiler, a current CMake and pip or uv are enough to build
from source:
pip install --upgrade -r requirements-build.txt
pip wheel --no-deps -w dist .
If you prefer a conda environment, create the provided one and CMake will
discover the dependencies from it instead of fetching them:
conda env create -f psnr_hvsm-dev.yml
Development mode
To install in development mode:
pip install --upgrade -r requirements.txt
Creating Python wheel
pip install --upgrade -r requirements-build.txt
python -m build --wheel
Verifying a clean source build
To build from source in a scratch virtualenv that has no conda environment for CMake to discover and to run the test suite against the result:
./clean-build-check.sh
Running tests on different versions of Python using tox
pip install --upgrade -r requirements-tox.txt
tox --parallel auto
Metadata
Release files for psnr-hvsm 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| psnr_hvsm-0.3.0-cp315-cp315-win_amd64.whl | CPython 3.15 | CPython 3.15 | Windows x86-64 | Details |
| psnr_hvsm-0.3.0-cp315-cp315-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl | CPython 3.15 | CPython 3.15 | Linux glibc 2.24+ x86-64, Linux glibc 2.28+ x86-64 | Details |
| psnr_hvsm-0.3.0-cp314-cp314-win_amd64.whl | CPython 3.14 | CPython 3.14 | Windows x86-64 | Details |
| psnr_hvsm-0.3.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl | CPython 3.14 | CPython 3.14 | Linux glibc 2.24+ x86-64, Linux glibc 2.28+ x86-64 | Details |
| psnr_hvsm-0.3.0-cp313-cp313-win_amd64.whl | CPython 3.13 | CPython 3.13 | Windows x86-64 | Details |
| psnr_hvsm-0.3.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl | CPython 3.13 | CPython 3.13 | Linux glibc 2.28+ x86-64, Linux glibc 2.24+ x86-64 | Details |
| psnr_hvsm-0.3.0-cp312-cp312-win_amd64.whl | CPython 3.12 | CPython 3.12 | Windows x86-64 | Details |
| psnr_hvsm-0.3.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl | CPython 3.12 | CPython 3.12 | Linux glibc 2.24+ x86-64, Linux glibc 2.28+ x86-64 | Details |
| psnr_hvsm-0.3.0-cp311-cp311-win_amd64.whl | CPython 3.11 | CPython 3.11 | Windows x86-64 | Details |
| psnr_hvsm-0.3.0-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl | CPython 3.11 | CPython 3.11 | Linux glibc 2.24+ x86-64, Linux glibc 2.28+ x86-64 | Details |
| psnr_hvsm-0.3.0-cp310-cp310-win_amd64.whl | CPython 3.10 | CPython 3.10 | Windows x86-64 | Details |
| psnr_hvsm-0.3.0-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl | CPython 3.10 | CPython 3.10 | Linux glibc 2.24+ x86-64, Linux glibc 2.28+ x86-64 | Details |
Total release size: 79.0 MB
Release files / psnr_hvsm-0.3.0-cp315-cp315-win_amd64.whl
| Download URL | psnr_hvsm-0.3.0-cp315-cp315-win_amd64.whl |
|---|---|
| Size | 3.0 MB |
| Tags | CPython 3.15 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
4b9346d41faafebe96b55904b50fba9e279c29803c0f2a059c8e6b51bda04650
|
|
BLAKE2b-256 checksum How to use checksums |
db62d20219978e7c1623d957f43008e7d06e3b7b9da7f54bbc1aaec6d7454c5f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / psnr_hvsm-0.3.0-cp315-cp315-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
| Download URL | psnr_hvsm-0.3.0-cp315-cp315-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 10.2 MB |
| Tags | CPython 3.15 Linux glibc 2.24+ x86-64 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
8cb6448e4884c49f77f39f9fc673e87a349ddf79c29eb77eaf018cd2f6458000
|
|
BLAKE2b-256 checksum How to use checksums |
568529aa8b95b6119d142f06f9ac4d9538d8f49869868361a97f3131dd271aee
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / psnr_hvsm-0.3.0-cp314-cp314-win_amd64.whl
| Download URL | psnr_hvsm-0.3.0-cp314-cp314-win_amd64.whl |
|---|---|
| Size | 3.0 MB |
| Tags | CPython 3.14 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
267c85376269f883e713933776ee558a2994f4e622acdbc0860bfbe711aabd25
|
|
BLAKE2b-256 checksum How to use checksums |
3bb47e8cb1e0c4737752390aa79449cc1c69d5c8d7cd96e1c2f0b8fb00e9f652
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / psnr_hvsm-0.3.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
| Download URL | psnr_hvsm-0.3.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 10.2 MB |
| Tags | CPython 3.14 Linux glibc 2.24+ x86-64 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
5f030d134e1a6f66079f64112a0c6f442bfd9cbbbdbc7cf86748865a1dd8af89
|
|
BLAKE2b-256 checksum How to use checksums |
fb28c6bcd7d95862e7ed44f40eaf847a9886ef04a7d44f624bec709f6ce47cd0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / psnr_hvsm-0.3.0-cp313-cp313-win_amd64.whl
| Download URL | psnr_hvsm-0.3.0-cp313-cp313-win_amd64.whl |
|---|---|
| Size | 3.0 MB |
| Tags | CPython 3.13 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
67c8c589bc747be5e1768cd22f74f112f75e9669b65bdb8c8109deb3a81ebd00
|
|
BLAKE2b-256 checksum How to use checksums |
597a1832f6f1d651b2bb682a5e0050a757439649a42eb724da6347271c0080db
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / psnr_hvsm-0.3.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
| Download URL | psnr_hvsm-0.3.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 10.2 MB |
| Tags | CPython 3.13 Linux glibc 2.24+ x86-64 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
a3992f2fe697a5f21ab5a0f8fc935459ca6a7b3de13d5f3f22ff4a26835bafdf
|
|
BLAKE2b-256 checksum How to use checksums |
37393a48263d249d68534e4dc7b7d4043d7c178d1448846a936b800eef1948f5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / psnr_hvsm-0.3.0-cp312-cp312-win_amd64.whl
| Download URL | psnr_hvsm-0.3.0-cp312-cp312-win_amd64.whl |
|---|---|
| Size | 3.0 MB |
| Tags | CPython 3.12 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
6552cca8eb470594bcb4b02a37e1bbe6c63346a26e44c2464e0f2970b080d64e
|
|
BLAKE2b-256 checksum How to use checksums |
ccca84df70570bb11c046371d12a5c23169aad9ffbb8c32b373b36104bb4d9d5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / psnr_hvsm-0.3.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
| Download URL | psnr_hvsm-0.3.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 10.2 MB |
| Tags | CPython 3.12 Linux glibc 2.24+ x86-64 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
9c4754daf63a73f489014c17425f321c9ea1d3bde140de6acd135d6400be6f6d
|
|
BLAKE2b-256 checksum How to use checksums |
ee8504c2cb34fa6cdc91e802654b21623a8c75151c9b990ca0f4647412f89a57
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / psnr_hvsm-0.3.0-cp311-cp311-win_amd64.whl
| Download URL | psnr_hvsm-0.3.0-cp311-cp311-win_amd64.whl |
|---|---|
| Size | 3.0 MB |
| Tags | CPython 3.11 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
3022c9e5ff83e805c966d25879f97c7c2c2f0823c52b17f96041feeff58be29d
|
|
BLAKE2b-256 checksum How to use checksums |
772b57a23bd1312d008cfdc8fa67c8d6e44a17beeb9770aabdb269aacd111120
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / psnr_hvsm-0.3.0-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
| Download URL | psnr_hvsm-0.3.0-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 10.2 MB |
| Tags | CPython 3.11 Linux glibc 2.24+ x86-64 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
b8914133f5b1b2de569311dd778db5620d62e2c91de60cdd6e4c802d3545fb74
|
|
BLAKE2b-256 checksum How to use checksums |
33e43a223c3e4fd7d6ad89b761aef08e51126958617ab0e2f2afcfa1f370beed
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / psnr_hvsm-0.3.0-cp310-cp310-win_amd64.whl
| Download URL | psnr_hvsm-0.3.0-cp310-cp310-win_amd64.whl |
|---|---|
| Size | 3.0 MB |
| Tags | CPython 3.10 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
6ba8eba930e51a2fb7f64330351df0a0285de3e4e1c707dfe09d8f01471fc211
|
|
BLAKE2b-256 checksum How to use checksums |
0b145b218dd63c713f9d64a8eab476f1347c92702de20679274db9d1b4d90858
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / psnr_hvsm-0.3.0-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
| Download URL | psnr_hvsm-0.3.0-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 10.2 MB |
| Tags | CPython 3.10 Linux glibc 2.24+ x86-64 Linux glibc 2.28+ x86-64 |
|
SHA-256 checksum How to use checksums |
00813d86330f9d9486df5b15dd8571411e31ecf1a8f96e83164dd2b12d246443
|
|
BLAKE2b-256 checksum How to use checksums |
fa491d68aa49b0c5f7b64e8f1097292c777f9f1cee803f14c2eaedcc439bf16b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|