Coverage for src/bob/bio/face/reports/scface.py: 0%

55 statements  

« prev     ^ index     » next       coverage.py v7.6.0, created at 2024-07-13 00:04 +0200

1import matplotlib.pyplot as plt 

2import numpy as np 

3 

4from matplotlib.backends.backend_pdf import PdfPages 

5 

6import bob.measure 

7 

8from bob.bio.base.score.load import get_split_dataframe 

9 

10 

11def scface_report( 

12 scores_dev, 

13 scores_eval, 

14 output_filename, 

15 titles, 

16 fmr_threshold=1e-3, 

17 figsize=(16, 8), 

18 colors=plt.cm.tab10.colors, 

19): 

20 distances = [ 

21 "close", 

22 "medium", 

23 "far", 

24 ] 

25 # "combined", 

26 

27 eval_fmr_fnmr = dict() 

28 

29 for ( 

30 d_scores, 

31 e_scores, 

32 title, 

33 ) in zip(scores_dev, scores_eval, titles): 

34 eval_fmr_fnmr[title] = [] 

35 

36 # Load the score files and fill in the angle associated to each camera 

37 impostors_dev, genuines_dev = get_split_dataframe(d_scores) 

38 impostors_eval, genuines_eval = get_split_dataframe(e_scores) 

39 

40 # loading the dask dataframes 

41 impostors_dev = impostors_dev.compute() 

42 genuines_dev = genuines_dev.compute() 

43 impostors_eval = impostors_eval.compute() 

44 genuines_eval = genuines_eval.compute() 

45 # Computing the threshold combining all distances 

46 

47 # Computing the decision threshold 

48 i_dev = impostors_dev["score"].to_numpy() 

49 g_dev = genuines_dev["score"].to_numpy() 

50 

51 threshold = bob.measure.far_threshold( 

52 i_dev, 

53 g_dev, 

54 far_value=fmr_threshold, 

55 ) 

56 

57 def compute_fmr_fnmr(impostor_scores, genuine_scores): 

58 eval_fmr, eval_fnmr = bob.measure.farfrr( 

59 impostor_scores["score"].to_numpy(), 

60 genuine_scores["score"].to_numpy(), 

61 threshold, 

62 ) 

63 return eval_fmr, eval_fnmr 

64 

65 for distance in distances: 

66 i_eval = impostors_eval.loc[ 

67 impostors_eval.probe_distance == distance 

68 ] 

69 g_eval = genuines_eval.loc[genuines_eval.probe_distance == distance] 

70 

71 eval_fmr_fnmr[title].append(compute_fmr_fnmr(i_eval, g_eval)) 

72 

73 # Combined 

74 # eval_fmr_fnmr[title].append(compute_fmr_fnmr(impostors_eval, genuines_eval)) 

75 

76 pass 

77 

78 # Plotting 

79 pdf = PdfPages(output_filename) 

80 

81 # Figure for eval plot 

82 fig = plt.figure(figsize=figsize) 

83 ax = fig.add_subplot(111) 

84 

85 width = 0.8 / len(titles) 

86 X = np.arange(len(distances)) 

87 

88 for i, (title, color) in enumerate(zip(titles, colors)): 

89 fmrs = [-1 * fmr * 100 for fmr, _ in eval_fmr_fnmr[title]] 

90 fnmrs = [fnmr * 100 for _, fnmr in eval_fmr_fnmr[title]] 

91 x_axis = X + (i + 1) * width - width / 2 

92 ax.bar( 

93 x_axis, 

94 fmrs, 

95 width, 

96 label=title, 

97 color=color, 

98 alpha=0.75, 

99 hatch="\\", 

100 ) 

101 ax.bar(x_axis, fnmrs, width, color=color, alpha=0.5, hatch="/") 

102 

103 # Writting the texts on top of the bar plots 

104 for i, fnmr, fmr in zip(x_axis, fnmrs, fmrs): 

105 plt.text(i - width / 2, fnmr + 1, str(round(fnmr, 1)), fontsize=10) 

106 plt.text( 

107 i - width / 2, 

108 fmr - 4.5, 

109 str(int(fmr)) if fmr <= 0.4 else str(round(abs(fmr), 1)), 

110 fontsize=10, 

111 ) 

112 

113 ax.set_axisbelow(True) 

114 

115 # Plot finalization 

116 plt.title( 

117 f"FMR vs FNMR. at Dev. FMR@{fmr_threshold*100}% under differente distances" 

118 ) 

119 # ax.set_xlabel("Distances", fontsize=14) 

120 ax.set_ylabel( 

121 "FMR(%) vs FNMR(%) ", fontsize=14 

122 ) 

123 plt.ylim([-25, 104]) 

124 

125 ax.set_xticks(X + 0.5) 

126 ax.set_xticklabels(distances, fontsize=16) 

127 

128 yticks = np.array([-20, 0, 20, 40, 60, 80, 100]) 

129 ax.set_yticks(yticks) 

130 ax.set_yticklabels(abs(yticks), fontsize=16) 

131 plt.axhline(0, linestyle="-", color="k") 

132 

133 plt.legend() 

134 plt.grid() 

135 

136 pdf.savefig(fig) 

137 pdf.close()