苦学Opencv的第十四天:人脸检测和人脸识别
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啦!!!!激动之余别忘记复习一下内容,明天我们将开始实战,做一个小型的人脸识别系统!!!加油吧!!!
相关文章:

苦学Opencv的第十四天:人脸检测和人脸识别
Python OpenCV入门到精通学习日记:人脸检测和人脸识别 前言 经过了十三天的不懈努力,我们终于也是来到了人脸检测和人脸识别啦!相信大家也很激动吧。接下来我们开始吧! 人脸识别是基于人的脸部特征信息进行身份识别的一种生物识…...

PyTorch学习(1)
PyTorch学习(1) CIFAR-10数据集-图像分类 数据集来源是官方提供的: torchvision.datasets.CIFAR10()共有十类物品,需要用CNN实现图像分类问题。 代码如下:(CIFAR_10_Classifier_Self_1.py) import torch import t…...

三思而后行:计算机行业的决策智慧
在计算机行业,"三思而后行"这一原则显得尤为重要。在这个快速发展、技术不断更新换代的领域,每一个决策都可能对项目的成功与否产生深远的影响。以下是一篇关于在计算机行业中三思重要性的文章。 三思而后行:计算机行业的决策智慧 …...

Linux--Socket编程UDP
前文:Socket套接字编程 UDP协议特点 无连接:UDP在发送数据之前不需要建立连接,减少了开销和发送数据之前的时延。尽最大努力交付:UDP不保证可靠交付,主机不需要维持复杂的连接状态表。面向报文:UDP对应用层…...

《javaEE篇》--单例模式详解
目录 单例模式 饿汉模式 懒汉模式 懒汉模式(优化) 指令重排序 总结 单例模式 单例模式属于一种设计模式,设计模式就好比是一种固定代码套路类似于棋谱,是由前人总结并且记录下来我们可以直接使用的代码设计思路。 单例模式就是,在有…...

Java核心 - Lambda表达式详解与应用示例
作者:逍遥Sean 简介:一个主修Java的Web网站\游戏服务器后端开发者 主页:https://blog.csdn.net/Ureliable 觉得博主文章不错的话,可以三连支持一下~ 如有疑问和建议,请私信或评论留言! 前言 Lambda表达式是…...

算法通关:006_1二分查找
二分查找 查找一个数组里面是否存在num主要代码运行结果 详细写法自动生成数组和num,利用对数器查看二分代码是否正确 查找一个数组里面是否存在num 主要代码 /*** Author: ggdpzhk* CreateTime: 2024-07-27*/ public class cg {//二分查找public static boolean …...

总结一些vue3小知识3
总结一些vue3小知识1:http://t.csdnimg.cn/C5vER 总结一些vue3小知识2:http://t.csdnimg.cn/sscid 1.限制时间选择器只能选择后面的日期 说明:disabled-date属性是一个用来判断该日期是否被禁用的函数,接受一个 Date 对象作为参…...

JAVAWeb实战(前端篇)
项目实战一 0.项目结构 1.创建vue3项目,并导入所需的依赖 npm install vue-router npm install axios npm install pinia npm install vue 2.定义路由,axios,pinia相关的对象 文件(.js) 2.1路由(.js) import {cre…...

axios请求大全
本文讲解axios封装方式以及针对各种后台接口的请求方式 axios的介绍和基础配置可以看这个文档: 起步 | Axios中文文档 | Axios中文网 axios的封装 axios封装的重点有三个,一是设置全局config,比如请求的基础路径,超时时间等,第二点是在每次…...

C# 简单的单元测试
文章目录 前言参考文档新建控制台项目新建测试项目添加引用添加测试方法测试结果(有错误)测试结果,通过正规的方法抛出异常 总结 前言 听说复杂的项目最好都要单元测试一下。我这里也试试单元测试这个功能。到时候调试起来也方便。 参考文档 C# 单元测试…...

Linux中Mysql5.7主从架构(一主多从)配置教程
🏡作者主页:点击! 🐧Linux基础知识(初学):点击! 🐧Linux高级管理防护和群集专栏:点击! 🔐Linux中firewalld防火墙:点击! ⏰️创作…...

BACnet物联网关BL103:Modbus协议转BACnet/MSTP
随着物联网技术在楼宇自动化与暖通控制系统中的迅猛发展,构建一种既经济高效又高度可靠的协议转换物联网关成为了不可或缺的核心硬件组件。在此背景下,我们钡铼特别推荐一款主流的BAS(楼宇自动化系统)与BACnet物联网关——BL103&a…...

Go 语言条件变量 Cond
1.Cond 的使用方法 Go 标准库提供 Cond 同步原语的目的是为等待/通知场景下的并发操作提供支持。Cond 通常用于等待某个条件的一组 goroutine,当条件变为 true 时,其中一个或者所有的 goroutine 会被唤醒执行。 Cond 与某个条件相关,这个条件需要一组 goroutine 协作达到。当这…...

PostgreSQL 中如何重置序列值:将自增 ID 设定为特定值开始
我是从excel中将数据导入,然后再通过sql插入数据,就报错。 需要设置自增ID开始值 1、确定序列名称: 首先,需要找到与的增字段相关的序列名称。假设表名是 my_table 和自增字段是 id,可以使用以下查询来获取序列名称…...

Unity 之 【Android Unity 共享纹理】之 Android 共享图片给 Unity 显示
Unity 之 【Android Unity 共享纹理】之 Android 共享图片给 Unity 显示 目录 Unity 之 【Android Unity 共享纹理】之 Android 共享图片给 Unity 显示 一、简单介绍 二、共享纹理 1、共享纹理的原理 2、共享纹理涉及到的关键知识点 3、什么可以实现共享 不能实现共享…...

Go语言的数据结构
数据结构 数组 支持多维数组,属于值类型,支持range遍历 例子:随机生成长度为10整数数组 package main import ("fmt""math/rand" ) // 赋值 随机获取100以内的整数 func RandomArrays() {var array [10]int //声明var…...

python_在sqlite中创建表并写入表头
python_在sqlite中创建表并写入表头 import sqlite3def write_title_to_sqlite(tableName,titleList,dataTypeGroupsList,database_path):conn sqlite3.connect(database_path)# 创建游标cursor conn.cursor()#MEMO 长文本#create_table_bodycreate_table_body "序号 …...

1.c#(winform)编程环境安装
目录 安装vs创建应用帮助查看器安装与使用( msdn) 安装vs 安装什么版本看个人心情,或者公司开发需求需要 而本栏全程使用vs2022进行开发c#,着重讲解winform桌面应用开发 使用***.net framework***开发 那先去官网安装企业版的vs…...

图中的最短环
2608. 图中的最短环 现有一个含 n 个顶点的 双向 图,每个顶点按从 0 到 n - 1 标记。图中的边由二维整数数组 edges 表示,其中 edges[i] [ui, vi] 表示顶点 ui 和 vi 之间存在一条边。每对顶点最多通过一条边连接,并且不存在与自身相连的顶…...

安装依赖 npm install idealTree:lib: sill idealTree buildDeps 卡着不动
我一直怀疑是网络问题,因为等了很久也能安装成功,就是时间比较长,直到现在完全受不了了,决定好好整治下这个问题! 1、执行命令 npm config get userconfig 查看配置文件所在位置,将其删除。 2、执行 n…...

LLMs之Llama 3.1:Llama 3.1的简介、安装和使用方法、案例应用之详细攻略
LLMs之Llama 3.1:Llama 3.1的简介、安装和使用方法、案例应用之详细攻略 导读:2024年7月23日,Meta重磅推出Llama 3.1。本篇文章主要提到了Meta推出的Llama 3.1自然语言生成模型。 背景和痛点 >> 过去开源的大型语言模型在能力和性能上一…...

如何实现一个大模型在回答问题时同时提供相关内容链接
通义生成 为了让大模型在回答问题时能够提供相关内容链接,通常采用的方法是结合检索增强生成(Retrieval-Augmented Generation, RAG)的技术。这种方法可以让大模型在生成答案的同时,从外部知识源中检索相关信息,并将这…...

<数据集>玉米地杂草识别数据集<目标检测>
数据集格式:VOCYOLO格式 图片数量:9900张 标注数量(xml文件个数):9900 标注数量(txt文件个数):9900 标注类别数:2 标注类别名称:[Maize, Weed] 序号类别名称图片数框数1Maize8439125142Weed959231048…...

vue3中动态添加form表单校验
<template><div><div v-for"(formData, index) in forms" :key"index"><u-form :model"formData" :rules"rules" ref"formRefs"><u-form-item label"用户名" prop"username"…...

Java面试八股之什么是声明式事务管理,spring怎么实现声明式事务管理?
什么是声明式事务管理,spring怎么实现声明式事务管理? 声明式事务管理是一种编程范式,它允许开发人员通过声明性的配置或注解,而不是硬编码事务处理逻辑,来指定哪些方法或类应该在其上下文中执行事务。这种方法将事务…...

springboot 缓存预热的几种方案
缓存预热是指在 Spring Boot 项目启动时,预先将数据加载到缓存系统(如 Redis)中的一种机制。 这里我给大家总结几个缓存预热的方案。 方案1:使用启动监听事件实现缓存预热 可以使用 ApplicationListener 监听 ContextRefreshed…...

谷粒商城实战笔记-62-商品服务-API-品牌管理-OSS整合测试
文章目录 一,Java中上传文件到阿里云OSS1,整合阿里云OSS2,测试上传文件 二,Java中整合阿里云OSS服务指南引言准备工作1. 注册阿里云账号2. 获取Access Key3. 添加依赖 实现OSS客户端1. 初始化OSSClient2. 创建Bucket3. 上传文件4.…...

linux c 递归锁的介绍
递归锁的递归特性确实只是对于持有锁的线程。当一个线程获取了递归锁后,它可以多次重复获取该锁,而不会导致自身阻塞或死锁。这是递归锁的重要特点,它允许同一个线程在已经持有锁的情况下,再次获取相同的锁。 然而,对…...

React好用的组件库有哪些
React好用的组件库有很多,它们各自具有不同的特点和优势,适用于不同的开发场景和需求。以下是一些受欢迎的React组件库及其特点: Material-UI(现更名为MUI) 特点:这是一个开源的React组件库,实…...