基于传统方法的人脸识别代码实现
该代码使用OpenCV、LBP和PCA算法实现了基于传统方法的人脸识别,主要流程如下:
- 使用OpenCV中的人脸检测器,检测图像中的人脸区域。
- 将检测到的人脸区域转换为灰度图像,然后使用局部二值模式(LBP)算法提取人脸特征。
- 使用PCA算法对提取出的人脸特征进行降维处理,提取主要特征。
- 对训练集中的每张人脸图像进行相同的处理,得到一个人脸特征向量,并将其添加到一个列表中,同时将该人脸所属的标签添加到另一个列表中。
- 对测试集中的每张人脸图像进行相同的处理,得到一个人脸特征向量,并使用PCA算法将其降维处理。
- 对于测试集中的每张人脸图像,遍历训练集中的所有人脸特征向量,计算它们与测试集中的人脸特征向量之间的欧氏距离,找到与该测试集中的人脸特征向量最相似的训练集中的人脸特征向量。
- 将该训练集中的人脸特征向量所属的标签作为该测试集中的人脸图像的预测标签,并将其与实际标签比较,计算准确率。
import cv2
import os
import numpy as np
from sklearn.decomposition import PCA
from skimage.feature import local_binary_pattern
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, (100, 100))
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.01s
cv2.imshow('Training on image...', image)
cv2.waitKey(10)
# 检测脸部
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, (100, 100))
face_lbp = local_binary_pattern(face, 1, 8, 'uniform').reshape(1, -1)
# 我们忽略未检测到的脸部
if face is not None:
# 将脸添加到脸部列表并添加相应的标签
# 将每张面部图像转换为一维向量并添加到列表中
face_vector = np.reshape(face_lbp, (1, -1))[0] # 行数为1,列数不一定
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
if __name__ == '__main__':
# svd_solver='randomized':表示随机求取 pca,因为数据量较大,使用随机方式求解快些
pca = PCA(n_components=50, svd_solver='randomized')
faces, labels = prepare_training_data('exam2')
# 进行PCA降维处理,提取主要特征
faces = pca.fit_transform(faces) # 训练集拟合
images_names = os.listdir('test2') # 返回test目录下的文件和文件夹
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_alt.xml')
nofacenum = 0
error = 0
right = 0
for name in images_names:
img = cv2.imread('test2/'+name)
subjects = ['00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19',
'20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '0']
# 生成图像的副本,这样就能保留原始图像
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 len(rect) == 0:
cv2.putText(img1, 'unrecognized', (10, 20), cv2.FONT_HERSHEY_COMPLEX, 1, (128, 128, 0), 2)
cv2.imshow('test2', img1)
nofacenum += 1
print('nofacenum:%d'%nofacenum)
cv2.waitKey()
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, (100, 100))
face_lbp = local_binary_pattern(face, 1, 8, 'uniform').reshape(1, -1)
face_pca = pca.transform(face_lbp) # 测试集降维
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] # 获得最小欧式距离,即最近邻
cv2.putText(img1, subjects[c], (x, y), cv2.FONT_HERSHEY_COMPLEX, 1, (128, 128, 0), 2)
cv2.imshow('test2', img1)
if (subjects[c] == name[:2]):
right += 1
print('right:%d' % right)
cv2.waitKey()
else:
error += 1
print('error:%d' % error)
cv2.waitKey()
if c & 0xFF == ord('q'): # 按下q程序结束
stop = True
cv2.destroyAllWindows() # 释放窗口
rate = right/(len(images_names)-nofacenum)
print('准确率为:%.2f' % rate)
原文地址: https://www.cveoy.top/t/topic/jC1r 著作权归作者所有。请勿转载和采集!