1.1 -使用卷积网络来进行编码
系统构建一个编码,对该编码的元素进行比较,FaceNet模型需要大量的数据和长时间的训练
#获取模型
FRmodel = faceRecoModel(input_shape=(3,96,96))
#打印模型的总参数数量
print(“参数数量:” + str(FRmodel.count_params()))
1.2.计算两个编码以及阈值之间的误差
13.使用三元组损失函数
(A,P,N)
def triplet_loss(y_true, y_pred, alpha=0.2):
“”"
根据公式(4)实现三元组损失函数
参数:
y_true -- true标签,当你在Keras里定义了一个损失函数的时候需要它,但是这里不需要。
y_pred -- 列表类型,包含了如下参数:
anchor -- 给定的“anchor”图像的编码,维度为(None,128)
positive -- “positive”图像的编码,维度为(None,128)
negative -- “negative”图像的编码,维度为(None,128)
alpha -- 超参数,阈值
返回:
loss -- 实数,损失的值
"""
# 获取anchor, positive, negative的图像编码
anchor, positive, negative = y_pred[0], y_pred[1], y_pred[2]
# 第一步:计算"anchor" 与 "positive"之间编码的距离,这里需要使用axis=-1
pos_dist = tf.reduce_sum(tf.square(tf.subtract(anchor, positive)), axis=-1)
# 第二步:计算"anchor" 与 "negative"之间编码的距离,这里需要使用axis=-1
neg_dist = tf.reduce_sum(tf.square(tf.subtract(anchor, negative)), axis=-1)
# 第三步:减去之前的两个距离,然后加上alpha
basic_loss = tf.add(tf.subtract(pos_dist, neg_dist), alpha)
# 通过取带零的最大值和对训练样本的求和来计算整个公式
loss = tf.reduce_sum(tf.maximum(basic_loss, 0))
return loss
with tf.Session() as test:
tf.set_random_seed(1)
y_true = (None, None, None)
y_pred = (tf.random_normal([3, 128], mean=6, stddev=0.1, seed=1),
tf.random_normal([3, 128], mean=1, stddev=1, seed=1),
tf.random_normal([3, 128], mean=3, stddev=4, seed=1))
loss = triplet_loss(y_true, y_pred)
print("loss = " + str(loss.eval()))
FaceNet是通过最小化组损失来训练的,但是由于训练需要大量的数据和时间,所以我们不会从头训练,相反,我们会加载一个已经训练好了的模型,运行下列代码来加载模型
#开始时间
start_time = time.clock()
#编译模型
FRmodel.compile(optimizer = ‘adam’, loss = triplet_loss, metrics = [‘accuracy’])
#加载权值
fr_utils.load_weights_from_FaceNet(FRmodel)
#结束时间
end_time = time.clock()
#计算时差
minium = end_time - start_time
print(“执行了:” + str(int(minium / 60)) + “分” + str(int(minium%60)) + “秒”)
database = {}
database[“danielle”] = fr_utils.img_to_encoding(“images/danielle.png”, FRmodel)
database[“younes”] = fr_utils.img_to_encoding(“images/younes.jpg”, FRmodel)
database[“tian”] = fr_utils.img_to_encoding(“images/tian.jpg”, FRmodel)
database[“andrew”] = fr_utils.img_to_encoding(“images/andrew.jpg”, FRmodel)
database[“kian”] = fr_utils.img_to_encoding(“images/kian.jpg”, FRmodel)
database[“dan”] = fr_utils.img_to_encoding(“images/dan.jpg”, FRmodel)
database[“sebastiano”] = fr_utils.img_to_encoding(“images/sebastiano.jpg”, FRmodel)
database[“bertrand”] = fr_utils.img_to_encoding(“images/bertrand.jpg”, FRmodel)
database[“kevin”] = fr_utils.img_to_encoding(“images/kevin.jpg”, FRmodel)
database[“felix”] = fr_utils.img_to_encoding(“images/felix.jpg”, FRmodel)
database[“benoit”] = fr_utils.img_to_encoding(“images/benoit.jpg”, FRmodel)
database[“arnaud”] = fr_utils.img_to_encoding(“images/arnaud.jpg”, FRmodel)
def verify(image_path,identity,database,model):
encoding =fr_utils.img_to_encoding(image_path,model)
dist =linalg.norm(encoding -database[identity])
if dist <0.7:
print("欢迎 "+str(identity) + "回家!")
is_door_open =True
else:
print("经验证,您与"+str(identity) +"不符!")
is_door_open =False
return dist,is_door_open
verify(“images/camera_0.jpg”,“younes”,database,FRmodel)
def who_is_it(image_path,database,model):
“”“根据指定的图片来进行人脸识别”“”
#计算图像的编码
encodings =fr_utils.img_to_encoding(image_path,model)
# 找到最相近的编码
min_dist =100
#遍历数据库找到最相近的编码
for(name,db_enc) in database.items():
dist =linalg.norm(encodings-db_enc)
if dist 0.7:
print("抱歉,您的信息不在数据库中.")
else:
print("姓名" +str(identity) +" 差距 " +str(min_dist))
return min_dist,identity
who_is_it(“images/camera_0.jpg”,database,FRmodel)