-
Notifications
You must be signed in to change notification settings - Fork 3
/
facenet.py
executable file
·99 lines (80 loc) · 3.25 KB
/
facenet.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
from inception_blocks_v2 import *
from fr_utils import *
from keras import backend as K
from os import listdir
K.set_image_data_format("channels_first")
class FaceNetClass:
def __init__(self):
self.faceNetModel = faceRecoModel(input_shape=(3, 96, 96))
print('Total params: ', self.faceNetModel.count_params())
self.faceNetModel.compile(optimizer='adam', loss=self.triplet_loss, metrics=['accuracy'])
load_weights_from_FaceNet(self.faceNetModel)
self.face_ids = {}
self.files = listdir('images/')
self.pre_train_count = 0
self.pre_train()
@staticmethod
def triplet_loss(y_pred, alpha=0.2):
"""
Implementation of the triplet loss as defined in FaceNet paper
Arguments:
y_pred -- python list containing three objects:
anchor -- the encodings for the anchor images, of shape (None, 128)
positive -- the encodings for the positive images, of shape (None, 128)
negative -- the encodings for the negative images, of shape (None, 128)
Returns:
loss -- real number, value of the loss
"""
anchor, positive, negative = y_pred[0], y_pred[1], y_pred[2]
pos_dist = tf.reduce_sum(tf.square(tf.subtract(anchor, positive)), -1)
neg_dist = tf.reduce_sum(tf.square(tf.subtract(anchor, negative)), -1)
basic_loss = tf.add(tf.subtract(pos_dist, neg_dist), alpha)
loss = tf.reduce_mean(tf.maximum(basic_loss, 0.0))
return loss
def pre_train(self):
if self.pre_train_count is 1:
return
self.pre_train_count += 1
print(self.files)
for file in self.files:
name = file.split('.')[0]
if name is 'test':
continue
else:
embedding = img_to_encoding('images/' + file, self.faceNetModel)
if embedding is None:
continue
if name in self.face_ids:
self.face_ids[name].append(embedding)
else:
self.face_ids[name] = []
self.face_ids[name].append(embedding)
def one_shot_train(self, data):
name = data['name']
image_paths = data['image']
print(name, image_paths)
for image_path in image_paths:
if name in self.face_ids:
self.face_ids[name].append(img_to_encoding(image_path, self.faceNetModel))
else:
self.face_ids[name] = []
self.face_ids[name].append(img_to_encoding(image_path, self.faceNetModel))
return
def recognize(self, image_path):
encoding = img_to_encoding(image_path, self.faceNetModel)
if encoding is None:
return None
min_diff = 100
for (person, encs) in self.face_ids.items():
for enc in encs:
if enc is None:
continue
diff = np.linalg.norm(encoding - enc)
print(person, diff)
if diff < min_diff:
min_diff = diff
exp_person = person
print(str(min_diff), exp_person)
if min_diff > 0.65:
return None
return min_diff, exp_person