现在人脸识别功能已经很成熟了,就想做个好玩的小功能:
只要某人来到摄像头前,就播放语音:某某某,你好!
分解一下实现步骤,大概就是:
摄像头采集图像,然后运行人脸识别算法,识别出人脸特征,进行人脸比对,并进行语音提示。
再说一下编程语言的选取,目前做人工智能的,用python的最多,就用它了。
具体实现的时候,大体分为下面几部分:
1,找一个人脸识别库,运行起来;
2,添加人脸图片;
3,使用摄像头获取图像;
4,文字转换为音频文件;
5,播放音频文件;
6,人脸与音频播放关联起来;
7,循环执行。
下面具体说明下实现步骤:
一,找一个人脸识别库,运行起来
直接上网搜索,就有很多介绍推荐的,具体到能在自己的环境中运行起来,还是得试一试的。 我参考了几个例子后,选择的人脸识别库是:face_recognition,这是Github开源人脸识别项目。号称是世界上最简洁的人脸识别库,只需要几个接口,就完成了人脸识别功能。
我下面的demo中,只调用了如下4个接口:
定位图片中的所有人脸:
face_locations(face_image,number_of_times_to_upsample=1,model="hog")
识别人脸特征(128个特征向量):
face_encodings(face_image, known_face_locations=None, num_jitters=1)
人脸比对:
compare_faces(known_face_encodings, face_encoding_to_check, tolerance=0.6)
人脸距离:
face_distance(known_face_encodings, face_encoding_to_check)
示例是快速上手一个新库的主要手段,从Face Recognition 官方库下载 源码 ,打开其中的 examples 目录,可以看到里面有各种示例,我是参考了 face_distance.py 、 find_faces_in_picture.py 和 facerec_ipcamera_knn.py 来熟悉这个 Face Recognition 库的使用。
有了示例程序,然后就是搭建环境,主要就是安装几个依赖库:
pip install numpy opencv-python
pip install dlib
pip install face_recognition
再然后就是把demo跑起来了。
文章后面我会提供完整代码。
二,添加人脸图片
demo目录结构如下图:
train中,存放的是底库图片,图片名就是底库人脸对应的人名,例如,lintax.jpg;
test中,存放的是测试图片,具体来说就是test.jpg。
audio目录中,存放的是音频文件。
main.py,就是python代码。
这里,我先把自己用手机拍的照片传进去,选一个有自己正脸的,裁剪得只有自己正脸的图片,编辑图片名称,做为人脸底库。然后换另一张多人的照片,看能否识别到自己。
开头试了下,竟然不能识别到!
做了如下几种调整后,可以识别了:
1,缩小底库图片;
我是缩小到240*240,与例程中图像分辨率比较接近就行了。
2,缩小测试图片,也是缩放到与例程分辨率比较接近的程度。
然后,就能识别到自己了。
然而,出现了一个新问题,有别人也被识别到我了。
考虑这个情况是比对的阈值选择问题,要更加严格一些。这里就需要来调整人脸比对的阈值;
看这个人脸比对函数:
compare_faces(known_face_encodings, face_encoding_to_check, tolerance=0.6)
参考face_recognition项目的中文说明:
tolerance=0.6:两张脸之间有多少距离才算匹配。该值越小对比越严格,0.6是典型的最佳值。
再看另一处说明:
本项目的人脸识别是基于业内领先的C++开源库 dlib中的深度学习模型,用Labeled Faces in the Wild人脸数据集进行测试,有高达99.38%的准确率。但对小孩和亚洲人脸的识别准确率尚待提升。
亚洲人脸,毫无疑问,我的脸是属于其中的。我也不会去搞什么人脸训练工作,就调整下阈值试试吧。
试了下,把阈值改为0.4就可以了:
tolerance=0.4
到这里,主体功能算是可用了,剩下就是添枝加叶了。
三,使用摄像头获取图像
就是如下两步,就获取到摄像头的图像了:
cam = cv2.VideoCapture(0)
ret,img = cam.read()
接下来,就是把这个图片送入人脸识别,看看能否出结果。
当然,前提是电脑上有个摄像头,并且可以正常工作。
四,文字转换为音频文件
这里,我是采用的网络上的在线转换,见如下地址:
https://app.xunjiepdf.com/text2voice/
输入文字,然后转音频,下载,很方便的。
五,播放音频文件
选什么音频播放库,我对比了几个,选择了playsound,因为它支持mp3,而前面我获取的音频文件就是mp3格式的。
播放动作,也很方便,就是一句代码的事:
playsound('./audio/hello_lintax.mp3')
六,人脸与音频播放关联起来
这个也简单,就是选匹配度最高的特征,对应到人名,再与音频播放关联起来:
name = known_names[best_match] #选匹配度最高的名字
if(name.lower()=="lintax"): #判断人名,与音频播放关联起来
playsound('./audio/hello_lintax.mp3')
七,循环执行
就是在前面的一次性人脸识别之外,添加一个while循环。
我这里也是简单处理,每5秒从摄像机捕获一帧图像,进行特征提取、比对,根据匹配情况确定是否播放语音。
八,源码
整个demo的代码如下,当然,也可以直接下载(python人脸识别demo-深度学习文档类资源-CSDN下载):
import face_recognition as fr
import cv2
import numpy as np
import os
import time
from playsound import playsound
path = "./train/"
known_names = []
known_name_encodings = []
print("train:")
images = os.listdir(path)
for file_name in images:
print(file_name)
image = fr.load_image_file(path + file_name)
image_path = path + file_name
encoding = fr.face_encodings(image)[0]
#print(encoding)
known_name_encodings.append(encoding)
known_names.append(os.path.splitext(os.path.basename(image_path))[0].capitalize())
print(known_names)
#调用摄像头
cam = cv2.VideoCapture(0)
minW = 0.1*cam.get(3)
minH = 0.1*cam.get(4)
while True:
print("cam.read")
ret,img = cam.read()
#展示捕获图片
print("imshow")
cv2.imshow('camera',img)
k = cv2.waitKey(20)
print("input key is ",k)
if k == 27: # esc
break
#test_image = "./test/test.jpg"
#image = cv2.imread(test_image)
image = img
# image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
print("face_locations:")
face_locations = fr.face_locations(image)
print("face_encodings:")
face_encodings = fr.face_encodings(image, face_locations)
for (top, right, bottom, left), face_encoding in zip(face_locations, face_encodings):
print("compare_faces:")
matches = fr.compare_faces(known_name_encodings, face_encoding, tolerance=0.4)
name = ""
print(matches)
print("face_distance:")
face_distances = fr.face_distance(known_name_encodings, face_encoding)
print(face_distances)
best_match = np.argmin(face_distances)
print(best_match)
if matches[best_match]:
name = known_names[best_match]
print(name)
if(name.lower()=="lintax"):
playsound('./audio/hello_lintax.mp3')
cv2.rectangle(image, (left, top), (right, bottom), (0, 0, 255), 2)
cv2.rectangle(image, (left, bottom - 15), (right, bottom), (0, 0, 255), cv2.FILLED)
font = cv2.FONT_HERSHEY_DUPLEX
cv2.putText(image, name, (left + 6, bottom - 6), font, 1.0, (255, 255, 255), 1)
#cv2.imwrite("./output.jpg", image)
time.sleep(5)
#释放资源
cam.release()
cv2.destroyAllWindows()
主要参考文章:
http://www.zzvips.com/article/210357.html
https://github.com/ageitgey/face_recognition
https://zhuanlan.zhihu.com/p/45827914