Coverage for colour/utilities/metrics.py: 100%
20 statements
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-15 19:01 +1300
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-15 19:01 +1300
1"""
2Metrics
3=======
5Define various metrics for evaluating signal quality and comparing data:
7- :func:`colour.utilities.metric_mse`
8- :func:`colour.utilities.metric_psnr`
10References
11----------
12- :cite:`Wikipedia2003c` : Wikipedia. (2003). Mean squared error. Retrieved
13 March 5, 2018, from https://en.wikipedia.org/wiki/Mean_squared_error
14- :cite:`Wikipedia2004` : Wikipedia. (2004). Peak signal-to-noise ratio.
15 Retrieved March 5, 2018, from
16 https://en.wikipedia.org/wiki/Peak_signal-to-noise_ratio
17"""
19from __future__ import annotations
21import typing
23import numpy as np
25from colour.algebra import sdiv, sdiv_mode
27if typing.TYPE_CHECKING:
28 from colour.hints import (
29 ArrayLike,
30 NDArrayFloat,
31 Real,
32 Tuple,
33 )
35from colour.utilities import as_float, as_float_array, zeros
37__author__ = "Colour Developers"
38__copyright__ = "Copyright 2013 Colour Developers"
39__license__ = "BSD-3-Clause - https://opensource.org/licenses/BSD-3-Clause"
40__maintainer__ = "Colour Developers"
41__email__ = "colour-developers@colour-science.org"
42__status__ = "Production"
44__all__ = [
45 "metric_mse",
46 "metric_psnr",
47]
50def metric_mse(
51 a: ArrayLike,
52 b: ArrayLike,
53 axis: int | Tuple[int] | None = None,
54) -> NDArrayFloat:
55 """
56 Compute the mean squared error (MSE) between the specified arrays
57 :math:`a` and :math:`b`.
59 Parameters
60 ----------
61 a
62 Variable :math:`a`.
63 b
64 Variable :math:`b`.
65 axis
66 Axis or axes along which the means are computed. The default is to
67 compute the mean of the flattened array. If this is a tuple of
68 integers, a mean is performed over multiple axes instead of a
69 single axis or all the axes as before.
71 Returns
72 -------
73 :class:`numpy.ndarray`
74 Mean squared error (MSE).
76 References
77 ----------
78 :cite:`Wikipedia2003c`
80 Examples
81 --------
82 >>> a = np.array([0.48222001, 0.31654775, 0.22070353])
83 >>> b = a * 0.9
84 >>> metric_mse(a, b) # doctest: +ELLIPSIS
85 0.0012714...
86 """
88 return as_float(np.mean((as_float_array(a) - as_float_array(b)) ** 2, axis=axis))
91def metric_psnr(
92 a: ArrayLike,
93 b: ArrayLike,
94 max_a: Real = 1,
95 axis: int | Tuple[int] | None = None,
96) -> NDArrayFloat:
97 """
98 Compute the peak signal-to-noise ratio (PSNR) between the specified
99 arrays :math:`a` and :math:`b`.
101 Parameters
102 ----------
103 a
104 Array :math:`a`.
105 b
106 Array :math:`b`.
107 max_a
108 Maximum possible value of the array :math:`a`.
109 axis
110 Axis or axes along which the means are computed. The default is
111 to compute the mean of the flattened array. If this is a tuple
112 of integers, a mean is performed over multiple axes, instead of
113 a single axis or all the axes as before.
115 Returns
116 -------
117 :class:`numpy.ndarray`
118 Peak signal-to-noise ratio (PSNR).
120 References
121 ----------
122 :cite:`Wikipedia2004`
124 Examples
125 --------
126 >>> a = np.array([0.48222001, 0.31654775, 0.22070353])
127 >>> b = a * 0.9
128 >>> metric_psnr(a, b) # doctest: +ELLIPSIS
129 28.9568515...
130 """
132 mse = as_float_array(metric_mse(a, b, axis))
133 psnr = zeros(mse.shape)
135 with sdiv_mode():
136 psnr[mse != 0] = 10 * np.log10(sdiv(max_a**2, mse[mse != 0]))
138 return as_float(psnr)