0. 引言
利用 Python 语言开发,借助 Dlib 库提取出摄像头视频流中的人脸,提取人脸特征并计算特征值之间的欧氏距离,来和预存的人脸特征进行对比,判断是否匹配,达到人脸识别的目的;
实现的效果:
图1 已知人脸
图 2 未知人脸
图 3 多个已知人脸
1. 设计流程
先说下 人脸检测 ( Face Detection ) 和 人脸识别 ( Face Recognition ) ,人脸检测是达到检测出场景中人脸的目的就可以了,而后者不仅需要检测出人脸,还要和 已有人脸数据进行比对,识别出是否在数据库中,或者进行身份标注之类处理,人脸检测 和 人脸识别 两者有时候可能会被理解混淆;
Wikipedia 关于人脸识别系统 / Face Recognition System 的描述比较形象:they work by comparing selected facial features from given image with faces within a database.
本项目参考自 Dlib 官网例程 :
#face recognition model, the object maps human faces into 128D vectors
facerec = dlib.face_recognition_model_v1("dlib_face_recognition_resnet_model_v1.dat"
shape =predictor(img, dets[0])
face_descriptor = facerec.compute_face_descriptor(img, shape)
项目核心在于 利用 “dlib_face_recognition_resnet_model_v1.dat” 这个 model,提取人脸图像的 128D 特征 "face_descriptor",然后比对不同人脸图片的 128D 特征,计算不同人脸的 128D 特征的欧氏距离 来判断是否为同一张脸;
大概流程如下:
人脸录入 >>> 存入本地 CSV >>>
调用摄像头实时获取视频流 >>>
Dlib 实时人脸检测并计算 128D 特征 >>>
将摄像头人脸的特征与已知人脸特征进行比对 >>>
如果有欧式距离比较小的认为有相似的人脸显示人名
图 4 设计流程
2. 源码介绍
主要有
get_face_from_camera.py ,
get_features_into_CSV.py ,
face_reco_from_camera.py
这三个 python 文件,下面分别介绍;
2.1 get_face_from_camera.py / 人脸注册录入
人脸识别需要将 提取到的图像数据 和 已有图像数据 进行比对分析,所以这部分代码实现的功能就是 人脸录入;
程序会生成一个窗口,显示调用的摄像头实时获取的图像;
然后根据键盘输入进行人脸捕获:
> “N” 新录入人脸,新建文件夹 person_X/ 用来存储某人的人脸图像
> "S" 开始捕获人脸,将捕获到的人脸放到 person_X/ 路径下
> “Q” 退出窗口
部分代码:
#利用 Dlib 的正向人脸检测器
detector =dlib.get_frontal_face_detector()
rects =detector(img_gray, 0)
#遍历每个检测到的人脸
for k, d in enumerate(rects):
#计算坐标
pos_start =tuple([d.left(), d.top()])
pos_end =tuple([d.right(), d.bottom()])
#计算高度
height = d.bottom() -d.top()
width = d.right() -d.left()
#画人脸矩形特征框
cv2.rectangle(im_rd, tuple([d.left(), d.top()]), tuple([d.right(), d.bottom()]), (0, 255, 255), 2)
#根据人脸大小生成空的图像
im_blank = np.zeros((height, width, 3), np.uint8)
#按下 s 存储图片
ifkk == ord('s'):
cv2.imwrite("xxx.jpg", im_blank)
图 5 人脸矩形框坐标介绍
这样我们得到了 person_1, person_2, person_3... 的人脸图片,如下图所示。
图 6 存储的 person_x 的一组人脸
2.2 get_features_into_CSV.py /将图像文件中人脸数据提取出来存入CSV
这部分代码实现的功能是将之前捕获到的人脸图像文件,提取出 128D 特征,然后计算出某人人脸数据的特征均值存入 CSV 中,方便之后识别时候进行比对;利用 numpy.mean() 计算特征均值;
get_features_into_CSV.py 的部分代码:
# return_128d_features() 获取某张图像的 128D 特征
shape =predictor(img_gray, dets[0])
face_descriptor =facerec.compute_face_descriptor(img_gray, shape)
# write_into_csv() 将某个文件夹中的图像读取特征并写入 CSV
with open ("xx_csv","w", newline="") as csvfile:
writer = csv.writer(csvfile)
features_128d = return_128d_features(img_xxx)
writer.writerow(features_128d)
# compute_the_mean() 从 CSV 中读取 128D 特征,并计算特征均值
np.mean 计算均值
2.3 face_reco_from_camera.py/ 实时人脸识别对比分析
这部分源码实现的功能:
调用摄像头,捕获摄像头中的人脸,然后如果检测到人脸,将摄像头中的人脸提取出 128D 的特征,然后和之前录入人脸的 128D 特征 进行计算欧式距离,如果比较小(小于一个设定的阈值),可以判定为一个人,否则不是一个人;
欧氏距离对比的阈值设定,是在 return_euclidean_distance 函数的 dist 变量;
这部分实现的流程如下:
调用摄像头实时获取视频流 >>>
Dlib 实时人脸检测并计算 128D 特征 >>>
将摄像头人脸的特征与已知人脸特征进行比对 >>>
如果有欧式距离比较小的认为有相似的人脸显示人名
部分代码如下:
# 当摄像头开启时
whilecap.isOpened():
# 读取视频流
flag, img_rd =cap.read()
img_gray =cv2.cvtColor(img_rd, cv2.COLOR_RGB2GRAY)
#存储所有人脸的坐标/名字
pos_namelist =[]
name_namelist =[]
#遍历捕获到的图像中所有的人脸
forkinrange(len(faces)):
#让人名跟随在矩形框的下方
#确定人名的位置坐标
#先默认所有人不认识,是 unknown
name_namelist.append("unknown")
#每个捕获人脸的名字坐标
pos_namelist.append(tuple([faces[k].left(), int(faces[k].bottom() + (faces[k].bottom() - faces[k].top()) / 4)]))
#对于某张人脸,遍历所有存储的人脸特征
foriinrange(len(features_known_arr)):
print("with person_", str(i+1),"the", end='')
#将某张人脸与存储的所有人脸数据进行比对
compare =return_euclidean_distance(features_cap_arr[k], features_known_arr[i])
ifcompare =="same":#找到了相似脸
name_namelist[k] ="person_"+ str(i+1)
#矩形框
forkk, dinenumerate(faces):
#绘制矩形框
cv2.rectangle(img_rd, tuple([d.left(), d.top()]), tuple([d.right(), d.bottom()]), (0, 255, 255), 2)
#写人脸名字
foriinrange(len(faces)):
cv2.putText(img_rd, name_namelist[i], pos_namelist[i], font, 0.8, (0, 255, 255), 1, cv2.LINE_AA)
print("Name list now:", name_namelist,"\n")
cv2.putText(img_rd,"Face Register", (20, 40), font, 1, (255, 255, 255), 1, cv2.LINE_AA)
cv2.putText(img_rd,"Faces:"+ str(len(faces)), (20, 100), font, 1, (0, 0, 255), 1, cv2.LINE_AA)
cv2.imshow("camera", img_rd)
#释放摄像头
cap.release()
#删除建立的窗口
cv2.destroyAllWindows()
# 代码已上传到了我的 GitHub,如果对您有帮助欢迎 Star 下:https://github.com/coneypo/Dlib_face_recognition_from_camera
领取专属 10元无门槛券
私享最新 技术干货