人脸识别 Python 代码:使用 PCA 降维和 OpenCV 实现
以下是使用 Python 和 OpenCV 库进行人脸识别的代码。该代码使用 PCA 进行特征提取,并利用 Haar 级联分类器进行人脸检测,并通过欧氏距离进行人脸匹配。
import cv2
import os
import numpy as np
from sklearn.decomposition import PCA
def detect_face(img, face_cascade): #返回脸的图像和数值信息
#将测试图像转换为灰度图像,因为opencv人脸检测器需要灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
#检测多尺度图像,返回值是一张脸部区域信息的列表(x,y,宽,高)(输入图像,每次图像尺寸减小的比例,至少检测次数,目标的最小尺寸)
faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30), flags=cv2.CASCADE_SCALE_IMAGE) #检测人脸
# 如果未检测到面部,则返回原始图像
if (len(faces) == 0):
return None, None
#假设多张脸
for (x, y, w, h) in faces:
# 返回图像的正面部分
# cv2.imshow('face', img[y:y + w, x:x + h, :])
face = gray[y:y + w, x:x + h].astype(np.float32) # 数值转换
face = cv2.resize(face, (150,150))
return face, faces
def prepare_training_data(data_folder_path):
# 获取数据文件夹中的目录(每个主题的一个目录)
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_alt.xml') #训练一组数据
dirs = os.listdir(data_folder_path) #返回data_folder_path目录下的文件夹和文件
# 两个列表分别保存所有的脸部和标签
faces = []
labels = []
# 浏览每个目录并访问其中的图像
for dir_name in dirs:
# dir_name(str类型)即标签
label = int(dir_name)
# 建立包含当前主题主题图像的目录路径
subject_dir_path = data_folder_path + '/' + dir_name
# 获取给定主题目录内的图像名称
subject_images_names = os.listdir(subject_dir_path)
# 浏览每张图片并检测脸部,然后将脸部信息添加到脸部列表faces[]
for image_name in subject_images_names:
# 建立图像路径
image_path = subject_dir_path + '/' + image_name
# 读取图像
image = cv2.imread(image_path)
#确保图像正确加载
if image is None:
continue
# 显示图像0.1s
cv2.imshow('Training on image...', image)
cv2.waitKey(100)
# 检测脸部
gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
# 检测多尺度图像,返回值是一张脸部区域信息的列表(x,y,宽,高)(输入图像,每次图像尺寸减小的比例,至少检测次数,目标的最小尺寸)
rect = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30),flags=cv2.CASCADE_SCALE_IMAGE) # 检测人脸
# 假设多张脸
for (x, y, w, h) in rect:
# 返回图像的正面部分
# cv2.imshow('face', img[y:y + w, x:x + h, :])
face = gray[y:y + w, x:x + h].astype(np.float32) # 数值转换
face = cv2.resize(face, (150, 150))
# 我们忽略未检测到的脸部
if face is not None:
#将脸添加到脸部列表并添加相应的标签
#将每张面部图像转换为一维向量并添加到列表中
face_vector = np.reshape(face,(1,-1))[0]
print(face.shape)
faces.append(face_vector)
labels.append(label)
#将faces和labels转换为numpy数组,以备后续PCA操作
faces= np.array(faces)
labels= np.array(labels)
return faces, labels
cap = cv2.VideoCapture(0)
stop = False
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
pca = PCA(n_components=60, svd_solver='full')
faces, labels = prepare_training_data('raw1')
# 进行PCA降维处理,提取主要特征
faces = pca.fit_transform(faces)
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_alt.xml')
while not stop:
success, img = cap.read()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
face, rect = detect_face(img, face_cascade)
if not rect is None:
# 检测人脸
(x, y, w, h) = rect
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
c = cv2.waitKey(100)
subjects = ['xu', 'LU', 'ZHOU']
# 生成图像的副本,这样就能保留原始图像
img1 = img.copy()
# 将测试图像转换为灰度图像,因为opencv人脸检测器需要灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 检测多尺度图像,返回值是一张脸部区域信息的列表(x,y,宽,高)
rect = face_cascade.detectMultiScale(img, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30),flags=cv2.CASCADE_SCALE_IMAGE)
if not rect is None:
for (x, y, w, h) in rect:
face = gray[y:y + w, x:x + h].astype(np.float32) # 数值转换
face = cv2.resize(face, (150, 150))
# face_vector = np.reshape(face,(1,-1))[0]#转换成一维向量
# 如果传入了PCA模型,则将人脸图像降维
face_pca = pca.transform(face.reshape(1, -1))
# face_pca = np.reshape(face_pca,(1,-1))[0]
cv2.rectangle(img1, (x, y), (x + w, y + h), (0, 255, 0), 2) # 画出矩形框
min_d = 1000000000000
c = -1
for i, f in enumerate(faces): # i,f是训练数据的信息,遍历训练数据
d = ((face_pca - f) ** 2).sum() # 计算test和训练图片的欧氏距离
if d < min_d:
min_d = d
c = labels[i] # 获得最小欧式距离,即最近邻
print(subjects[c])
cv2.putText(img1, subjects[c], (x, y), cv2.FONT_HERSHEY_COMPLEX, 1, (128, 128, 0), 2)
cv2.imshow('test', img1)
cv2.imshow('img', img1)
cv2.waitKey(1)
if c & 0xFF == ord('q'):
stop = True
cv2.destroyAllWindows()
# 0.81
为什么摄像头不显示
内容:可能是以下原因之一:
1. 摄像头没有正确连接到计算机;
2. 摄像头驱动程序没有正确安装;
3. 摄像头被其他程序占用,例如Skype或Zoom等;
4. 摄像头硬件故障。
解释:
- 人脸检测:使用
face_cascade.detectMultiScale()函数检测图像中的人脸,该函数返回人脸区域的坐标信息。 - 特征提取:使用 PCA 降维技术提取人脸的特征。
- 人脸匹配:使用欧氏距离计算测试人脸与训练人脸之间的距离,并将距离最小的训练人脸作为匹配结果。
- 显示结果:在图像中显示人脸识别结果,包括识别到的姓名。
注意事项:
- 确保已安装 OpenCV 库。
- 确保已将 Haar 级联分类器文件
haarcascade_frontalface_default.xml和haarcascade_frontalface_alt.xml放在代码的同一目录下。 - 确保在
prepare_training_data()函数中正确设置训练数据目录路径。 - 确保摄像头已正确连接到计算机,并且驱动程序已正确安装。
可能的错误和解决方法:
- 摄像头无法打开:检查摄像头是否正确连接到计算机,并且驱动程序是否已正确安装。
- 人脸检测失败:检查 Haar 级联分类器文件是否已正确放置。
- 识别结果不准确:尝试增加训练数据量,或调整 PCA 的参数。
- 其他错误:参考 OpenCV 文档,或在网上搜索相关解决方案。
代码的扩展:
- 可以使用其他特征提取方法,例如深度学习模型。
- 可以使用其他距离度量方法,例如余弦相似度。
- 可以添加人脸识别功能,例如登录或身份验证。
- 可以将人脸识别集成到其他应用程序中,例如图像处理或视频监控。
希望这能够帮助你完成人脸识别项目。如果你还有其他问题,请随时提问。
原文地址: http://www.cveoy.top/t/topic/mJI3 著作权归作者所有。请勿转载和采集!