Python 3 利用 Dlib 实现摄像头实时人脸识别

0.引言

  利用 Python 开发,借助 Dlib 库捕获摄像头中的人脸,提取人脸特征,通过计算特征值之间的欧氏距离,来和预存的人脸特征进行对比,判断是否匹配,达到人脸识别的目的;

  可以从摄像头中抠取人脸图片存储到本地,然后提取构建预设人脸特征;

  根据抠取的 / 已有的同一个人多张人脸图片提取 128D 特征值,然后计算该人的 128D 特征均值;

  然后和摄像头中实时获取到的人脸提取出的特征值,计算欧氏距离,判定是否为同一张人脸;  

    

  Features :

  • 支持人脸数据采集,自行建立人脸数据库
  • 调用摄像头实时人脸检测和识别
  • 支持多张人脸 ( updated on 08.23 )    

 

  人脸识别 / Face Recognition 的说明:

  Wikipedia 关于人脸识别系统 / Face Recognition System 的描述:they work by comparing selected facial features from given image with faces within a database.

  本项目中就是比较 预设的人脸的特征 和 摄像头实时获取到的人脸的特征 

  核心就是 提取 128D 人脸特征,然后计算 摄像头人脸特征 和 预设的特征脸的欧式距离,进行比对;

 

  效果如下(分别给出单张/两张人脸情况下识别结果 ):

  

Python 3 利用 Dlib 实现摄像头实时人脸识别_第1张图片

Python 3 利用 Dlib 实现摄像头实时人脸识别_第2张图片  

Python 3 利用 Dlib 实现摄像头实时人脸识别_第3张图片

 

图 1 摄像头单个/两个人脸识别效果 

 

1. 总体流程

  先说下 人脸检测 ( Face detection ) 和 人脸识别 ( Face Recognition ) ,前者是达到检测出场景中人脸的目的就可以了,而后者不仅需要检测出人脸,还要和已有人脸数据进行比对,识别出是否在数据库中,或者进行身份标注之类处理,人脸检测和人脸识别两者有时候可能会被理解混淆;

  我的之前一些项目都是用 Dlib 做人脸检测这块,这个项目想要实现的功能是人脸识别功能,借助的是 Dlib 官网中 face_recognition.py 这个例程 ( Link:http://dlib.net/face_recognition.py.html );

  核心在于 利用 “dlib_face_recognition_resnet_model_v1.dat” 这个 model,提取人脸图像的 128D 特征,然后比对不同人脸图片的 128D 特征,设定阈值 计算欧氏距离 来判断是否为同一张脸;

1 # face recognition model, the object maps human faces into 128D vectors
2 facerec = dlib.face_recognition_model_v1("dlib_face_recognition_resnet_model_v1.dat")
3 
4 shape = predictor(img, dets[0])
5 face_descriptor = facerec.compute_face_descriptor(img, shape)

 

   

Python 3 利用 Dlib 实现摄像头实时人脸识别_第4张图片

图 2 总体设计流程

 

2.源码介绍

  主要有

    get_face_from_camera.py , 

    get_features_into_CSV.py ,

    face_reco_from_camera.py

  这三个 .py 文件,下面分别介绍;

 

2.1 get_face_from_camera.py / 人脸注册录入

  人脸识别需要将 提取到的图像数据 和 已有图像数据 进行比对分析,所以这部分代码实现的功能就是 人脸录入

  程序会生成一个窗口,显示调用的摄像头实时获取的图像;

  (关于摄像头的调用方式可以参考这里: Python 3 利用 Dlib 19.7 实现摄像头人脸检测特征点标定);

  

  然后根据键盘输入进行人脸捕获:

  • “N” 新录入人脸,新建文件夹 person_X/  用来存储某人的人脸图像
  • "S" 开始捕获人脸,将捕获到的人脸放到 person_X/ 路径下
  • “Q” 退出窗口

  

  摄像头的调用是利用 opencv 库的 cv2.VideoCapture(0), 此处参数为 0 代表调用的是笔记本的默认摄像头,你也可以让它调用传入已有视频文件;

 Python 3 利用 Dlib 实现摄像头实时人脸识别_第5张图片 

图 3  get_face_from_camera.py 的界面

   

  捕获到的一组人脸示例;

Python 3 利用 Dlib 实现摄像头实时人脸识别_第6张图片

图 4 捕获到的一组人脸

 

  get_face_from_camera.py 源码

复制代码

  1 # created at 2018-05-11
  2 # updated at 2018-09-07
  3 
  4 # Author:   coneypo
  5 # Blog:     http://www.cnblogs.com/AdaminXie
  6 # GitHub:   https://github.com/coneypo/Dlib_face_recognition_from_camera
  7 
  8 # 进行人脸录入
  9 # 录入多张人脸
 10 import dlib         # 人脸识别的库 Dlib
 11 import numpy as np  # 数据处理的库 Numpy
 12 import cv2          # 图像处理的库 OpenCv
 13 import os
 14 import shutil
 15 
 16 # Dlib 预测器
 17 detector = dlib.get_frontal_face_detector()
 18 predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')
 19 
 20 # 创建 cv2 摄像头对象
 21 cap = cv2.VideoCapture(0)
 22 
 23 # cap.set(propId, value)
 24 # 设置视频参数,propId 设置的视频参数,value 设置的参数值
 25 cap.set(3, 480)
 26 
 27 # 截图 screenshoot 的计数器
 28 cnt_ss = 0
 29 
 30 # 人脸截图的计数器
 31 cnt_p = 0
 32 
 33 # 存储人脸的文件夹
 34 current_face_dir = 0
 35 
 36 # 保存
 37 path_make_dir = "data/faces_from_camera/"
 38 
 39 path_csv = "data/csvs_from_camera/"
 40 
 41 
 42 # clear the old folders at first
 43 def pre_clear():
 44     folders_rd = os.listdir(path_make_dir)
 45     for i in range(len(folders_rd)):
 46         shutil.rmtree(path_make_dir+folders_rd[i])
 47 
 48     csv_rd = os.listdir(path_csv)
 49     for i in range(len(csv_rd)):
 50         os.remove(path_csv+csv_rd[i])
 51 
 52 
 53 # clear the exist folders of faces and csv
 54 pre_clear()
 55 
 56 
 57 # 人脸种类数目的计数器
 58 person_cnt = 0
 59 
 60 # cap.isOpened() 返回 true/false 检查初始化是否成功
 61 while cap.isOpened():
 62 
 63     # cap.read()
 64     # 返回两个值:
 65     #    一个布尔值 true/false,用来判断读取视频是否成功/是否到视频末尾
 66     #    图像对象,图像的三维矩阵q
 67     flag, im_rd = cap.read()
 68 
 69     # 每帧数据延时 1ms,延时为 0 读取的是静态帧
 70     kk = cv2.waitKey(1)
 71 
 72     # 取灰度
 73     img_gray = cv2.cvtColor(im_rd, cv2.COLOR_RGB2GRAY)
 74 
 75     # 人脸数 rects
 76     rects = detector(img_gray, 0)
 77 
 78     # print(len(rects))q
 79 
 80     # 待会要写的字体
 81     font = cv2.FONT_HERSHEY_COMPLEX
 82 
 83     # 按下 'n' 新建存储人脸的文件夹
 84     if kk == ord('n'):
 85         person_cnt += 1
 86         # current_face_dir = path_make_dir + time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime())
 87         current_face_dir = path_make_dir + "person_" + str(person_cnt)
 88         print('\n')
 89         for dirs in (os.listdir(path_make_dir)):
 90             if current_face_dir == path_make_dir + dirs:
 91                 shutil.rmtree(current_face_dir)
 92                 print("删除旧的文件夹:", current_face_dir)
 93         os.makedirs(current_face_dir)
 94         print("新建的人脸文件夹: ", current_face_dir)
 95 
 96         # 将人脸计数器清零
 97         cnt_p = 0
 98 
 99     if len(rects) != 0:
100         # 检测到人脸
101 
102         # 矩形框
103         for k, d in enumerate(rects):
104 
105             # 计算矩形大小
106             # (x,y), (宽度width, 高度height)
107             pos_start = tuple([d.left(), d.top()])
108             pos_end = tuple([d.right(), d.bottom()])
109 
110             # 计算矩形框大小
111             height = d.bottom() - d.top()
112             width = d.right() - d.left()
113 
114             # 根据人脸大小生成空的图像
115             cv2.rectangle(im_rd, tuple([d.left(), d.top()]), tuple([d.right(), d.bottom()]), (0, 255, 255), 2)
116             im_blank = np.zeros((height, width, 3), np.uint8)
117 
118             # 按下 's' 保存摄像头中的人脸到本地
119             if kk == ord('s'):
120                 cnt_p += 1
121                 for ii in range(height):
122                     for jj in range(width):
123                         im_blank[ii][jj] = im_rd[d.top() + ii][d.left() + jj]
124                 cv2.imwrite(current_face_dir + "/img_face_" + str(cnt_p) + ".jpg", im_blank)
125                 print("写入本地:", str(current_face_dir) + "/img_face_" + str(cnt_p) + ".jpg")
126 
127         # 显示人脸数
128     cv2.putText(im_rd, "Faces: " + str(len(rects)), (20, 100), font, 0.8, (0, 255, 0), 1, cv2.LINE_AA)
129 
130     # 添加说明
131     cv2.putText(im_rd, "Face Register", (20, 40), font, 1, (255, 255, 255), 1, cv2.LINE_AA)
132     cv2.putText(im_rd, "N: New face folder", (20, 350), font, 0.8, (255, 255, 255), 1, cv2.LINE_AA)
133     cv2.putText(im_rd, "S: Save face", (20, 400), font, 0.8, (255, 255, 255), 1, cv2.LINE_AA)
134     cv2.putText(im_rd, "Q: Quit", (20, 450), font, 0.8, (255, 255, 255), 1, cv2.LINE_AA)
135 
136     # 按下 'q' 键退出
137     if kk == ord('q'):
138         break
139 
140     # 窗口显示
141     # cv2.namedWindow("camera", 0) # 如果需要摄像头窗口大小可调
142     cv2.imshow("camera", im_rd)
143 
144 # 释放摄像头
145 cap.release()
146 
147 # 删除建立的窗口
148 cv2.destroyAllWindows()

复制代码

 

  get_face_from_camera.py 的输出 log

复制代码

删除旧的文件夹: F:/code/python/P_dlib_face_reco/data/faces_from_camera/person_1
新建的人脸文件夹:  F:/code/python/P_dlib_face_reco/data/faces_from_camera/person_1
写入本地: F:/code/python/P_dlib_face_reco/data/faces_from_camera/person_1/img_face_1.jpg
写入本地: F:/code/python/P_dlib_face_reco/data/faces_from_camera/person_1/img_face_2.jpg
写入本地: F:/code/python/P_dlib_face_reco/data/faces_from_camera/person_1/img_face_3.jpg
写入本地: F:/code/python/P_dlib_face_reco/data/faces_from_camera/person_1/img_face_4.jpg
写入本地: F:/code/python/P_dlib_face_reco/data/faces_from_camera/person_1/img_face_5.jpg
写入本地: F:/code/python/P_dlib_face_reco/data/faces_from_camera/person_1/img_face_6.jpg


删除旧的文件夹: F:/code/python/P_dlib_face_reco/data/faces_from_camera/person_2
新建的人脸文件夹:  F:/code/python/P_dlib_face_reco/data/faces_from_camera/person_2
写入本地: F:/code/python/P_dlib_face_reco/data/faces_from_camera/person_2/img_face_1.jpg
写入本地: F:/code/python/P_dlib_face_reco/data/faces_from_camera/person_2/img_face_2.jpg
写入本地: F:/code/python/P_dlib_face_reco/data/faces_from_camera/person_2/img_face_3.jpg
写入本地: F:/code/python/P_dlib_face_reco/data/faces_from_camera/person_2/img_face_4.jpg


删除旧的文件夹: F:/code/python/P_dlib_face_reco/data/faces_from_camera/person_3
新建的人脸文件夹:  F:/code/python/P_dlib_face_reco/data/faces_from_camera/person_3
写入本地: F:/code/python/P_dlib_face_reco/data/faces_from_camera/person_3/img_face_1.jpg
写入本地: F:/code/python/P_dlib_face_reco/data/faces_from_camera/person_3/img_face_2.jpg
写入本地: F:/code/python/P_dlib_face_reco/data/faces_from_camera/person_3/img_face_3.jpg
写入本地: F:/code/python/P_dlib_face_reco/data/faces_from_camera/person_3/img_face_4.jpg
写入本地: F:/code/python/P_dlib_face_reco/data/faces_from_camera/person_3/img_face_5.jpg
写入本地: F:/code/python/P_dlib_face_reco/data/faces_from_camera/person_3/img_face_6.jpg
写入本地: F:/code/python/P_dlib_face_reco/data/faces_from_camera/person_3/img_face_7.jpg

复制代码

 

2.2 get_features_into_CSV.py / 将图像文件中人脸数据提取出来存入 CSV

  这部分代码实现的功能是将之前捕获到的人脸图像文件,提取出 128D 特征,然后计算出某人人脸数据的特征均值存入 CSV 中,方便之后识别时候进行比对;

  利用 numpy.mean() 计算特征均值;

  get_features_into_CSV.py 源码:

复制代码

  1 # created at 2018-05-11
  2 
  3 # updated at 2018-09-06
  4 # 增加录入多张人脸到CSV的功能
  5 
  6 # By        coneypo
  7 # Blog:     http://www.cnblogs.com/AdaminXie
  8 # GitHub:   https://github.com/coneypo/Dlib_face_recognition_from_camera
  9 
 10 #   return_128d_features()          获取某张图像的128d特征
 11 #   write_into_csv()                将某个文件夹中的图像读取特征并写入csv
 12 #   compute_the_mean()              从csv中读取128d特征,并计算特征均值
 13 
 14 
 15 import cv2
 16 import os
 17 import dlib
 18 from skimage import io
 19 import csv
 20 import numpy as np
 21 import pandas as pd
 22 
 23 path_faces_rd = "data/faces_from_camera/"
 24 path_csv = "data/csvs_from_camera/"
 25 
 26 # detector to find the faces
 27 detector = dlib.get_frontal_face_detector()
 28 
 29 # shape predictor to find the face landmarks
 30 predictor = dlib.shape_predictor("shape_predictor_5_face_landmarks.dat")
 31 
 32 # face recognition model, the object maps human faces into 128D vectors
 33 facerec = dlib.face_recognition_model_v1("dlib_face_recognition_resnet_model_v1.dat")
 34 
 35 
 36 # 返回单张图像的128D特征
 37 def return_128d_features(path_img):
 38     img = io.imread(path_img)
 39     img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
 40     dets = detector(img_gray, 1)
 41 
 42     print("检测的人脸图像:", path_img, "\n")
 43 
 44     # 因为有可能截下来的人脸再去检测,检测不出来人脸了
 45     # 所以要确保是 检测到人脸的人脸图像 拿去算特征
 46     if len(dets) != 0:
 47         shape = predictor(img_gray, dets[0])
 48         face_descriptor = facerec.compute_face_descriptor(img_gray, shape)
 49     else:
 50         face_descriptor = 0
 51         print("no face")
 52 
 53     # print(face_descriptor)
 54     return face_descriptor
 55 
 56 
 57 # 将文件夹中照片特征提取出来,写入csv
 58 # 输入input:
 59 #   path_faces_personX:     图像文件夹的路径
 60 #   path_csv:               要生成的csv路径
 61 
 62 def write_into_csv(path_faces_personX, path_csv):
 63     dir_pics = os.listdir(path_faces_personX)
 64     with open(path_csv, "w", newline="") as csvfile:
 65         writer = csv.writer(csvfile)
 66         for i in range(len(dir_pics)):
 67             # 调用return_128d_features()得到128d特征
 68             print("正在读的人脸图像:", path_faces_personX + "/" + dir_pics[i])
 69             features_128d = return_128d_features(path_faces_personX + "/" + dir_pics[i])
 70             #  print(features_128d)
 71             # 遇到没有检测出人脸的图片跳过
 72             if features_128d == 0:
 73                 i += 1
 74             else:
 75                 writer.writerow(features_128d)
 76 
 77 
 78 # 读取 某人 所有的人脸图像的数据,写入 person_X.csv
 79 faces = os.listdir(path_faces_rd)
 80 for person in faces:
 81     print(path_csv + person + ".csv")
 82     write_into_csv(path_faces_rd + person, path_csv + person + ".csv")
 83 
 84 
 85 # 从csv中读取数据,计算128d特征的均值
 86 def compute_the_mean(path_csv_rd):
 87     column_names = []
 88 
 89     # 128列特征
 90     for i in range(128):
 91         column_names.append("features_" + str(i + 1))
 92 
 93     # 利用pandas读取csv
 94     rd = pd.read_csv(path_csv_rd, names=column_names)
 95 
 96     # 存放128维特征的均值
 97     feature_mean = []
 98 
 99     for i in range(128):
100         tmp_arr = rd["features_" + str(i + 1)]
101         tmp_arr = np.array(tmp_arr)
102 
103         # 计算某一个特征的均值
104         tmp_mean = np.mean(tmp_arr)
105         feature_mean.append(tmp_mean)
106     return feature_mean
107 
108 
109 # 存放所有特征均值的 CSV 的路径
110 path_csv_feature_all = "data/features_all.csv"
111 # 存放人脸特征的csv的路径
112 path_csv_rd = "data/csvs_from_camera/"
113 
114 with open(path_csv_feature_all, "w", newline="") as csvfile:
115     writer = csv.writer(csvfile)
116     csv_rd = os.listdir(path_csv_rd)
117     print("特征均值: ")
118     for i in range(len(csv_rd)):
119         feature_mean = compute_the_mean(path_csv_rd + csv_rd[i])
120         # print(feature_mean)
121         print(path_csv_rd + csv_rd[i])
122         writer.writerow(feature_mean)

复制代码

 

  我们可以看下对于某张图片,face_descriptor 的输出结果:

  绿色框内是我们的返回 128D 特征的函数;

  在红色框内调用该函数来计算 img_face_13.jpg;

  可以看到黄色框中的输出为 128D 的向量;

Python 3 利用 Dlib 实现摄像头实时人脸识别_第7张图片

图 5 返回单张图像的 128D 特征的计算结果

 

  所以就把人脸图像进行批量化操作,提取出 128D 的特征,然后计算特征均值,存入 features_all.csv;

  features_all.csv 是一个 n 行 128 列的 CSV, n 是录入的人脸数,128 列是某人的 128D 特征;

  这存储的就是 录入的人脸数据,之后 摄像头捕获的人脸 将要拿过来和 这些特征值 进行比对,如果欧式距离比较近的话,就可以认为是同一张人脸

 

   get_features_into_CSV.py 的输出 log:

复制代码

F:/code/python/P_dlib_face_reco/data/csvs_from_camera/person_1.csv
正在读的人脸图像: F:/code/python/P_dlib_face_reco/data/faces_from_camera/person_1/img_face_1.jpg
检测的人脸图像: F:/code/python/P_dlib_face_reco/data/faces_from_camera/person_1/img_face_1.jpg 

...

正在读的人脸图像: F:/code/python/P_dlib_face_reco/data/faces_from_camera/person_5/img_face_3.jpg
检测的人脸图像: F:/code/python/P_dlib_face_reco/data/faces_from_camera/person_5/img_face_3.jpg 

正在读的人脸图像: F:/code/python/P_dlib_face_reco/data/faces_from_camera/person_5/img_face_4.jpg
检测的人脸图像: F:/code/python/P_dlib_face_reco/data/faces_from_camera/person_5/img_face_4.jpg 

正在读的人脸图像: F:/code/python/P_dlib_face_reco/data/faces_from_camera/person_5/img_face_5.jpg
检测的人脸图像: F:/code/python/P_dlib_face_reco/data/faces_from_camera/person_5/img_face_5.jpg 

特征均值: 
F:/code/python/P_dlib_face_reco/data/csvs_from_camera/person_1.csv
F:/code/python/P_dlib_face_reco/data/csvs_from_camera/person_2.csv
F:/code/python/P_dlib_face_reco/data/csvs_from_camera/person_3.csv
F:/code/python/P_dlib_face_reco/data/csvs_from_camera/person_4.csv
F:/code/python/P_dlib_face_reco/data/csvs_from_camera/person_5.csv

复制代码

 

2.3 face_reco_from_camera.py / 实时人脸识别对比分析

  这部分源码实现的功能:调用摄像头,捕获摄像头中的人脸,然后如果检测到人脸,将 摄像头中的人脸提取出 128D 的特征,然后和 之前录入人脸的 128D 特征 进行计算欧式距离,如果比较小,可以判定为一个人,否则不是一个人;

  欧氏距离对比的阈值设定,是在 return_euclidean_distance 函数的 dist 变量;

  我这里程序里面指定的 欧氏距离判断阈值是 0.4,具体阈值可以根据实际情况或者测得结果进行修改;

  

  这边做了一个,让人名跟随显示在头像下方,如果想要在人脸矩形框下方显示人名,首先需要知道 Dlib 生成的矩形框的尺寸怎么读取;

  Dlib 返回的 dets 变量是一系列人脸的数据,此处对单张人脸处理,所以取 dets[0] 的参数;

  可以通过 dets[0].top()dets[0].bottom()dets[0].left() 和 dets[0].right() 来确定要显示的人名的坐标;

Python 3 利用 Dlib 实现摄像头实时人脸识别_第8张图片

图 6 dets[0].top() 等参数说明 

  

  得到矩形框的坐标,就可以获取人名的相对位置;

  这是我这边取的坐标:

1 pos_text_1 = tuple([dets[0].left(), int(dets[0].bottom()+(dets[0].bottom()-dets[0].top())/4)])

 

  Python 3 利用 Dlib 实现摄像头实时人脸识别_第9张图片

图 7 face_reco_from_camera.py 生成的人脸识别窗口界面

 

 face_reco_from_camera.py 源码:

复制代码

  1 # created at 2018-05-11
  2 # updated at 2018-09-08
  3 # support multi-faces now
  4 
  5 # Author:   coneypo
  6 # Blog:     http://www.cnblogs.com/AdaminXie
  7 # GitHub:   https://github.com/coneypo/Dlib_face_recogqnition_from_camera
  8 
  9 import dlib         # 人脸识别的库dlib
 10 import numpy as np  # 数据处理的库numpy
 11 import cv2          # 图像处理的库OpenCv
 12 import pandas as pd # 数据处理的库Pandas
 13 
 14 # face recognition model, the object maps human faces into 128D vectors
 15 facerec = dlib.face_recognition_model_v1("dlib_face_recognition_resnet_model_v1.dat")
 16 
 17 
 18 # 计算两个向量间的欧式距离
 19 def return_euclidean_distance(feature_1, feature_2):
 20     feature_1 = np.array(feature_1)
 21     feature_2 = np.array(feature_2)
 22     dist = np.sqrt(np.sum(np.square(feature_1 - feature_2)))
 23     print("e_distance: ", dist)
 24 
 25     if dist > 0.4:
 26         return "diff"
 27     else:
 28         return "same"
 29 
 30 
 31 # 处理存放所有人脸特征的 CSV
 32 path_features_known_csv = "data/features_all.csv"
 33 csv_rd = pd.read_csv(path_features_known_csv, header=None)
 34 
 35 # 存储的特征人脸个数
 36 # print(csv_rd.shape[0])
 37 
 38 # 用来存放所有录入人脸特征的数组
 39 features_known_arr = []
 40 
 41 # known faces
 42 for i in range(csv_rd.shape[0]):
 43     features_someone_arr = []
 44     for j in range(0, len(csv_rd.ix[i, :])):
 45         features_someone_arr.append(csv_rd.ix[i, :][j])
 46     #    print(features_someone_arr)
 47     features_known_arr.append(features_someone_arr)
 48 print("Faces in Database:", len(features_known_arr))
 49 
 50 # Dlib 预测器
 51 detector = dlib.get_frontal_face_detector()
 52 predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')
 53 
 54 # 创建 cv2 摄像头对象
 55 cap = cv2.VideoCapture(0)
 56 
 57 # cap.set(propId, value)
 58 # 设置视频参数,propId 设置的视频参数,value 设置的参数值
 59 cap.set(3, 480)
 60 
 61 
 62 # 返回一张图像多张人脸的 128D 特征
 63 def get_128d_features(img_gray):
 64     dets = detector(img_gray, 1)
 65     if len(dets) != 0:
 66         face_des = []
 67         for i in range(len(dets)):
 68             shape = predictor(img_gray, dets[i])
 69             face_des.append(facerec.compute_face_descriptor(img_gray, shape))
 70     else:
 71         face_des = []
 72     return face_des
 73 
 74 
 75 # cap.isOpened() 返回true/false 检查初始化是否成功
 76 while cap.isOpened():
 77 
 78     flag, img_rd = cap.read()
 79     kk = cv2.waitKey(1)
 80 
 81     # 取灰度
 82     img_gray = cv2.cvtColor(img_rd, cv2.COLOR_RGB2GRAY)
 83 
 84     # 人脸数 dets
 85     faces = detector(img_gray, 0)
 86 
 87     # 待会要写的字体
 88     font = cv2.FONT_HERSHEY_COMPLEX
 89 
 90     cv2.putText(img_rd, "Press 'q': Quit", (20, 400), font, 0.8, (84, 255, 159), 1, cv2.LINE_AA)
 91 
 92     # 存储人脸名字和位置的两个 list
 93     # list 1 (faces): store the name of faces               Jack    unknown unknown Mary
 94     # list 2 (pos_namelist): store the positions of faces   12,1    1,21    1,13    31,1
 95 
 96     # 存储所有人脸的名字
 97     pos_namelist = []
 98     name_namelist = []
 99 
100     # 检测到人脸
101     if len(faces) != 0:
102         # 获取当前捕获到的图像的所有人脸的特征,存储到 features_cap_arr
103         features_cap_arr = []
104         for i in range(len(faces)):
105             shape = predictor(img_rd, faces[i])
106             features_cap_arr.append(facerec.compute_face_descriptor(img_rd, shape))
107 
108         # 遍历捕获到的图像中所有的人脸
109         for k in range(len(faces)):
110             # 让人名跟随在矩形框的下方
111             # 确定人名的位置坐标
112             # 先默认所有人不认识,是 unknown
113             name_namelist.append("unknown")
114 
115             # 每个捕获人脸的名字坐标
116             pos_namelist.append(tuple([faces[k].left(), int(faces[k].bottom() + (faces[k].bottom() - faces[k].top()) / 4)]))
117 
118             # 对于某张人脸,遍历所有存储的人脸特征
119             for i in range(len(features_known_arr)):
120                 print("with person_", str(i+1), "the ", end='')
121                 # 将某张人脸与存储的所有人脸数据进行比对
122                 compare = return_euclidean_distance(features_cap_arr[k], features_known_arr[i])
123                 if compare == "same":  # 找到了相似脸
124                     name_namelist[k] = "person_" + str(i+1)
125 
126             # 矩形框
127             for kk, d in enumerate(faces):
128                 # 绘制矩形框
129                 cv2.rectangle(img_rd, tuple([d.left(), d.top()]), tuple([d.right(), d.bottom()]), (0, 255, 255), 2)
130 
131         # 写人脸名字
132         for i in range(len(faces)):
133             cv2.putText(img_rd, name_namelist[i], pos_namelist[i], font, 0.8, (0, 255, 255), 1, cv2.LINE_AA)
134 
135     print("Name list now:", name_namelist, "\n")
136 
137     cv2.putText(img_rd, "Face Register", (20, 40), font, 1, (255, 255, 255), 1, cv2.LINE_AA)
138     cv2.putText(img_rd, "Faces: " + str(len(faces)), (20, 100), font, 1, (0, 0, 255), 1, cv2.LINE_AA)
139 
140     # 按下 q 键退出
141     if kk == ord('q'):
142         break
143 
144     # 窗口显示
145     cv2.imshow("camera", img_rd)
146 
147 # 释放摄像头
148 cap.release()
149 
150 # 删除建立的窗口
151 cv2.destroyAllWindows()

复制代码

 

 face_reco_from_camera.py 输出 log:

复制代码

Faces in Database: 5
Name list now: [] 

Name list now: [] 

Name list now: [] 

Name list now: [] 

Name list now: [] 

with person_ 1 the e_distance:  0.40770022710364756
with person_ 2 the e_distance:  0.41082186674421134
with person_ 3 the e_distance:  0.3961545573801463
with person_ 4 the e_distance:  0.3881850644563972
with person_ 5 the e_distance:  0.3495735780870818
Name list now: ['person_4'] 

with person_ 1 the e_distance:  0.4314467101915446
with person_ 2 the e_distance:  0.4299990464683071
with person_ 3 the e_distance:  0.4182695008637471
with person_ 4 the e_distance:  0.4173694262729763
with person_ 5 the e_distance:  0.38357217732017734
Name list now: ['person_4'] 

with person_ 1 the e_distance:  0.4262991040992263
with person_ 2 the e_distance:  0.43254966504500664
with person_ 3 the e_distance:  0.41576433114841965
with person_ 4 the e_distance:  0.4122140311433292
with person_ 5 the e_distance:  0.38073570942005236
Name list now: ['person_4'] 

with person_ 1 the e_distance:  0.42088261541728456
with person_ 2 the e_distance:  0.42064499551908163
with person_ 3 the e_distance:  0.404443147870785
with person_ 4 the e_distance:  0.4043774203639022
with person_ 5 the e_distance:  0.37271089160417986
Name list now: ['person_4'] 

复制代码

 

  实时输出结果:

Python 3 利用 Dlib 实现摄像头实时人脸识别_第10张图片

图 9 实时输出的欧氏距离结果

 

  通过实时的输出结果,看的比较明显;

  输出绿色部分:当是我自己(即之前分析提取特征的default_person)时,计算出来的欧式距离基本都在 0.2 左右

  输出红色部分:而换一张图片上去比如特朗普,明显看到欧式距离计算结果 达到了 0.8,此时就可以判定,后来这张人脸不是我们预设的人脸;

  所以之前提到的欧式距离计算对比的阈值可以由此设定,本项目中取的是 dist=0.4

 

3.总结

  核心就是 提取人脸特征,然后计算欧式距离和预设的特征脸进行比对;

  不过这个实时获取摄像头人脸进行比对,要实时的进行计算摄像头脸的特征值,然后还要计算欧氏距离,所以计算量比较大,可能摄像头视频流会出现卡顿;

   

  update on 09.06:

  满足多张人脸识别需要

# 请尊重他人劳动成果,转载或者使用源码请注明出处:http://www.cnblogs.com/AdaminXie

# 代码已上传到了我的 GitHub,如果对您有帮助欢迎 Star 下:https://github.com/coneypo/Dlib_face_recognition_from_camera

# 如有问题请留言或者联系邮箱: [email protected]

你可能感兴趣的:(Python 3 利用 Dlib 实现摄像头实时人脸识别)