目录
一、生成人脸识别数据
二、加载人脸识别的训练数据
三、基于特征脸进行人脸识别
四、基于 Fisherface 进行人脸识别
五、基于 LBPH 进行人脸识别
全部代码
为了进行人脸识别,我们需要待识别的人脸,人脸可以通过两种方式获取
(下面,我们用自己提供的图像(摄像头)完成人脸数据的收集)
代码
# 可直接运行
import cv2
import os
# 创建一个特定的文件夹,用于存放人脸数据
output_folder = '../data/at/ReadyGo'
if not os.path.exists(output_folder):
os.makedirs(output_folder)
# 初始化两个CascadeClassifier对象,分别用于人脸和眼睛
face_cascade = cv2.CascadeClassifier(
'C:/MyOpenCV/cascades/haarcascade_frontalface_default.xml')
eye_cascade = cv2.CascadeClassifier(
'C:/MyOpenCV/cascades/haarcascade_eye.xml')
camera = cv2.VideoCapture(0)
count = 0
while (cv2.waitKey(1) == -1):
success, frame = camera.read()
if success:
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(
gray, 1.3, 5, minSize=(120, 120))
for (x, y, w, h) in faces:
cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2)
# 将人脸区域调整为200*200像素
face_img = cv2.resize(gray[y:y + h, x:x + w], (200, 200))
face_filename = '%s/%d.pgm' % (output_folder, count)
cv2.imwrite(face_filename, face_img)
count += 1
cv2.imshow('Capturing Faces...', frame)
camera.release()
cv2.destroyAllWindows()
代码解析
上面,我们生成了训练数据,并将他们保存在根据人名或者人名首字母进行组织的文件夹中。
下面,我们编写一个脚本加载这些图像,并以一种 OpenCV 的人脸识别器能够理解的方式对它们进行标签。
代码
import os
import cv2
import numpy
def read_images(path, image_size):
names = []
training_images, training_labels = [], []
label = 0
for dirname, subdirnames, filenames in os.walk(path):
for subdirname in subdirnames:
names.append(subdirname)
subject_path = os.path.join(dirname, subdirname)
for filename in os.listdir(subject_path):
img = cv2.imread(os.path.join(subject_path, filename),
cv2.IMREAD_GRAYSCALE)
if img is None:
# The file cannot be loaded as an image.
# Skip it.
continue
img = cv2.resize(img, image_size)
training_images.append(img)
training_labels.append(label)
label += 1
training_images = numpy.asarray(training_images, numpy.uint8)
training_labels = numpy.asarray(training_labels, numpy.int32)
return names, training_images, training_labels
通过如下代码调用 read_images 函数:
path_to_training_images = '../data/at'
training_image_size = (200, 200)
names, training_images, training_labels = read_images(
path_to_training_images, training_image_size)
代码分析
到目前为止,我们已经有了有用格式的训练数据(但还没有训练),而且还没有创建人脸识别器。
下面的脚本,与此脚本为同一个脚本,运行时需同时运行。
上面,我们已经有了有用格式的训练图像(数组)和标签(数组)。
下面,用两行代码创建和训练一个人脸识别器。
代码
model = cv2.face.EigenFaceRecognizer_create() # 使用默认参数
model.train(training_images, training_labels)
我们可以选择地将两个参数传递给cv2.EigenFaceRecognizer_create():
下面,我们将进行人脸识别器的初始化:
face_cascade = cv2.CascadeClassifier(
'C:/MyOpenCV/cascades/haarcascade_frontalface_default.xml')
然后初始化摄像头回传信号,遍历帧,对每一帧进行人脸识别和检测
camera = cv2.VideoCapture(0)
while (cv2.waitKey(1) == -1):
success, frame = camera.read()
if success:
faces = face_cascade.detectMultiScale(frame, 1.3, 5)
for (x, y, w, h) in faces:
cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
roi_gray = gray[x:x + w, y:y + h]
if roi_gray.size == 0:
continue
roi_gray = cv2.resize(roi_gray, training_image_size)
label, confidence = model.predict(roi_gray)
text = '%s, confidence = %.2f' % (names[label], confidence)
cv2.putText(frame, text, (x, y - 20), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2)
cv2.imshow('Face Recognition', frame)
camera.release()
cv2.destroyAllWindows()
代码分析
拓展:
置信度典型的取值范围取决于算法,特征脸和Fisherfish产生的值的范围大致在0~20000,低于4000的所有数值都表示是一个相当有信心的识别结果。对于LBPH,好的识别结果参考值低于50,所有超过80的值都被认为是糟糕的置信度。
下面,我们用其他算法替换特征脸
cv2.face.FisherFaceRecognizer_create() 和 cv2.face.EigenFaceRecognizer_create()接收相同的两个可选参数:主成分数量和置信度阈值
只需替换一行代码(使用默认参数):
model = cv2.face.FisherFaceRecognizer_create()
LBPH 算法接收以下可选参数(按顺序):
替换一行代码(使用默认参数):
model = cv2.face.LBPHFaceRecognizer_create()
注意:
使用LBPH不需要调整(resize)图像的大小
1.采集人脸数据(.py)
import cv2
import os
# 创建一个特定的文件夹,用于存放人脸数据
output_folder = '../data/at/ReadyGo'
if not os.path.exists(output_folder):
os.makedirs(output_folder)
# 初始化两个CascadeClassifier对象,分别用于人脸和眼睛
face_cascade = cv2.CascadeClassifier(
'C:/MyOpenCV/cascades/haarcascade_frontalface_default.xml')
eye_cascade = cv2.CascadeClassifier(
'C:/MyOpenCV/cascades/haarcascade_eye.xml')
camera = cv2.VideoCapture(0)
count = 0
while (cv2.waitKey(1) == -1):
success, frame = camera.read()
if success:
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(
gray, 1.3, 5, minSize=(120, 120))
for (x, y, w, h) in faces:
cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2)
# 将人脸区域调整为200*200像素
face_img = cv2.resize(gray[y:y + h, x:x + w], (200, 200))
face_filename = '%s/%d.pgm' % (output_folder, count)
cv2.imwrite(face_filename, face_img)
count += 1
cv2.imshow('Capturing Faces...', frame)
camera.release()
cv2.destroyAllWindows()
2.识别人脸(.py)
import os
import cv2
import numpy
def read_images(path, image_size):
names = []
training_images, training_labels = [], []
label = 0
for dirname, subdirnames, filenames in os.walk(path):
for subdirname in subdirnames:
names.append(subdirname)
subject_path = os.path.join(dirname, subdirname)
for filename in os.listdir(subject_path):
img = cv2.imread(os.path.join(subject_path, filename),
cv2.IMREAD_GRAYSCALE)
if img is None:
# The file cannot be loaded as an image.
# Skip it.
continue
img = cv2.resize(img, image_size)
training_images.append(img)
training_labels.append(label)
label += 1
training_images = numpy.asarray(training_images, numpy.uint8)
training_labels = numpy.asarray(training_labels, numpy.int32)
return names, training_images, training_labels
path_to_training_images = '../data/at'
training_image_size = (200, 200)
names, training_images, training_labels = read_images(
path_to_training_images, training_image_size)
model = cv2.face.LBPHFaceRecognizer_create()
model.train(training_images, training_labels)
face_cascade = cv2.CascadeClassifier(
'C:/MyOpenCV/cascades/haarcascade_frontalface_default.xml')
camera = cv2.VideoCapture(0)
while (cv2.waitKey(1) == -1):
success, frame = camera.read()
if success:
faces = face_cascade.detectMultiScale(frame, 1.3, 5)
for (x, y, w, h) in faces:
cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
roi_gray = gray[x:x + w, y:y + h]
if roi_gray.size == 0:
continue
# roi_gray = cv2.resize(roi_gray, training_image_size)
label, confidence = model.predict(roi_gray)
text = '%s, confidence = %.2f' % (names[label], confidence)
cv2.putText(frame, text, (x, y - 20), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2)
cv2.imshow('Face Recognition', frame)
camera.release()
cv2.destroyAllWindows()
【参考】:OpenCV 4计算机视觉 Python语言实现(原书第三版) 作者:Joseph Howse