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
« 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
4from matplotlib.backends.backend_pdf import PdfPages
6import bob.measure
8from bob.bio.base.score.load import get_split_dataframe
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",
27 eval_fmr_fnmr = dict()
29 for (
30 d_scores,
31 e_scores,
32 title,
33 ) in zip(scores_dev, scores_eval, titles):
34 eval_fmr_fnmr[title] = []
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)
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
47 # Computing the decision threshold
48 i_dev = impostors_dev["score"].to_numpy()
49 g_dev = genuines_dev["score"].to_numpy()
51 threshold = bob.measure.far_threshold(
52 i_dev,
53 g_dev,
54 far_value=fmr_threshold,
55 )
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
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]
71 eval_fmr_fnmr[title].append(compute_fmr_fnmr(i_eval, g_eval))
73 # Combined
74 # eval_fmr_fnmr[title].append(compute_fmr_fnmr(impostors_eval, genuines_eval))
76 pass
78 # Plotting
79 pdf = PdfPages(output_filename)
81 # Figure for eval plot
82 fig = plt.figure(figsize=figsize)
83 ax = fig.add_subplot(111)
85 width = 0.8 / len(titles)
86 X = np.arange(len(distances))
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="/")
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 )
113 ax.set_axisbelow(True)
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])
125 ax.set_xticks(X + 0.5)
126 ax.set_xticklabels(distances, fontsize=16)
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")
133 plt.legend()
134 plt.grid()
136 pdf.savefig(fig)
137 pdf.close()