原标题:OpenCV+Tensorflow实现实时人脸识别演示
Facenet网络介绍
FaceNet是谷歌提出的人脸识别模型,它跟其他人脸识别模型最大的一个不同就是它不是一个中间层输出,而是直接在欧几里德低维空间嵌入生成人脸特征,这个对以后的各种识别、分类、相似度比较都非常方便。相比其他的深度学习方法,FaceNet仅需要128个字节来表示一张脸。FaceNet网络设计目标任务有如下
1.验证-验证是否为同一张脸
3.聚类-发现人脸具有相同之处的人
关于什么是神经网络嵌入,这个解释比较复杂,简单的说神经网络的嵌入学习可以帮助我们把离散变量表示为连续的向量,在低维空间找到最近邻,tensorflow中的word2vec就是用了嵌入。一旦嵌入神经网络训练好以后,目标任务就变得很简单:
人脸验证 – 就变成相似度比较问题
人脸识别 – 就变成KNN分类问题
人脸聚类 – 就变成通过K-Means可以完成的问题
相比其它的人脸识别网络,通过添加分类层实现人脸识别,在分类层之前输出的人脸特征数据动则就几千个维度数据,而且不能很好表达一张新的人脸。FaceNet使用三元损失函数基于LMNN训练输出128维的连续向量。三元损失包含了两个匹配人脸的指纹与一个不匹配的人脸指纹,损失函数训练的目标是训练它在匹配人脸指纹与不匹配人脸指纹之间距离margin足够大为止。人脸指纹来自人脸区域图像,没有经过对齐,只是结果简单的几何变换。整个网络架构与三元表示如下:
其中
对正负样本的选择需要选择难样本得到triplet,有利于更好的训练效果与模型收敛。
代码实现:
借用了Github上的一个tensorflow版本facenet实现,下载了预训练的facenet模型,基于得到embedding数据,这个会输出512个维度数据,进行比较实现人脸相似度计算。相似度计算采用了余弦相似度度量,两个嵌入数据距离为0表示完全一致,距离为1表示完全不同。0.5或者90度表示二者相互独立。
facenet预训练模型下载:
/davidsandberg/facenet
加载模型与样本数据代码如下
withtf.Graph().as_default():
withtf.Session() assess:
# Load the model
facenet.load_model( "D:/python/facenet/data/0408-102900")
# Get input and output tensors
images_placeholder = tf.get_default_graph().get_tensor_by_name( "input:0")
embeddings = tf.get_default_graph().get_tensor_by_name( "embeddings:0")
phase_train_placeholder = tf.get_default_graph().get_tensor_by_name( "phase_train:0")
# Run forward pass to calculate embeddings
images, names = load_face_labels()
num_labels = len(names)
feed_dict = {images_placeholder: images, phase_train_placeholder: False}
labels_embeddings = sess.run(embeddings, feed_dict=feed_dict)
人脸比较的代码如下
defface_compare(face_image):
# Run forward pass to calculate embeddings
feed_dict = {images_placeholder: face_image, phase_train_placeholder: False}
embedding_result = sess.run(embeddings, feed_dict=feed_dict)
minDist = 1000000
label_index = -1
fori inrange(num_labels):
# 余弦相似
dist = facenet.distance([labels_embeddings[i]], [embedding_result[ 0]], 1)
ifminDist > dist:
label_index = i
minDist = dist
print( "minDist: %1.4f"%minDist)
ifminDist > 0.25:
return"unknown"
ifnames[label_index] == 3:
return"zhigang"
ifnames[label_index] == 2:
return"peter"
ifnames[label_index] == 1:
return"balvin"
OpenCV实时摄像头调用与输出
capture = cv.VideoCapture( 0)
height = capture. get(cv.CAP_PROP_FRAME_HEIGHT)
width = capture. get(cv.CAP_PROP_FRAME_WIDTH)
out= cv.VideoWriter( "D:/faces.mp4", cv.VideoWriter_fourcc( 'D', 'I', 'V', 'X'), 15,
(np. int(width), np. int(height)), True)
whileTrue:
ret, frame = capture.read()
ifret isTrue:
frame = cv.flip(frame, 1)
cv.imshow( "frame", frame)
rgb = cv.cvtColor(frame, cv.COLOR_BGR2RGB)
result, bb = mtcnn_align_demo(rgb)
ifresult isnot None:
name = face_compare(result)
cv.rectangle(frame, (bb[ 0], bb[ 1]), (bb[ 2], bb[ 3]), ( 0, 0, 255), 1, 8, 0)
cv.putText(frame, name, (bb[ 0], bb[ 1]), cv.FONT_HERSHEY_SIMPLEX, 1.0, ( 0, 255, 0), 2, 8)
cv.imshow( "face recognition demo", frame)
out.write(frame)
cv.imwrite( "D:/face_recognition.png", frame)
c = cv.waitKey( 10)
ifc == 27:
break
else:
break
out.release()
capture.release()
cv.destroyAllWindows()
人脸数据采集
通过MTCNN进行人脸实时检测,采集了待比较的每个人的人脸数据,进行了数据采选,打上了标签。采集数据代码如下:
whileTrue:
ret, frame = capture.read()
ifret isTrue:
frame = cv.flip(frame, 1)
cv.imshow( "frame", frame)
rgb = cv.cvtColor(frame, cv.COLOR_BGR2RGB)
result = detection(rgb)
out.write(result)
c = cv.waitKey( 10)
ifc == 27:
break
else:
break
cv.destroyAllWindows()
运行效果
balvin与我
欢迎扫码加入【OpenCV研习社】
- 学习OpenCV+tensorflow开发技术
- 与更多伙伴相互交流、一起学习进步
- 每周一到每周五分享知识点学习(音频+文字+源码)
- 系统化学习知识点,从易到难、由浅入深
- 直接向老师提问、每天答疑辅导返回搜狐,查看更多
责任编辑: