大家好,欢迎来到IT知识分享网。
Dlib中,人脸识别的基本思路为:
- 计算已知图片中所有人脸对应的特征向量;
- 计算要识别的未知图片中所有人脸对应的特征向量;
- 计算人脸之间的欧式距离;
- 如果两张人脸之间的欧式距离小于设定的阈值,则认为是同一个人,否则认为不是同一个人
【 1. 计算特征向量 】
在人脸特征点检测中,我们学会了如何获取人脸的特征点。但是特征点只是用于标识人脸关键点的坐标而已,如果想要实现人脸识别,那么必须将特征点转换为特征向量。
1. 加载人脸识别模型
首先,我们得通过dlib.face_recognition_model_v1() 加载人脸识别的模型:
dlib.face_recognition_model_v1(人脸识别模型路径)
import dlib import cv2 #人脸识别模型的路径 face_rec_model_path = 'dlib_face_recognition_resnet_model_v1.dat' # 加载人脸识别模型 facerec = dlib.face_recognition_model_v1(face_rec_model_path)
2. 计算特征向量
在加载完模型之后,我们需要先使用前面学到的知识,先检测特征点:
import cv2 # 加载人脸识别模型 face_rec_model_path = 'dlib_face_recognition_resnet_model_v1.dat' facerec = dlib.face_recognition_model_v1(face_rec_model_path) # 加载特征点识别模型 predictor_path = "shape_predictor_5_face_landmarks.dat" predictor = dlib.shape_predictor(predictor_path) # 读取图片 img_path = "step1/image/face.jpg" img = cv2.imread(img_path) # 转换为灰阶图片 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 正向人脸检测器将图像 detector = dlib.get_frontal_face_detector() # 使用人脸识别模型来检测图像中的人脸 faces = detector(gray, 1) # 使用特征点识别模型来检测人脸中的特征 for i, face in enumerate(faces): # 获取人脸特征点 shape = predictor(img, face)
通过上面的代码,我们检测到人脸的特征点,并将它们保存在shape中。下面我们通过facerec.compute_face_descriptor()来计算特征向量,它的函数声明如下:
facerec.compute_face_descriptor(图片对象, 特征点)
具体代码如下:
face_descriptor = facerec.compute_face_descriptor(img,shape)
这样,我们就计算出了人脸特征向量。
【 2. 计算欧氏距离 】
- 欧氏距离(也称欧几里得距离)是一个常用的的距离度量,它指的是在空间中两个向量(点)之间的直线距离。
欧氏距离越小,说明两个向量越接近,也就是两个向量差异越小。 - 假设在两个向量分别为 x(x1,x2,…,xm) 和 y(y1,y2,…,ym),则这两个向量的欧氏距离的计算公式为:
( x 1 − y 1 ) 2 + ( x 2 − y 2 ) 2 + . . + ( x m − y m ) 2 ( x 1 − y 1 ) \sqrt{(x_1-y_1)^2+(x_2-y_2)^2+..+(x_m-y_m)^2}\sqrt{(x_1−y_1)} (x1−y1)2+(x2−y2)2+..+(xm−ym)2(x1−y1) - 在Python中可以通过长度为 m 的列表来表示维数为 m 的向量。
例如x为(1,2,3,4,5),那么它可以表示为x=[1,2,3,4,5]。 - 在Python中计算两个长度相同的列表的欧氏距离:
import numpy as np # 导入numpy库 x = [1,2,3,4,5] # 声明两个长度相同的列表 y = [3,4,5,2,1] x_array = np.array(x) # 将列表转换为numpy数组 y_array = np.array(y) distance = np.linalg.norm(x_array-y_array) # 计算x_array与y_array之间的欧氏距离
【 3. 识别人脸 】
1. 准备数据
2. 计算所有已知图片中人脸的特征向量
glob(正则表达式): # glob()返回匹配的文件列表,
glob()会返回匹配的文件列表,这样我们就可以获取到在known_image_path下所有以jpg结尾的的图片,如下:
import glob glob.glob(os.path.join(known_image_path, "*.jpg"))
然后我们就可以来计算所有已知图片中人脸的特征向量,代码如下所示:
known_image_path = "step1/image/known_image" # 声明descriptors,用于存放已知图片对应的人脸特征向量 descriptors = [] # 声明names,用于存放于人脸特征向量对应的名字。 names = ["TongDaWei","XiaYu","ZhangYiShan"] # 遍历known_image_path文件夹下所有以.jpg结尾的文件。 for f in glob.glob(os.path.join(known_image_path, "*.jpg")): img = dlib.load_rgb_image(f) # 1.人脸检测 dets = detector(img, 1) for k, d in enumerate(dets): # 2.关键点检测 shape = predictor(img, d) # 3.计算特征向量(也成为人脸描述符) descriptor = facerec.compute_face_descriptor(img, shape) # 转换为numpy数组 v = np.array(descriptor) descriptors.append(v)
3. 识别人脸
当欧氏距离小于某个阈值时,则可以认为他们是同一个人。那这个阈值应该设定为多少呢?
- 原理:计算待识别的图片特征向量与已知图片特征向量的欧氏距离,如果欧氏距离小于阈值,则认为是同一张图片。
- 在Dlib中,对于在LFW人脸数据集,当阈值设置为0.6时,的识别精度能达到99.38%。
- 但是,当阈值设置为0.6时,对于小孩和亚洲人的识别率不是很高。故我们要识别的图片是亚洲人时,要将阈值适当地降低,在这里我们设置为0.4。
具体代码片段如下
tolerance = 0.4 current_name = "Unknow" for i in range(len(descriptors)): #假设当前带识别的图片特征为current distance = np.linalg.norm(descriptors[i]-current) if distance<tolerance: #names用于存放于已知人脸特征向量对应的名字 current_name = names[i] break print("当前图片识别结果为:"+current_name)
【 4. 范例 】
# 0. 导入模块 import os import dlib import glob import numpy as np import cv2 # 1. 加载模型、图片 正向人脸检测器 detector = dlib.get_frontal_face_detector() 加载特征点提取模型 predictor_path = 'shape_predictor_68_face_landmarks.dat' predictor = dlib.shape_predictor(predictor_path) 加载面部识别模型 face_rec_model_path = 'dlib_face_recognition_resnet_model_v1.dat' facerec = dlib.face_recognition_model_v1(face_rec_model_path) 已知图片 known_image_path = 'know' 测试图片 test_image_path = "unknow" # 2. 声明存放数据的变量 声明descriptors,用于存放已知图片对应的人脸特征向量 descriptors = [] 声明names,用于存放于人脸特征向量对应的名字。 names = ["reba"] # 3. 开始检测 遍历known_image_path文件夹下所有以.jpg结尾的文件。 for f in glob.glob(os.path.join(known_image_path, "*.jpg")): img = dlib.load_rgb_image(f) 使用 detector 检测器来检测图像中的人脸 dets = detector(img, 1) for k, d in enumerate(dets): 获取人脸特征点 shape = predictor(img, d) 计算特征向量 face_descriptor = facerec.compute_face_descriptor(img, shape) 特征向量转换为numpy array v = np.array(face_descriptor) 把此次数据存到人脸特征向量列表里面 descriptors.append(v) # 4. 进行判断 遍历test_image_path文件夹下所有以.jpg结尾的文件。 for f in glob.glob(os.path.join(test_image_path, "*.jpg")): img = dlib.load_rgb_image(f) 使用 detector 检测器来检测图像中的人脸 dets = detector(img, 1) for k, d in enumerate(dets): 获取人脸特征点 shape = predictor(img, d) 计算特征向量 face_descriptor = facerec.compute_face_descriptor(img, shape) 将当前待判断的图片特征向量转化为 current current = np.array(face_descriptor) 计算欧式距离,识别人脸 设置阈值 tolerance = 0.1 设置该图片名字初值为:Unknow current_name = "Unknow name" 对这个存放着已知图片特征向量的列表descriptors[]遍历 for i in range(len(descriptors)): 计算欧氏距离 distance = np.linalg.norm(descriptors[i] - current) 对欧氏距离判断 if distance < tolerance: names用于存放着人脸特征向量对应的名字 current_name = names[i] break 输出对当前图片的识别结果 print("当前图片识别结果为:" + current_name)
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/134013.html