2428 字
12 分钟
OpenCV案例:人脸识别与人脸检测

1. 介绍#

人脸识别是指程序对输入的人脸图像进行判断,并识别出其对应的人的过程。

2. 人脸识别#

​ 人脸识别,就是要找到一个模型可以用简洁又具有差异性的方式准确反映出每个人脸的特征在识别人脸时,先将当前人脸采用与前述同样的方式提取特征,再从已有特征集中找出当前特征的最邻近样本,从而得到当前人脸的标签

​ OpenCV提供了三种人脸识别方法,分别是LBPH方法EigenFishfaces方法Fisherfaces方法

2.1 LBP人脸识别#

原理#

LBP算法的基本原理是,将像素点A的值与其最邻近的 8 个像素点的值逐一比较

  • 如果A的像素值大于其临近点的像素值,则得到0
  • 如果A的像素值小于其临近点的像素值,则得到1

​ 最后,将得到的0和1值连起来,得到一个8位的二进制序列,这个二进制序列转换为十进制数,即是点A的LBP值

LBP算法也是获取图像的灰度变化特征,但LBP算法受光照影响较小,算法稳定性较强

使用方法#

  • 用函数cv2.face.LBPHFaceRecognizer_create()生成识别器实例
    • 函数原型val = cv2.face.LBPHFaceRecognizer_create( radius, neighbors, grid_x, grid_y, threshold )
  • 用函数cv2.face_FaceRecognizer.train()完成模型训练
    • 函数原型None = cv2.face_FaceRecognizer.train( src, labels )
  • 用函数cv2.face_FaceRecognizer.predict()完成人脸识别
    • 函数原型label, confidence = cv2.face_FaceRecognizer.predict( src )

示例#

import cv2
import numpy as np
Amount = 9
Group = 40
# 准备训练数据
images = []
for s in range(1, 1 + Group):
for n in range(1, 1 + Amount):
path = "ORL" + "\\" + "s" + str(s) + "\\" + str(n) + ".pgm"
image = cv2.imread(path, 0)
# cv2.imshow("preview", image)
# cv2.waitKey()
images.append(image)
labels = []
count = 0
for s in range(1, 1 + Group):
label = [count] * Amount
count = count + 1
labels.extend(label)
# 训练
recognizer = cv2.face.LBPHFaceRecognizer_create()
recognizer.train(images, np.array(labels))
# 预测
s = np.random.randint(1, 1 + Group)
path = "ORL" + "\\" + "s" + str(s) + "\\10.pgm"
predict_image = cv2.imread(path, 0)
cv2.imwrite("LBPH_predict.png", predict_image)
label, confidence = recognizer.predict(predict_image)
print("select =", str(s))
print("predict =", str(label+1))
print("confidence = %.2f" % confidence) # 值越接近于0,识别可靠性越高
select = 12
predict = 12
confidence = 64.23

LBPH_predict

2.2 PCA人脸识别(EigenFace)#

原理#

EigenFaces通常也被称为特征脸,它使用 主成分分析 方法将高维的人脸数据处理为低维数据后,再进行数据分析和处理,获取识别结果

使用方法#

  • 用函数cv2.face.EigenFaceRecognizer_create()生成识别器实例
    • 函数原型val = cv2.face.LBPHFaceRecognizer_create( num_components, threshold )
  • 用函数cv2.face_FaceRecognizer.train()完成模型训练
    • 函数原型None = cv2.face_FaceRecognizer.train( src, labels )
  • 用函数cv2.face_FaceRecognizer.predict()完成人脸识别
    • 函数原型label, confidence = cv2.face_FaceRecognizer.predict( src )

示例#

import cv2
import numpy as np
Amount = 9
Group = 40
# 准备训练数据
images = []
for s in range(1, 1 + Group):
for n in range(1, 1 + Amount):
path = "ORL" + "\\" + "s" + str(s) + "\\" + str(n) + ".pgm"
image = cv2.imread(path, 0)
# cv2.imshow("preview", image)
# cv2.waitKey()
images.append(image)
labels = []
count = 0
for s in range(1, 1 + Group):
label = [count] * Amount
count = count + 1
labels.extend(label)
# 训练
recognizer = cv2.face.EigenFaceRecognizer_create()
recognizer.train(images, np.array(labels))
# 预测
s = np.random.randint(1, 1 + Group)
path = "ORL" + "\\" + "s" + str(s) + "\\10.pgm"
predict_image = cv2.imread(path, 0)
cv2.imwrite("EigenFace_predict.png", predict_image)
label, confidence = recognizer.predict(predict_image)
print("select =", str(s))
print("predict =", str(label+1))
print("confidence = %.2f" % confidence) # 值越接近于0,识别可靠性越高
select = 33
predict = 33
confidence = 772.21

EigenFace_predict

2.3 LDA人脸识别(FisherFace)#

原理#

Fisherfaces采用LDA方法(Linear Discriminant Analysis)实现人脸识别。

线性判别分析对特征降维的同时考虑类别信息:在低维表示下,相同的类应该紧密地聚集在一起不同的类别应该尽可能地分散开,并且它们之间的距离尽可能地远

线性判别分析就是要尽力满足以下两个要求:

  • 类别之间的差别尽可能地大
  • 类别内部的差别尽可能地小

​ 做线性判别分析时,首先将训练样本集投影到一条直线上,让投影后的点满足:同类间的点尽可能地靠近,异类间的点尽可能地远离。做识别时,将待测样本再投影到直线上根据投影点的位置判定样本的类别,就完成了识别

LDA

使用方法#

  • 用函数cv2.face.FisherFaceRecognizer_create()生成识别器实例
    • 函数原型val = cv2.face.LBPHFaceRecognizer_create( num_components, threshold )
  • 用函数cv2.face_FaceRecognizer.train()完成模型训练
    • 函数原型None = cv2.face_FaceRecognizer.train( src, labels )
  • 用函数cv2.face_FaceRecognizer.predict()完成人脸识别
    • 函数原型label, confidence = cv2.face_FaceRecognizer.predict( src )

示例#

import cv2
import numpy as np
Amount = 9
Group = 40
# 准备训练数据
images = []
for s in range(1, 1 + Group):
for n in range(1, 1 + Amount):
path = "ORL" + "\\" + "s" + str(s) + "\\" + str(n) + ".pgm"
image = cv2.imread(path, 0)
# cv2.imshow("preview", image)
# cv2.waitKey()
images.append(image)
labels = []
count = 0
for s in range(1, 1 + Group):
label = [count] * Amount
count = count + 1
labels.extend(label)
# 训练
recognizer = cv2.face.FisherFaceRecognizer_create()
recognizer.train(images, np.array(labels))
# 预测
s = np.random.randint(1, 1 + Group)
path = "ORL" + "\\" + "s" + str(s) + "\\10.pgm"
predict_image = cv2.imread(path, 0)
cv2.imwrite("FisherFace_predict.png", predict_image)
label, confidence = recognizer.predict(predict_image)
print("select =", str(s))
print("predict =", str(label+1))
print("confidence = %.2f" % confidence) # 值越接近于0,识别可靠性越高
select = 2
predict = 2
confidence = 616.28

FisherFace_predict

3. 人脸检测#

​ 在人脸检测中,主要任务是构造能够区分包含人脸实例和不包含人脸实例的分类器。这些包含人脸图像的实例,被称为正类,而不包含人脸图像的实例,则被称为负类

​ OpenCV提供了三种不同的训练好的级联分类器,分别为 HAAR特征级联分类器HOG特征分类器基于LBP算法的级联分类器

​ 在OpenCV中,有一些训练好的级联分类器,方便供用户使用。这些分类器可以用来检测人脸检测脸部特征(眼睛、鼻子)、检测人体或其他物体。这些级联分类器以XML文件的形式存放在OpenCV源文件的data目录下,加载不同级联分类器的XML文件就可以实现对不同对象的检测

Haar特征反映的是图像的灰度变化,它将像素划分为模块后求差值Haar特征用黑白两种矩形框组合成特征模板,在特征模板内,用白色矩形像素块的像素和减去黑色矩形像素块的像素和来表示该模板的特征。

XML文件名级联分类器类型
harrcascade_eye.xml眼睛检测
haarcascade_eye_tree_eyeglasses.xml眼镜检测
haarcascade_mcs_nose.xml鼻子检测
haarcascade_mcs_mouth.xml嘴巴检测
harrcascade_smile.xml表情检测
hogcascade_pedestrians.xml行人检测
lbpcasecade_frontalface.xml正面人脸检测
lbpcasecade_profileface.xml人脸检测
lbpcascade_silverware.xml金属检测

示例#

import cv2
# 读取待检测的图像
image = cv2.imread('family.jpg')
# 获取 XML 文件,加载人脸检测器
faceCascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
# 色彩转换,转换为灰度图像
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
# 调用函数 detectMultiScale
faces = faceCascade.detectMultiScale( gray,
scaleFactor=1.15,
minNeighbors=10,
minSize=(5,5))
# 打印输出的测试结果
print("共发现{0}个人脸!".format(len(faces)))
print("人脸坐标为:\n", faces)
# 逐个标注人脸
for (x, y, w, h) in faces:
cv2.rectangle(image, (x, y), (x + w, y + w), (0, 255, 0), 2)
# 保存检测结果
cv2.imwrite("face_detect.jpg", image)
共发现5个人脸!
人脸坐标为:
[[449 68 84 84]
[363 380 72 72]
[316 61 75 75]
[491 316 73 73]
[212 281 93 93]]
原图检测结果
familyface_detect

4. 人脸数据库#

CAS-PEAL#

CAS-PEAL中科院计算技术研究所在2003年完成的包含1040位志愿者(其中有595位男性445位女性的共99594幅人脸图像的数据库

​ 数据集的所有图像都是在专门的采集环境中采集的,涵盖了姿态表情饰物光照等4种主要变化条件,部分人脸图像具有背景、距离和时间跨度的变化

​ 目前,该数据库面向研究开放了其子集CAS-PEAL-R1,包含1040人30900幅图像

ORL#

ORL数据集包含40个人400幅图像。这些图像具有不同的拍摄时间不同的光线不同的面部表情不同的面部细节

所有的图像都是在亮度均匀的背景下拍摄的,被拍摄对象处于直立状态,拍摄正脸

​ 数据集内所有的图像是以PGM格式存储的,都是尺寸为92×112,包含256个灰度级的灰度图像。图像文件被放置在40个不同的目录内,目录名用3位数字的序号表示,每个目录对应一个不同的人,里面有10幅被拍摄对象的不同图像,并用两位数字作为文件名

Yale#

​ Yale数据集由15人(14名男性、1名女性)的人脸图像组成,每人都有11幅灰度图像。这个数据集的人脸图像,在光线条件面部表情饰物等方面都有变化。

Extended Yale#

​ 在Yale数据集上扩充至28人,其数据集包含28个人9个姿势64个照明条件下的16128幅图像

FERET#

​ FERET(Facial Recognition Technology)是由美国国防部资助的计划,该计划旨在开发用于人脸自动识别的新技术和算法

​ FERET数据库包含1564组共计14126幅图像。所有这些图像,是由1199个不同的被拍摄对象365组重复拍摄对象的图像构成的,其中的365组重复拍摄对象,是指被拍摄对象在已经完成第1组拍摄的情况下,在不同的时间又拍摄了第2组图像。

FERET数据库人脸识别领域应用最广泛的人脸数据库之一

封面
示例歌曲
示例艺术家
封面
示例歌曲
示例艺术家
0:00 / 0:00