Coverage for utilities/metrics.py: 30%

20 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2025-11-16 22:49 +1300

1""" 

2Metrics 

3======= 

4 

5Define various metrics for evaluating signal quality and comparing data: 

6 

7- :func:`colour.utilities.metric_mse` 

8- :func:`colour.utilities.metric_psnr` 

9 

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""" 

18 

19from __future__ import annotations 

20 

21import typing 

22 

23import numpy as np 

24 

25from colour.algebra import sdiv, sdiv_mode 

26 

27if typing.TYPE_CHECKING: 

28 from colour.hints import ( 

29 ArrayLike, 

30 NDArrayFloat, 

31 Real, 

32 Tuple, 

33 ) 

34 

35from colour.utilities import as_float, as_float_array, zeros 

36 

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" 

43 

44__all__ = [ 

45 "metric_mse", 

46 "metric_psnr", 

47] 

48 

49 

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`. 

58 

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. 

70 

71 Returns 

72 ------- 

73 :class:`numpy.ndarray` 

74 Mean squared error (MSE). 

75 

76 References 

77 ---------- 

78 :cite:`Wikipedia2003c` 

79 

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 """ 

87 

88 return as_float(np.mean((as_float_array(a) - as_float_array(b)) ** 2, axis=axis)) 

89 

90 

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`. 

100 

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. 

114 

115 Returns 

116 ------- 

117 :class:`numpy.ndarray` 

118 Peak signal-to-noise ratio (PSNR). 

119 

120 References 

121 ---------- 

122 :cite:`Wikipedia2004` 

123 

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 """ 

131 

132 mse = as_float_array(metric_mse(a, b, axis)) 

133 psnr = zeros(mse.shape) 

134 

135 with sdiv_mode(): 

136 psnr[mse != 0] = 10 * np.log10(sdiv(max_a**2, mse[mse != 0])) 

137 

138 return as_float(psnr)