Python OpenCV入门到精通学习日记:人脸检测和人脸识别
前言
经过了十三天的不懈努力,我们终于也是来到了人脸检测和人脸识别啦!相信大家也很激动吧。接下来我们开始吧!
人脸识别是基于人的脸部特征信息进行身份识别的一种生物识别技术,也是计算机视觉重点发展的技术。机器学习算法诞生之后,计算机可以通过摄像头等输入设备自动分析图像中包含的内容信息,随着技术的不断发展,现在已经有了多种人脸识别的算法。接下来我们将学习OpenCV自带的多种图像跟踪技术和3种人脸识别技术的用法。
人脸检测和人脸识别
- Python OpenCV入门到精通学习日记:人脸检测和人脸识别
- 前言
- 1 人脸检测
- 1.1 级联分类器
- 1.2 方法
- 1.3 分析人脸位置
- 2 检测其他内容
- 2.1 眼睛检测
- 2.2 猫脸检测
- 2.3 行人检测
- 2.4 车牌检测
- 3 人脸识别
- 3.1 Eigenfaces人脸识别器
- 3.2 Fisherfaces人脸识别器
- 3.3 Local Binary Pattern Histogram人脸识别器
- 小结
1 人脸检测
人脸检测是让计算机在一幅画面中找出人脸的位置。毕竟计算机还达不到人类的智能水平,所以计算机在检测人脸的过程中实际上是在做“分类”操作,例如,计算机发现图像中有一些像素组成了眼睛的特征,那这些像素就有可能是“眼睛”;如果“眼睛”旁边还有“鼻子”和“另一只眼睛”的特征,那这3个元素所在的区域就很有可能是人脸区域;但如果“眼睛”旁边缺少必要的“鼻子”和“另一只眼睛”,那就认为这些像素并没有组成人脸,它们不是人脸图像的一部分。
检测人脸的算法比较复杂,但OpenCV已经将这些算法封装好,我们将学习如何利用OpenCV自带的功能进行人脸检测。
1.1 级联分类器
将一系列简单的分类器按照一定顺序级联到一起就构成了级联分类器,使用级联分类器的程序可以通过一系列简单的判断来对样本进行识别。例如,依次满足“有6条腿”“有翅膀”“有头、胸、腹”这3个条件的样本就可以被初步判断为昆虫,但如果任何一个条件不满足,则不会被认为是昆虫。
OpenCV提供了一些已经训练好的级联分类器,这些级联分类器以XML文件的方式保存在指定路径中。
路径如下:
...\Python\Lib\site-packages\cv2\data\
如果没有错,那你会在data文件夹里面看见这些:
不同版本的OpenCV自带的级联分类器XML文件可能会有差别,data文件夹中缺少的XML文件可以到OpenCV的源码托管平台下载,链接: 源码托管平台github,github需要翻墙,如果没有条件,steam++也有github免费加速功能,凑合一下吧,链接: steam++。
每一个XML文件都对应一种级联分类器,但有些级联分类器的功能是类似的,部分XML文件对应的功能表格如下:
级联分类器XML文件名 | 检测的内容 |
---|---|
haarcascade_eye.xml | 眼睛检测 |
haarcascade_eye_tree_eyeglasses.xml | 眼镜检测 |
haarcascade_frontalcatface.xml | 前面猫脸检测 |
haarcascade_frontalface_default.xml | 前面人脸检测 |
haarcascade_fullbody.xml | 身形检测 |
haarcascade_lefteye_2splits.xml | 左眼检测 |
haarcascade_lowerbody.xml | 下半身检测 |
haarcascade_profileface.xml | 侧面人脸检测 |
haarcascade_righteye_2splits.xml | 右眼检测 |
haarcascade_russianplatenumber.xml | 车牌检测 |
haarcascade_smile.xml | 笑容检测 |
haarcascade_upperbody.xml | 上半身检测 |
想要实现哪种图像检测,就要在程序启动时加载对应的级联分类器。接下来我们学习如何加载并使用这些XML文件。
1.2 方法
OpenCV实现人脸检测需要做两步操作:加载级联分类器和使用分类器识别图像。这两步操作都有对应的方法。首先是加载级联分类器,OpenCV通过CascadeClassifier()
方法创建了分类器对象。
<CascadeClassifier object> =cv2.CascadeClassifier(filename)
参数说明:filename:级联分类器的XML文件名。
返回值说明:object:分类器对象。
然后我们使用已经创建好的分类器对图像进行识别,这个过程需要调用分类器对象的detectMultiScale()
方法。
objects = cascade.detectMultiScale(image, scaleFactor,minNeighbors, flags, minSize, maxSize)
对象说明:cascade:已有的分类器对象。
参数说明:image:待分析的图像。scaleFactor:可选参数,扫描图像时的缩放比例。minNeighbors:可选参数,每个候选区域至少保留多少个检测结果才可以判定为人脸。该值越大,分析的误差越小。flags:可选参数,旧版本OpenCV的参数,建议使用默认值。minSize:可选参数,最小的目标尺寸。maxSize:可选参数,最大的目标尺寸。返回值说明:objects:捕捉到的目标区域数组,数组中每一个元素都是一个目标区域,每一个目标区域都包含4个值,分别是:左上角点横坐标、左上角点纵坐标、区域宽、区域高。object的格式为:[[244 203 111 111] [432 81 133133]]。
1.3 分析人脸位置
haarcascade_frontalface_default.xml是检测正面人脸的级联分类器文件,加载该文件就可以创建出追踪正面人脸的分类器,调用分类器对象的detectMultiScale()
方法,得到的objects结果就是分析得出的人脸区域的坐标、宽和高。
import cv2img = cv2.imread("model.png") # 读取人脸图像
# 加载识别人脸的级联分类器
faceCascade = cv2.CascadeClassifier("cascades/haarcascade_frontalface_default.xml")
faces = faceCascade.detectMultiScale(img, 1.3) # 识别出所有人脸
for (x, y, w, h) in faces: # 遍历所有人脸的区域cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 5) # 在图像中人脸的位置绘制方框
cv2.imshow("img", img) # 显示最终处理的效果
cv2.waitKey() # 按下任何键盘按键后
cv2.destroyAllWindows() # 释放所有窗体
🌟faceCascade = cv2.CascadeClassifier("cascades/haarcascade_frontalface_default.xml")
中cascades/haarcascade_frontalface_default.xml
是haarcascade_frontalface_default.xml文件的路径,你这个文件在哪,你就设置在哪。
运行结果如下:
看着这个代码,我在想,那么我能不能把昨天学习的视频处理放在这里使用呢?说办就办。我们只需要将代码进行修改就可以了:
import cv2capture = cv2.VideoCapture(0) # 打开笔记本内置摄像头
while (capture.isOpened()): # 笔记本内置摄像头被打开后retval, img = capture.read() # 从摄像头中实时读取视频faceCascade = cv2.CascadeClassifier("cascades/haarcascade_frontalface_default.xml")faces = faceCascade.detectMultiScale(img, 1.3) # 识别出所有人脸for (x, y, w, h) in faces: # 遍历所有人脸的区域cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 5) # 在图像中人脸的位置绘制方框cv2.imshow("Video", img) # 在窗口中显示读取到的视频key = cv2.waitKey(1) # 窗口的图像刷新时间为1毫秒if key == 32: # 如果按下空格键break
capture.release() # 关闭笔记本内置摄像头
cv2.destroyAllWindows() # 销毁显示摄像头视频的窗口
很好,成功了!!!看成果:
OpenCV还可以实现为人脸添加戴墨镜的的功能,需要执行以下3个步骤:
- 编写一个覆盖图片的overlay_img()方法。因为素材中可能包含透明像素,这些透明像素不可以遮挡人脸,所以在覆盖背景图像时要做判断,忽略所有透明像素。判断一个像素是否为透明像素,只需将图像从3通道转为4通道,判断第4通道的alpha值,alpha值为1表示完全不透明,0表示完全透明。
- 创建人脸识别级联分类器,分析图像中人脸的区域。
- 把墨镜图像按照人脸宽度进行缩放,并覆盖到人脸区域约1/3的位置。
接下来可以开始编写代码了:
import cv2# 覆盖图像
def overlay_img(img, img_over, img_over_x, img_over_y):"""覆盖图像:param img: 背景图像:param img_over: 覆盖的图像:param img_over_x: 覆盖图像在背景图像上的横坐标:param img_over_y: 覆盖图像在背景图像上的纵坐标:return: 两张图像合并之后的图像"""img_h, img_w, img_p = img.shape # 背景图像宽、高、通道数img_over_h, img_over_w, img_over_c = img_over.shape # 覆盖图像高、宽、通道数if img_over_c == 3: # 通道数等于3img_over = cv2.cvtColor(img_over, cv2.COLOR_BGR2BGRA) # 转换成4通道图像for w in range(0, img_over_w): # 遍历列for h in range(0, img_over_h): # 遍历行if img_over[h, w, 3] != 0: # 如果不是全透明的像素for c in range(0, 3): # 遍历三个通道x = img_over_x + w # 覆盖像素的横坐标y = img_over_y + h # 覆盖像素的纵坐标if x >= img_w or y >= img_h: # 如果坐标超出最大宽高break # 不做操作img[y, x, c] = img_over[h, w, c] # 覆盖像素return img # 完成覆盖的图像face_img = cv2.imread("peoples.png") # 读取人脸图像
glass_img = cv2.imread("glass.png", cv2.IMREAD_UNCHANGED) # 读取眼镜图像,保留图像类型
height, width, channel = glass_img.shape # 获取眼镜图像高、宽、通道数
# 加载级联分类器
face_cascade = cv2.CascadeClassifier("./cascades/haarcascade_frontalface_default.xml")
garyframe = cv2.cvtColor(face_img, cv2.COLOR_BGR2GRAY) # 转为黑白图像
faces = face_cascade.detectMultiScale(garyframe, 1.3, 5) # 识别人脸
for (x, y, w, h) in faces: # 遍历所有人脸的区域gw = w # 眼镜缩放之后的宽度gh = int(height * w / width) # 眼镜缩放之后的高度度glass_img = cv2.resize(glass_img, (gw, gh)) # 按照人脸大小缩放眼镜overlay_img(face_img, glass_img, x, y + int(h * 1 / 3)) # 将眼镜绘制到人脸上
cv2.imshow("screen", face_img) # 显示最终处理的效果
cv2.waitKey() # 按下任何键盘按键后
cv2.destroyAllWindows() # 释放所有窗体
运行如下:
那么如何在视频中实现呢?让我们试试看:
import cv2# 覆盖图像
def overlay_img(img, img_over, img_over_x, img_over_y):"""覆盖图像:param img: 背景图像:param img_over: 覆盖的图像:param img_over_x: 覆盖图像在背景图像上的横坐标:param img_over_y: 覆盖图像在背景图像上的纵坐标:return: 两张图像合并之后的图像"""img_h, img_w, img_p = img.shape # 背景图像宽、高、通道数img_over_h, img_over_w, img_over_c = img_over.shape # 覆盖图像高、宽、通道数if img_over_c == 3: # 通道数等于3img_over = cv2.cvtColor(img_over, cv2.COLOR_BGR2BGRA) # 转换成4通道图像for w in range(0, img_over_w): # 遍历列for h in range(0, img_over_h): # 遍历行if img_over[h, w, 3] != 0: # 如果不是全透明的像素for c in range(0, 3): # 遍历三个通道x = img_over_x + w # 覆盖像素的横坐标y = img_over_y + h # 覆盖像素的纵坐标if x >= img_w or y >= img_h: # 如果坐标超出最大宽高break # 不做操作img[y, x, c] = img_over[h, w, c] # 覆盖像素return img # 完成覆盖的图像capture = cv2.VideoCapture(0)
while (capture.isOpened()):retval, face_img = capture.read()glass_img = cv2.imread("glass.png", cv2.IMREAD_UNCHANGED) # 读取眼镜图像,保留图像类型height, width, channel = glass_img.shape # 获取眼镜图像高、宽、通道数# 加载级联分类器face_cascade = cv2.CascadeClassifier("./cascades/haarcascade_frontalface_default.xml")garyframe = cv2.cvtColor(face_img, cv2.COLOR_BGR2GRAY) # 转为黑白图像faces = face_cascade.detectMultiScale(garyframe, 1.3, 5) # 识别人脸for (x, y, w, h) in faces: # 遍历所有人脸的区域gw = w # 眼镜缩放之后的宽度gh = int(height * w / width) # 眼镜缩放之后的高度度glass_img = cv2.resize(glass_img, (gw, gh)) # 按照人脸大小缩放眼镜overlay_img(face_img, glass_img, x, y + int(h * 1 / 3)) # 将眼镜绘制到人脸上cv2.imshow("screen", face_img) # 显示最终处理的效果key = cv2.waitKey(1)if key == 32:break
capture.release()
cv2.destroyAllWindows() # 释放所有窗体
正常运行但是会有报错:
libpng warning: iCCP: known incorrect sRGB profile
libpng warning: iCCP: known incorrect sRGB profile
指的是 PNG 图像文件中包含了一个已知不正确的 sRGB 色彩配置文件。这个警告通常不会影响图像的显示或处理,但它表明图像可能在不同的环境或软件中打开时颜色表现不一致。关于这个⚠️警告大家有什么见解麻烦在评论区讲讲哦~
2 检测其他内容
OpenCV提供的级联分类器除了可以识别人脸以外,还可以识别一些其他具有明显特征的物体,如眼睛、行人等。我来学习几个OpenCV自带的级联分类器的用法。
2.1 眼睛检测
haarcascade_eye.xml是检测眼睛的级联分类器文件,加载该文件就可以追踪眼睛的分类器。
这是一个梨子→[🍐]:在图像的眼睛位置绘制红框。
import cv2img = cv2.imread("img.png") # 读取人脸图像
# 加载识别眼睛的级联分类器
eyeCascade = cv2.CascadeClassifier("cascades\\haarcascade_eye.xml")
eyes = eyeCascade.detectMultiScale(img, 1.15) # 识别出所有眼睛
for (x, y, w, h) in eyes: # 遍历所有眼睛的区域cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 4) # 在图像中眼睛的位置绘制方框
cv2.imshow("img", img) # 显示最终处理的效果
cv2.waitKey() # 按下任何键盘按键后
cv2.destroyAllWindows() # 释放所有窗体
运行结果如下:
2.2 猫脸检测
OpenCV还提供了2个训练好的检测猫脸的级联分类器,分别是haarcascade_frontalcatface.xml 和
haarcascade_frontalcatface_extended.xml,前者的判断标准比较高,较为精确,但可能有些猫脸识别不出来;后者的判断标准比较低,只要类似猫脸就会被认为是猫脸。使用猫脸分类器不仅可以判断猫脸的位置,还可以识别图像中有几只猫。
这是一个梨子→[🍐]:在图像里找到猫脸的位置。
import cv2
img = cv2.imread("img.png") # 读取猫脸图像
# 加载识别猫脸的级联分类器
catFaceCascade = cv2.CascadeClassifier("cascades\\haarcascade_frontalcatface.xml")
catFace = catFaceCascade.detectMultiScale(img, 1.15, 4) # 识别出所有猫脸
for (x, y, w, h) in catFace: # 遍历所有猫脸的区域cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 5)# 在图像中猫脸的位置绘制方框
cv2.imshow("Where is your cat ?", img) # 显示最终处理的效果
cv2.waitKey() # 按下任何键盘按键后
cv2.destroyAllWindows() # 释放所有窗体
运行结果如下:
2.3 行人检测
haarcascade_fullbody.xml是检测人体(正面直立全身或背面直立全身)的级联分类器文件,加载该文件就可以追踪人体的分类器。
这是一个梨子→[🍐]:在图像中找到行人的位置。
import cv2
img = cv2.imread("img.png") # 读取图像
# 加载识别类人体的级联分类器
bodyCascade = cv2.CascadeClassifier("cascades\\haarcascade_fullbody.xml")
bodys = bodyCascade.detectMultiScale(img, 1.15, 4) # 识别出所有人体
for (x, y, w, h) in bodys: # 遍历所有人体区域cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 1)# 在图像中人体的位置绘制方框
cv2.imshow("img", img) # 显示最终处理的效果
cv2.waitKey() # 按下任何键盘按键后
cv2.destroyAllWindows() # 释放所有窗体
运行结果如下:
2.4 车牌检测
haarcascade_russian_plate_number.xml是检测汽车车牌的级联分类器文件,加载该文件就可以追踪图像中的车牌。
这是一个梨子→[🍐]:标记图像中车牌的位置。
import cv2img = cv2.imread("img.png") # 读取车的图像
# 加载识别车牌的级联分类器
plateCascade = cv2.CascadeClassifier("cascades\\haarcascade_russian_plate_number.xml")
plates = plateCascade.detectMultiScale(img, 1.15, 4) # 识别出所有车牌
for (x, y, w, h) in plates: # 遍历所有车牌区域cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2) # 在图像中车牌的位置绘制方框
cv2.imshow("img", img) # 显示最终处理的效果
cv2.waitKey() # 按下任何键盘按键后
cv2.destroyAllWindows() # 释放所有窗体
运行结果如下:
3 人脸识别
OpenCV提供了3种人脸识别方法 ,分别是 Eigenfaces 、Fisherfaces和LBPH。这3种方法都是通过对比样本的特征最终实现人脸识别。因为这3种算法提取特征的方式不一样,侧重点不同,所以不能分出孰优孰劣,只能说每种方法都有各自的识别风格。OpenCV为每一种人脸识别方法都提供了创建识别器、训练识别器和识别3种方法,这3种方法的语法非常相似。那么开始学吧!!!
3.1 Eigenfaces人脸识别器
Eigenfaces也叫作“特征脸”。Eigenfaces通过==PCA(主成分分析)==方法将人脸数据转换到另外一个空间维度做相似性计算。在计算过程中,算法可以忽略一些无关紧要的数据,仅识别一些具有代表性的特征数据,最后根据这些特征识别人脸。
开发者需要通过以下方法完成人脸识别操作:
- 通过
cv2.face.EigenFaceRecognizer_create()
方法创建Eigenfaces人脸识别器。
recognizer =cv2.face.EigenFaceRecognizer_create(num_components,threshold)参数说明:num_components:可选参数,PCA方法中保留的分量个数,建议使用默认值。threshold:可选参数,人脸识别时使用的阈值,建议使用默认值。
返回值说明:recognizer:创建的Eigenfaces人脸识别器对象。
- 创建识别器对象后,需要通过对象的
train()
方法训练识别器。建议每个人都给出2幅以上的人脸图像作为训练样本。
recognizer.train(src, labels)对象说明:recognizer:已有的Eigenfaces人脸识别器对象。
参数说明:src:用来训练的人脸图像样本列表,格式为list。样本图像必须宽、高一致。labels:样本对应的标签,格式为数组,元素类型为整数。数组长度必须与样本列表长度相同。样本与标签按照插入顺序一一对应
- 训练识别器后可以通过识别器的
predict()
方法识别人脸,该方法对比样本的特征,给出最相近的结果和评分。
label, confidence = recognizer.predict(src)对象说明:recognizer:已有的Eigenfaces人脸识别器对象。
参数说明:src:需要识别的人脸图像,该图像宽、高必须与样本一致。
返回值说明:label:与样本匹配程度最高的标签值。confidence:匹配程度最高的信用度评分。评分小于5000匹配程度较高,0分表示2幅图像完全一样。
这是一个梨子→[🍐]:使用Eigenfaces识别人脸,首先我们以两个人的照片作为训练样本,这里选用杨幂和北川景子(日本女演员,因为网上说她和杨幂长得很像,所以选她)。
import cv2
import numpy as npphotos = list() # 样本图像列表
lables = list() # 标签列表
target_size = (200, 200) # 设置统一的图像尺寸photos.append(cv2.resize(cv2.imread("face\\bei_1.png", 0),target_size)) # 记录第1张人脸图像
lables.append(0) # 第1张图像对应的标签
photos.append(cv2.resize(cv2.imread("face\\bei_2.png", 0),target_size)) # 记录第2张人脸图像
lables.append(0) # 第2张图像对应的标签
photos.append(cv2.resize(cv2.imread("face\\bei_3.png", 0),target_size)) # 记录第3张人脸图像
lables.append(0) # 第3张图像对应的标签photos.append(cv2.resize(cv2.imread("face\\yangmi_1.png", 0),target_size)) # 记录第4张人脸图像
lables.append(1) # 第4张图像对应的标签
photos.append(cv2.resize(cv2.imread("face\\yangmi_2.png", 0),target_size)) # 记录第5张人脸图像
lables.append(1) # 第5张图像对应的标签
photos.append(cv2.resize(cv2.imread("face\\yangmi_3.png", 0),target_size)) # 记录第6张人脸图像
lables.append(1) # 第6张图像对应的标签names = {"0": "bei", "1": "yangmi"} # 标签对应的名称字典recognizer = cv2.face.EigenFaceRecognizer_create() # 创建特征脸识别器
recognizer.train(photos, np.array(lables)) # 识别器开始训练i = cv2.imread("face\\yangmi_test.png", 0) # 待识别的人脸图像
i = cv2.resize(i,target_size)
label, confidence = recognizer.predict(i) # 识别器开始分析人脸图像
print("confidence = " + str(confidence)) # 打印评分
print(names[str(label)]) # 数组字典里标签对应的名字
cv2.waitKey() # 按下任何键盘按键后
cv2.destroyAllWindows() # 释放所有窗体
运行结果如下:
我的测试图也的确是杨幂,就是这个匹配程度很低,另外这是文件目录:
🌟因为我的图片都是网上随便找的,这可能是导致匹配度不高的原因,大家可以用家里人的照片试试。
❗️❗️❗️这里要注意:训练的图像和被检测的图像的尺寸相同,识别器要求所有训练图像具有相同的尺寸,如果尺寸不同,就需要在训练之前将它们调整为统一的尺寸。后面的Fisherfaces人脸识别器也是一样的。
3.2 Fisherfaces人脸识别器
Fisherfaces 是由 Ronald Fisher最早提出的,这也是Fisherfaces名字的由来。Fisherfaces通过LDA(线性判别分析技术)方法将人脸数据转换到另外一个空间维度做投影计算,最后根据不同人脸数据的投影距离判断其相似度。
开发者需要通过以下方法完成人脸识别操作。
- 通过
cv2.face.FisherFaceRecognizer_create()
方法创建Fisherfaces人脸识别器。
face.FisherFaceRecognizer_create(num_components,threshold)参数说明:num_components:可选参数,通过Fisherface方法进行判断分析时保留的分量个数,建议使用默认值。threshold:可选参数,人脸识别时使用的阈值,建议使用默认值。
返回值说明:recognizer:创建的Fisherfaces人脸识别器对象。
- 创建识别器对象后,需通过对象的
train()
方法训练识别器。建议每个人都给出2幅以上的人脸图像作为训练样本。 - 训练识别器后可以通过识别器的
predict()
方法识别人脸,该方法对比样本的特征,给出最相近的结果和评分。这两步和上一个一样,就不赘述了。
那我们继续我们的🍐吧!
import cv2
import numpy as npphotos = list() # 样本图像列表
lables = list() # 标签列表
target_size = (200, 200) # 设置统一的图像尺寸photos.append(cv2.resize(cv2.imread("face\\bei_1.png", 0),target_size)) # 记录第1张人脸图像
lables.append(0) # 第1张图像对应的标签
photos.append(cv2.resize(cv2.imread("face\\bei_2.png", 0),target_size)) # 记录第2张人脸图像
lables.append(0) # 第2张图像对应的标签
photos.append(cv2.resize(cv2.imread("face\\bei_3.png", 0),target_size)) # 记录第3张人脸图像
lables.append(0) # 第3张图像对应的标签photos.append(cv2.resize(cv2.imread("face\\yangmi_1.png", 0),target_size)) # 记录第4张人脸图像
lables.append(1) # 第4张图像对应的标签
photos.append(cv2.resize(cv2.imread("face\\yangmi_2.png", 0),target_size)) # 记录第5张人脸图像
lables.append(1) # 第5张图像对应的标签
photos.append(cv2.resize(cv2.imread("face\\yangmi_3.png", 0),target_size)) # 记录第6张人脸图像
lables.append(1) # 第6张图像对应的标签names = {"0": "bei", "1": "yangmi"} # 标签对应的名称字典recognizer = cv2.face.FisherFaceRecognizer_create() # 创建特征脸识别器
recognizer.train(photos, np.array(lables)) # 识别器开始训练i = cv2.imread("face\\yangmi_test.png", 0) # 待识别的人脸图像
i = cv2.resize(i,target_size)
label, confidence = recognizer.predict(i) # 识别器开始分析人脸图像
print("confidence = " + str(confidence)) # 打印评分
print(names[str(label)]) # 数组字典里标签对应的名字
cv2.waitKey() # 按下任何键盘按键后
cv2.destroyAllWindows() # 释放所有窗体
运行结果如下:
🌟同样的训练内容和测试内容,Fisherfaces人脸识别器似乎表现更好。
3.3 Local Binary Pattern Histogram人脸识别器
Local Binary Pattern Histogram简称LBPH,即局部二进制模式直方图,这是一种基于局部二进制模式算法,这种算法善于捕获局部纹理特征。
开发者需要通过以下方法来完成人脸识别操作。
- 通过
cv2.face. LBPHFaceRecognizer_create()
方法创建LBPH人脸识别器。
recognizer = cv2.face.LBPHFaceRecognizer_create(radius,neighbors, grid_x, grid_y, threshold)参数说明:radius:可选参数,圆形局部二进制模式的半径,建议使用默认值。neighbors:可选参数,圆形局部二进制模式的采样点数目,建议使用默认值。
返回值说明:grid_x:可选参数,水平方向上的单元格数,建议使用默认值。grid_y:可选参数,垂直方向上的单元格数,建议使用默认值。threshold:可选参数,人脸识别时使用的阈值,建议使用默认值。
后面两步和上面一样的啦,就不赘述了,但是要注意,这里的匹配度只要小于50就算匹配度较高了。
直接给大家最喜欢的🍐:
import cv2
import numpy as npphotos = list() # 样本图像列表
lables = list() # 标签列表
target_size = (200, 200) # 设置统一的图像尺寸photos.append(cv2.resize(cv2.imread("face\\bei_1.png", 0),target_size)) # 记录第1张人脸图像
lables.append(0) # 第1张图像对应的标签
photos.append(cv2.resize(cv2.imread("face\\bei_2.png", 0),target_size)) # 记录第2张人脸图像
lables.append(0) # 第2张图像对应的标签
photos.append(cv2.resize(cv2.imread("face\\bei_3.png", 0),target_size)) # 记录第3张人脸图像
lables.append(0) # 第3张图像对应的标签photos.append(cv2.resize(cv2.imread("face\\yangmi_1.png", 0),target_size)) # 记录第4张人脸图像
lables.append(1) # 第4张图像对应的标签
photos.append(cv2.resize(cv2.imread("face\\yangmi_2.png", 0),target_size)) # 记录第5张人脸图像
lables.append(1) # 第5张图像对应的标签
photos.append(cv2.resize(cv2.imread("face\\yangmi_3.png", 0),target_size)) # 记录第6张人脸图像
lables.append(1) # 第6张图像对应的标签names = {"0": "bei", "1": "yangmi"} # 标签对应的名称字典recognizer = cv2.face.LBPHFaceRecognizer_create() # 创建特征脸识别器
recognizer.train(photos, np.array(lables)) # 识别器开始训练i = cv2.imread("face\\yangmi_test.png", 0) # 待识别的人脸图像
i = cv2.resize(i,target_size)
label, confidence = recognizer.predict(i) # 识别器开始分析人脸图像
print("confidence = " + str(confidence)) # 打印评分
print(names[str(label)]) # 数组字典里标签对应的名字
cv2.waitKey() # 按下任何键盘按键后
cv2.destroyAllWindows() # 释放所有窗体
运行结果如下:
🌟根据结果我们可以发现:识别器可以识别出杨幂,但是匹配度依旧不高,可能还是图像质量不好和数量不多的原因导致的。
小结
人脸检测和人脸识别是相辅相成的,检测到了人脸才可以识别人脸。三种人脸识别器也是非常重要,我们需要熟练掌握实现方法和原理!!!
大家如果听到了这里,那么恭喜,你已经成功入门opencv啦!!!!激动之余别忘记复习一下内容,明天我们将开始实战,做一个小型的人脸识别系统!!!加油吧!!!