Coverage for crip\metric.py: 97%

39 statements  

« prev     ^ index     » next       coverage.py v7.5.2, created at 2024-07-16 01:15 +0800

1''' 

2 Metrics module of crip. 

3 

4 https://github.com/SEU-CT-Recon/crip 

5''' 

6 

7import numpy as np 

8from scipy.stats import ttest_ind, ttest_rel 

9from skimage.metrics import structural_similarity, peak_signal_noise_ratio 

10 

11from .utils import * 

12from ._typing import * 

13 

14 

15def computeMAPE(x: TwoOrThreeD, y: TwoOrThreeD, eps=1e-6) -> float: 

16 ''' Compute the Mean Absolution Percentage Error (%) where `x` is the prediction 

17 and `y` is the ground truth. 

18 ''' 

19 cripAssert(isOfSameShape(x, y), 'Input images must have the same shape.') 

20 

21 return np.mean(np.abs(x - y) / (y + eps)) * 100 

22 

23 

24def computePSNR(x: TwoOrThreeD, y: TwoOrThreeD, range_=1) -> float: 

25 ''' Compute the Peak Signal Noise Ratio (PSNR) (dB) between `x` and `y`. 

26 ''' 

27 cripWarning(range_ in [1, 255], 

28 '`range_` for PSNR is usually 1 or 255. Be sure your behavior follows your intention.') 

29 cripAssert(isOfSameShape(x, y), 'Input images must have the same shape.') 

30 

31 return peak_signal_noise_ratio(x, y, data_range=range_) 

32 

33 

34def computeSSIM(x: TwoOrThreeD, y: TwoOrThreeD, range_=1) -> float: 

35 ''' Compute the Structural Similarity (SSIM) between `x` and `y`. 

36 ''' 

37 cripWarning(range_ in [1, 255], 

38 '`range_` for SSIM is usually 1 or 255. Be sure your behavior follows your intention.') 

39 cripAssert(isOfSameShape(x, y), 'Input images must have the same shape.') 

40 

41 return structural_similarity(x, y, data_range=range_, channel_axis=0 if is3D(x) else None) 

42 

43 

44def computeRMSE(x: TwoOrThreeD, y: TwoOrThreeD, pixelwise: bool = False) -> Or[float, TwoOrThreeD]: 

45 ''' Compute the Root Mean Squared Error (RMSE) between `x` and `y`. 

46 ''' 

47 se = (x - y)**2 

48 reducer = identity if pixelwise else np.mean 

49 

50 return np.sqrt(reducer(se)) 

51 

52 

53def computeMAE(x: TwoOrThreeD, y: TwoOrThreeD, pixelwise: bool = False) -> Or[float, TwoOrThreeD]: 

54 ''' Compute the Mean Absolute Error (MAE) between `x` and `y`. 

55 ''' 

56 ae = np.abs(x - y) 

57 reducer = identity if pixelwise else np.mean 

58 

59 return reducer(ae) 

60 

61 

62def pvalueInd(control: NDArray, treated: NDArray, equalVar: bool = True) -> float: 

63 ''' Compute the two-sided p-value of the independent t-test between metrics `control` and `treated`. 

64 ''' 

65 

66 return ttest_ind(control.flatten(), treated.flatten(), equal_var=equalVar).pvalue 

67 

68 

69def pvalueRel(control: NDArray, treated: NDArray) -> float: 

70 ''' Compute the two-sided p-value of the related t-test between metrics `control` and `treated`. 

71 ''' 

72 

73 return ttest_rel(control.flatten(), treated.flatten()).pvalue 

74 

75 

76class AverageMeter(): 

77 ''' Computes and stores the average and current value in `avg` and `val` respectively. 

78 ''' 

79 

80 def __init__(self): 

81 self.val = 0 # current value 

82 self.avg = 0 # average value 

83 self.sum = 0 # sum of all values 

84 self.count = 0 # number of values 

85 

86 def update(self, val): 

87 self.val = val 

88 self.sum += val 

89 self.count += 1 

90 self.avg = self.sum / self.count