Coverage for src/bob/bio/face/reports/mobio.py: 0%
54 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 mobio_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 genders = [
21 "m",
22 "f",
23 ]
24 gender_labels = ["male", "female"]
26 # colors = plt.cm.tab20.colors
28 eval_fmr_fnmr = dict()
30 for (
31 d_scores,
32 e_scores,
33 title,
34 ) in zip(scores_dev, scores_eval, titles):
35 eval_fmr_fnmr[title] = []
37 # Load the score files and fill in the angle associated to each camera
38 impostors_dev, genuines_dev = get_split_dataframe(d_scores)
39 impostors_eval, genuines_eval = get_split_dataframe(e_scores)
41 # loading the dask dataframes
42 impostors_dev = impostors_dev.compute()
43 genuines_dev = genuines_dev.compute()
44 impostors_eval = impostors_eval.compute()
45 genuines_eval = genuines_eval.compute()
46 # Computing the threshold combining all distances
47 # Getting only the close distance to compute the threshold
49 threshold = bob.measure.far_threshold(
50 impostors_dev["score"].to_numpy(),
51 genuines_dev["score"].to_numpy(),
52 far_value=fmr_threshold,
53 )
55 def compute_fmr_fnmr(impostor_scores, genuine_scores):
56 eval_fmr, eval_fnmr = bob.measure.farfrr(
57 impostor_scores["score"].to_numpy(),
58 genuine_scores["score"].to_numpy(),
59 threshold,
60 )
61 return eval_fmr, eval_fnmr
63 # Combined
64 eval_fmr_fnmr[title].append(
65 compute_fmr_fnmr(impostors_eval, genuines_eval)
66 )
68 for gender in genders[1:]:
69 i_eval = impostors_eval.loc[impostors_eval.probe_gender == gender]
70 g_eval = genuines_eval.loc[genuines_eval.probe_gender == gender]
72 eval_fmr_fnmr[title].append(compute_fmr_fnmr(i_eval, g_eval))
74 pass
76 # Plotting
77 pdf = PdfPages(output_filename)
79 # Figure for eval plot
80 fig = plt.figure(figsize=figsize)
81 ax = fig.add_subplot(111)
83 width = 0.8 / len(titles)
84 X = np.arange(len(genders))
86 for i, (title, color) in enumerate(zip(titles, colors)):
87 fmrs = [-1 * fmr * 100 for fmr, _ in eval_fmr_fnmr[title]]
88 fnmrs = [fnmr * 100 for _, fnmr in eval_fmr_fnmr[title]]
90 x_axis = X + (i + 1) * width - width / 2
91 ax.bar(
92 x_axis,
93 fmrs,
94 width,
95 label=title,
96 color=color,
97 alpha=0.75,
98 hatch="\\",
99 )
100 ax.bar(x_axis, fnmrs, width, color=color, alpha=0.5, hatch="/")
102 # Writting the texts on top of the bar plots
103 for i, fnmr, fmr in zip(x_axis, fnmrs, fmrs):
104 plt.text(
105 i - width / 2, fnmr + 0.8, str(round(fnmr, 2)), fontsize=12
106 )
107 # print(i - width / 2)
108 plt.text(
109 i - width / 2, fmr - 2.2, str(round(abs(fmr), 2)), fontsize=12
110 )
112 ax.set_axisbelow(True)
114 # Plot finalization
115 plt.title(f"FMR vs FNMR . at Dev. FMR@{fmr_threshold*100}%")
116 # ax.set_xlabel("Genders", fontsize=18)
117 ax.set_ylabel("FMR(%) vs FNMR(%) ", fontsize=15)
118 # plt.ylim([-5, 40])
120 ax.set_xticks(X + 0.5)
121 ax.set_xticklabels(gender_labels, fontsize=14)
123 yticks = np.array([-5, 0, 5, 15, 25, 35])
124 ax.set_yticks(yticks)
125 ax.set_yticklabels(abs(yticks), fontsize=16)
127 plt.axhline(0, linestyle="-", color="k")
129 plt.legend()
130 plt.grid()
132 pdf.savefig(fig)
133 pdf.close()