本次来学习把需要识别的人像进行数据训练,我们先看一下源代码。因为本次需要调用的功能比较多,我们可以直接复制这段代码+更改文件存储路径后看是否能正常运行。如果无法运行的,大概率是需要安装一些对应功能。
import os
import cv2
from PIL import Image
import numpy as np
def getImageAndLabels(path):
facesSamples=[]
ids=[]
imagePaths=[os.path.join(path,f) for f in os.listdir(path)]
face_detector = cv2.CascadeClassifier('M:/python/pythoninstall/Lib/site-packages/cv2/data/haarcascade_frontalface_alt2.xml')
print('数据排列:',imagePaths)
for imagePath in imagePaths:
PIL_img=Image.open(imagePath).convert('L')
img_numpy=np.array(PIL_img,'uint8')
faces = face_detector.detectMultiScale(img_numpy)
id = int(os.path.split(imagePath)[1].split('.')[0])
for x,y,w,h in faces:
ids.append(id)
facesSamples.append(img_numpy[y:y+h,x:x+w])
print('id:', id)
print('fs:', facesSamples)
return facesSamples,ids
if __name__ == '__main__':
path='M:/python/workspace/PythonProject/face/'
faces,ids=getImageAndLabels(path)
recognizer=cv2.face.LBPHFaceRecognizer_create()
recognizer.train(faces,np.array(ids))
recognizer.write('trainer/trainer.yml')
1前期准备:
(1)在代码中我们需要根据自己电脑的情况检查路径和文件夹
(2)在face文件夹里我们需要提前放图片,图片命名方式为
id.some_other_info.jpg
也就是类似
1.Jay Chou.jpeg这样,首位是数字,中间是人脸信息,最后是格式
(3)代码依旧报错,需要安装相应模块
我的报错是这样的:
Traceback (most recent call last): File "M:\python\workspace\PythonProject\090.py", line 27, in <module> recognizer=cv2.face.LBPHFaceRecognizer_create() ^^^^^^^^ AttributeError: module 'cv2' has no attribute 'face'
根据豆包的提示:这个错误 AttributeError: module 'cv2' has no attribute 'face'
表明你尝试访问 cv2
模块里的 face
属性,但该属性并不存在,这通常和 OpenCV 版本有关。可以使用在命令行执行 pip
命令来安装或更新。具体而言是:
Windows 用户,可通过按下 Win + R
组合键,输入 cmd打开。然后输入下面命令。
pip install --upgrade opencv-contrib-python
这个安装需要等待一下就能安装好~
运行完我们可以在train函数找到一个yml的文件
还可以在控制台看到有id和faces数据的输出行,这些数字代表着人脸中被数据化的特征。
2具体代码解读:
在解决了基本环境配置问题后程序应该能运行了。那我们来解读一下~这是目前我们见过最长的代码了,我们先来看一下整体结构:
- 数据准备:从指定目录中读取所有图像文件,使用 Haar 级联分类器检测图像中的人脸,并提取人脸区域和对应的标签(ID)。
- 模型训练:使用提取的人脸数据和标签,使用 LBPH(局部二值模式直方图)人脸识别器进行训练。
- 模型保存:将训练好的模型保存到指定的 YAML 文件中。
具体怎么对应的,我们来解读代码。以下内容比较长,且大量涉及未见过的代码,可以快速浏览。看完整段代码解读部分之后回头再看:
import os
:导入 os
模块,该模块提供了与操作系统进行交互的功能,例如文件和目录操作。
即适用于所有支持 Python 的操作系统,包括 Windows、Linux、macOS 等。
from PIL import Image
:Python Imaging Library(Pillow)导入 Image
类,用于处理图像文件。
补充:在这里from PIL import Image和
import cv2都是图像处理的库。区别在于PIL
(Pillow)更早,主要用于基础的图像操作。而 OpenCV适用于更复杂的视觉任务。
PIL
(Pillow)支持常见的图像读取、保存、裁剪、缩放、旋转、颜色模式转换等操作。/支持多种图像格式,如 JPEG、PNG、BMP 等,方便在不同格式之间进行转换。- OpenCV支持图像滤波、边缘检测、特征提取(如 SIFT、SURF、ORB 等)、目标检测(如 Haar 级联分类器、HOG + SVM)、图像分割、运动分析等操作。例如:用 Haar 级联分类器进行人脸检测。/支持视频的读取、写入和处理,可用于视频分析、视频监控等领域。
def getImageAndLabels(path):
facesSamples=[]
ids=[]
def getImageAndLabels(path):
:定义名为getImageAndLabels
的函数(自定义的函数),接受一个参数path
,表示图像的路径。facesSamples=[]
:初始化一个空列表facesSamples
,用于存储从图像中提取的人脸样本。ids=[]
:初始化一个空列表ids
,用于存储每个人脸样本对应的标签(ID)。
imagePaths=[os.path.join(path,f) for f in os.listdir(path)]
os.listdir(path)
:返回指定目录path
下的所有文件和文件夹的名称列表。os.path.join(path,f)
:将目录路径path
和文件名f
组合成一个完整的文件路径。- 创建了一个包含指定目录下所有文件完整路径的列表
imagePaths
。
print('数据排列:',imagePaths)
- 打印出包含所有图像文件路径的列表
imagePaths
,用于调试和查看数据排列情况。
for imagePath in imagePaths:
PIL_img=Image.open(imagePath).convert('L')
for imagePath in imagePaths:
:遍历imagePaths
列表中的每个图像文件路径。Image.open(imagePath)
:使用Pillow
库的Image
类打开指定路径的图像文件。.convert('L')
:将打开的图像转换为灰度图像,因为人脸检测和识别通常使用灰度图像。
convert()
是Pillow
库中Image
对象的一个方法,用于将图像从一种模式转换为另一种模式。
'1'
:转换为 1 位像素的二值图像,即每个像素只能是 0(黑色)或 255(白色)。
'L'
:转换为 8 位像素的灰度图像。
'RGB'
:转换为 3 通道的真彩色图像。
'RGBA'
:在 RGB
的基础上增加了一个透明度通道(Alpha)。
'CMYK'
:转换为四通道的印刷色彩模式。
img_numpy=np.array(PIL_img,'uint8')
np.array(PIL_img, 'uint8')
:将Pillow
图像对象转换为numpy
数组,数据类型为uint8
(无符号 8 位整数),以便后续使用 OpenCV 进行处理。
faces = face_detector.detectMultiScale(img_numpy)
-
face_detector.detectMultiScale(img_numpy)
:使用之前创建的级联分类器对象face_detector
对灰度图像img_numpy
进行人脸检测。 - 该函数返回一个包含检测到的人脸的矩形框坐标的列表,每个矩形框由
(x, y, w, h)
表示,其中(x, y)
是矩形框的左上角坐标,w
和h
分别是矩形框的宽度和高度。
id = int(os.path.split(imagePath)[1].split('.')[0])
os.path.split(imagePath)[1]
:从完整的图像文件路径中提取文件名。.split('.')[0]
:将文件名按.
分割,并取第一个部分。int(...)
:将提取的文件名的第一部分转换为整数,作为该图像对应的标签(ID)。
for x,y,w,h in faces:
ids.append(id)
facesSamples.append(img_numpy[y:y+h,x:x+w])
for x,y,w,h in faces:
:遍历检测到的所有人脸矩形框。ids.append(id)
:将当前图像对应的标签(ID)添加到ids
列表中。facesSamples.append(img_numpy[y:y+h,x:x+w])
:从灰度图像中提取出人脸区域(根据矩形框的坐标),并将其添加到facesSamples
列表中。
print('id:', id)
print('fs:', facesSamples)
return facesSamples,ids
- 打印当前图像对应的标签(ID),用于调试和查看处理进度。
- 打印存储所有人脸样本的列表
facesSamples
,用于调试。 return facesSamples,ids
:返回包含所有人脸样本的列表facesSamples
和对应的标签列表ids
。
if __name__ == '__main__':
path='M:/python/workspace/PythonProject/face/'
if __name__ == '__main__':
:这是主函数,也就是代码主要的架构。path='M:/python/workspace/PythonProject/face/'
:指定包含人脸图像的目录路径。
faces,ids=getImageAndLabels(path)
- 调用
getImageAndLabels
函数,传入图像目录路径path
,并将返回的人脸样本列表和标签列表分别赋值给faces
和ids
。
recognizer=cv2.face.LBPHFaceRecognizer_create()
recognizer.train(faces,np.array(ids))
recognizer.write('trainer/trainer.yml')
-
cv2.face.LBPHFaceRecognizer_create()
:创建一个 LBPH(局部二值模式直方图)人脸识别器对象,用于训练和识别人脸。 -
recognizer.train(faces, np.array(ids))
:使用提取的人脸样本列表faces
和对应的标签列表ids
对人脸识别器进行训练。 -
recognizer.write('trainer/trainer.yml')
:将训练好的人脸识别模型保存到指定的 YAML 文件trainer/trainer.yml
中,以便后续使用。
3整段代码解读:
import numpy as np
#导入os模块,和操作系统交互
import os
#导入图像处理模块(复杂智能)
import cv2
#导入图像处理模块(简单快速)
from PIL import Image
#自定义子函数
def getImageAndLabels(path):
#建列表存人脸信息和人脸标签
facesSamples=[]
ids=[]
#生成图像完整路径
imagePaths=[os.path.join(path,f) for f in os.listdir(path)]
#调用分类器
face_detector = cv2.CascadeClassifier('M:/python/pythoninstall/Lib/site-packages/cv2/data/haarcascade_frontalface_alt2.xml')
#控制台输出人脸数据信息
print('数据排列:',imagePaths)
#循环打开imagePaths中路径
for imagePath in imagePaths:
#用Pillow 库的 Image 类将图片转换为灰度图
PIL_img=Image.open(imagePath).convert('L')
#将图像转换为数组
img_numpy=np.array(PIL_img,'uint8')
#用分类器对灰度人脸进行检测
faces = face_detector.detectMultiScale(img_numpy)
#从图像完整路径中提取文件名,将文件名中的第一部分转化为图像标签ID
id = int(os.path.split(imagePath)[1].split('.')[0])
#循环检测所有人脸矩形框,将ID添加到facesSamples列表中,根据矩形框坐标提取人脸区域
for x,y,w,h in faces:
ids.append(id)
facesSamples.append(img_numpy[y:y+h,x:x+w])
#打印图像标签ID
print('id:', id)
打印facesSamples列表
print('fs:', facesSamples)
#返回facesSamples列表和ID
return facesSamples,ids
#主函数
if __name__ == '__main__':
#指定包含人脸图像的目录路径
path='M:/python/workspace/PythonProject/face/'
#调用自定义的函数,传入图像路径 path,获取faces和ids值。
faces,ids=getImageAndLabels(path)
#用 LBPH(局部二值模式直方图)人脸识别器识别人脸。
recognizer=cv2.face.LBPHFaceRecognizer_create()
#用提取的faces和ids对人脸识别器进行训练。
recognizer.train(faces,np.array(ids))
#将训练好的人脸识别模型保存到指定的yml文件中
recognizer.write('trainer/trainer.yml')
4代码结构(重要理解!):
我们再次理解本段代码的结构,把def自定义函数折叠起来。整段代码在这里用到了先放过程中第二部会用到的人脸识别数据准备函数,再放整个内容的顺序。标记为主函数才对应了我们图像识别的三个流程,而子函数因为内容比较多,所以单独列出来,且因为需要提前处理顺序才放到主体函数之前。
下图将代码的结构进行了表达:
大家可以尝试运行下试试,下次我们来尝试人脸识别~