-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathevaluateMorphingVulnerability.py
128 lines (93 loc) · 4.89 KB
/
evaluateMorphingVulnerability.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
'''
Implementation of the framework to predict the vulnerability of biometric systems to attacks using morphed biometric information.
More details in:
[BMT18] M. Gomez-Barrero, C. Rathgeb, U. Scherhag, C. Busch, "Predicting the Vulnerability of Biometric Systems to
Attacks based on Morphed Biometric Information", in IET Biometrics, 2018.
Please remember to reference article [IET18] on any work made public, whatever the form,
based directly or indirectly on these metrics.
'''
__author__ = "Marta Gomez-Barrero"
__copyright__ = "Copyright (C) 2018 Hochschule Darmstadt"
__license__ = "License Agreement provided by Hochschule Darmstadt (https://github.com/dasec/morph-vuln-prediction/blob/master/hda-license.pdf)"
__version__ = "1.0"
import numpy
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import pylab
import seaborn as sns
import argparse
import csv
def computeVerificationThreshold(scores, rate):
'''Compute the verification threshold for a given FMR'''
scores.sort()
d = numpy.percentile(scores, 100 - rate)
return d
def computePmorph(mScores, mSubjects, nmScores, nmSubjects1, nmSubjects2, delta):
'''Compute Pmorph as in [BMT18]'''
Pmorph = 0.
deltaMorph = []
for i in range(len(nmScores)):
index1 = mSubjects == nmSubjects1[i]
index2 = mSubjects == nmSubjects2[i]
index = [a or b for a,b in zip(index1,index2)]
mu = mScores[index].mean()
d = 2 * delta - mu
deltaMorph.append(d)
if nmScores[i] > d:
Pmorph += 1
Pmorph = Pmorph / len(nmScores) * 100
return Pmorph, deltaMorph
parser = argparse.ArgumentParser(description='Evaluate the vulnerability of biometric systems to attacks using morphed biometric information.')
parser.add_argument('matedScoresFile', help='filename for the mated scores', type=str)
parser.add_argument('nonMatedScoresFile', help='filename for the non-mated scores', type=str)
parser.add_argument('figureFile', help='filename for the output figure', type=str)
parser.add_argument('--fmr', help='FMR in percentage of the verification threshold, if none provided, FMR = 0.1 per cent', nargs='?', default=0.1, type=float)
parser.add_argument('--figureTitle', help='title for the output figure', nargs='?', default='Morphing vulnerability', type=str)
parser.add_argument('--legendLocation', help='legend location', nargs='?', default='upper right', type=str)
args = parser.parse_args()
matedScoresFile = args.matedScoresFile
nonMatedScoresFile = args.nonMatedScoresFile
figureFile = args.figureFile
figureTitle = args.figureTitle
legendLocation = args.legendLocation
fmr = args.fmr
with open(matedScoresFile) as inf:
reader = csv.reader(inf, delimiter=" ")
matrix = list(zip(*reader))
subjectMated = numpy.asarray(matrix[0], dtype = int)
matedScores = numpy.asarray(matrix[1], dtype = float)
with open(nonMatedScoresFile) as inf:
reader = csv.reader(inf, delimiter=" ")
matrix = list(zip(*reader))
subjectNonMated_1 = numpy.asarray(matrix[0], dtype = int)
subjectNonMated_2 = numpy.asarray(matrix[1], dtype = int)
nonMatedScores = numpy.asarray(matrix[2], dtype = float)
delta = computeVerificationThreshold(nonMatedScores.copy(), fmr)
Pmorph, deltaMorph = computePmorph(matedScores, subjectMated, nonMatedScores, subjectNonMated_1, subjectNonMated_2, delta)
print("Pmorph = %.2f " % (Pmorph))
plt.clf()
sns.set_context("paper",font_scale=2, rc={"lines.linewidth": 2.5})
sns.set_style("white")
fig, ax = plt.subplots()
#ax2 = ax.twinx()
ax = sns.kdeplot(matedScores, shade=False, label='Mated', color=sns.xkcd_rgb["medium green"],linewidth=5)
ax = sns.kdeplot(nonMatedScores, shade=False, label='Non-mated', color=sns.xkcd_rgb["pale red"],linestyle='--',linewidth=5)
ax.legend(loc=legendLocation)
x1,y1 = ax.get_lines()[1].get_data()
x2,y2 = ax.get_lines()[0].get_data()
locAnnotations_Y = 0.75 * max(numpy.max(y1), numpy.max(y2))
locAnnotations_X = 0.6 * max(numpy.max(x1), numpy.max(x2))
ax.annotate("$P_{morph} = $ %.2f" % (Pmorph), xy=(locAnnotations_X, locAnnotations_Y), xytext=(locAnnotations_X, locAnnotations_Y),fontsize=14)
ax.axvline(delta, color='k', linestyle='--')
ax.annotate('$\delta$', xy=(delta+.015, locAnnotations_Y), xytext=(delta+.015, locAnnotations_Y),fontsize=16)
ax.axvline(numpy.max(deltaMorph), color=sns.xkcd_rgb["muted purple"], linestyle='--')
ax.annotate('$\delta_\mathit{morph}^\mathit{max}$', xy=(numpy.max(deltaMorph)+.015, locAnnotations_Y), xytext=(numpy.max(deltaMorph)+.015, locAnnotations_Y),fontsize=16)
ax.axvline(numpy.min(deltaMorph), color=sns.xkcd_rgb["muted purple"], linestyle='--')
ax.annotate('$\delta_\mathit{morph}^\mathit{min}$', xy=(numpy.min(deltaMorph)-.15, locAnnotations_Y), xytext=(numpy.min(deltaMorph)-.15, locAnnotations_Y),fontsize=16)
sns.despine()
plt.title(figureTitle)
plt.ylabel("Probability Density")
plt.xlabel("Similarity Scores")
plt.gcf().subplots_adjust(bottom=0.15)
pylab.savefig(figureFile)