人脸识别三大经典算法:LBPH、Eigenfaces、FisherFaces
- [一、LBPH 算法(局部二值模式直方图)](#一、LBPH 算法(局部二值模式直方图))
- [二、Eigenfaces 算法(特征脸)](#二、Eigenfaces 算法(特征脸))
-
- [1. 算法原理](#1. 算法原理)
- [2. 特点分析](#2. 特点分析)
- [3. 代码实现](#3. 代码实现)
- [三、FisherFaces 算法(费舍尔脸)](#三、FisherFaces 算法(费舍尔脸))
-
- [1. 算法原理](#1. 算法原理)
- [2. 特点分析](#2. 特点分析)
- [3. 代码实现](#3. 代码实现)
- 四、三种算法对比总结
一、LBPH 算法(局部二值模式直方图)
1. 基本原理
LBPH(Local Binary Patterns Histograms,局部二值模式直方图)是一种经典的图像纹理特征提取方法,广泛应用于人脸识别领域。
其核心思想是:利用 LBP 算子 描述图像局部纹理特征。LBP 算子将每个像素与其邻域内的像素进行灰度值比较,将比较结果编码为二进制数。随后,通过统计这些二进制数的直方图分布来提取图像的局部纹理信息。
在人脸识别任务中,LBPH 算法将人脸图像划分为多个局部块(Block) ,分别计算每个块的 LBP 直方图,最后将所有块的直方图拼接组合,形成完整的特征向量用于识别。

2. 实现步骤
核心流程
-
LBP 编码:以每个像素为中心,将其与周围邻域像素的灰度值进行比较,根据大小关系生成二进制编码,得到整幅图像的 LBP 编码图。
-
分块直方图统计:将 LBP 编码图划分为若干区域,统计每个区域的 LBP 直方图,再将所有区域的直方图拼接,得到整幅图像的完整直方图特征。
特点
LBPH 特征与 Haar 特征类似,本质上都是描述图像的灰度变化模式 。其最大优势在于鲁棒性------对光照变化、缩放、旋转和平移等干扰因素具有较强的抗干扰能力。通过比较不同人脸图像的 LBP 直方图差异,即可实现人脸识别。

3. 代码实现
python
import cv2
import numpy as np
# 加载训练图像(灰度图)
images = []
images.append(cv2.imread('fmjj1.png', cv2.IMREAD_GRAYSCALE))
images.append(cv2.imread('fmjj2.png', cv2.IMREAD_GRAYSCALE))
images.append(cv2.imread('ss1.png', cv2.IMREAD_GRAYSCALE))
images.append(cv2.imread('ss2.png', cv2.IMREAD_GRAYSCALE))
# 设置标签:前两张为"fmjj",后两张为"ss"
labels = [0, 0, 1, 1]
label_map = {0: 'fmjj', 1: 'ss', -1: '无法识别'}
# 待预测图像
predict_image = cv2.imread('fmjj.png', cv2.IMREAD_GRAYSCALE)
# 创建 LBPH 人脸识别器(设置置信度阈值 80)
recognizer = cv2.face.LBPHFaceRecognizer_create(threshold=80)
# 训练识别器
recognizer.train(images, np.array(labels))
# 预测
label, confidence = recognizer.predict(predict_image)
print('识别结果:', label_map[label])
print('置信度:', confidence)
# 在图像上显示识别结果
result_img = cv2.imread('fmjj.png').copy()
cv2.putText(result_img, label_map[label], (10, 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 0, 255), 2)
cv2.imshow('识别结果', result_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
二、Eigenfaces 算法(特征脸)
1. 算法原理
Eigenfaces 是一种基于主成分分析(PCA,Principal Component Analysis) 的人脸识别算法。其核心思想是:将高维的人脸图像数据通过 PCA 降维映射到低维空间,提取出人脸的主要特征方向(即"特征脸"),从而在保留关键信息的同时大幅降低计算复杂度。

2. 特点分析
| 优点 | 缺点 |
|---|---|
| 降维效果显著:将高维人脸数据压缩为低维特征,大幅减少计算量 | 对光照敏感:光照条件变化会显著改变人脸图像的主要特征向量 |
| 识别精度较高:提取的主要特征向量能够较好地区分不同人脸 | 对表情变化敏感:面部表情变化同样会影响特征向量的稳定性 |
| 计算效率高:训练和预测阶段均具有较快的处理速度 | 对姿态变化敏感:人脸朝向变化会影响识别效果 |
3. 代码实现
python
import cv2
import numpy as np
def load_and_resize(image_path, size=(120, 180)):
"""加载图像并统一尺寸"""
img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
img = cv2.resize(img, size)
return img
# 加载训练图像
images = []
images.append(load_and_resize('fmjj1.png'))
images.append(load_and_resize('fmjj2.png'))
images.append(load_and_resize('ss1.png'))
images.append(load_and_resize('ss2.png'))
# 标签
labels = [0, 0, 1, 1]
label_map = {0: 'fmjj', 1: 'ss'}
# 加载待预测图像
predict_image = load_and_resize('fmjj.png')
# 创建 Eigenfaces 识别器
recognizer = cv2.face.EigenFaceRecognizer_create()
# 训练
recognizer.train(images, np.array(labels))
# 预测
label, confidence = recognizer.predict(predict_image)
print('识别结果:', label_map[label])
print('置信度:', confidence)
# 显示结果
result_img = cv2.imread('fmjj.png').copy()
cv2.putText(result_img, label_map[label], (10, 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 0, 255), 2)
cv2.imshow('识别结果', result_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
三、FisherFaces 算法(费舍尔脸)
1. 算法原理
FisherFaces 算法基于线性判别分析(LDA,Linear Discriminant Analysis) 进行特征提取。与 Eigenfaces 的 PCA 不同,LDA 在降维过程中充分利用了类别标签信息,其优化目标为:
类内距离最小化:同一类别的样本在投影后尽可能聚集
类间距离最大化:不同类别的样本在投影后尽可能分散
通过 LDA 降维,FisherFaces 将原始人脸图像投影到低维判别空间,计算投影系数作为特征,从而实现高效识别。

2. 特点分析
| 优点 | 缺点 |
|---|---|
| 考虑类别信息:投影后的特征更具区分性,分类性能优于 PCA | 计算复杂度较高:训练阶段需计算类内/类间散度矩阵 |
| 对光照和角度有一定鲁棒性:结合了人脸几何形状和纹理信息 | 小样本问题:当样本数少于特征维度时,散度矩阵可能奇异 |
| 识别准确率高:尤其在类别区分明显的任务中表现优异 | 需要较多训练样本:每个类别至少需要 2-3 个样本 |
3. 代码实现
python
import cv2
import numpy as np
def load_and_resize(image_path, size=(120, 180)):
"""加载图像并统一尺寸"""
img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
img = cv2.resize(img, size)
return img
# 加载训练图像
images = []
images.append(load_and_resize('fmjj1.png'))
images.append(load_and_resize('fmjj2.png'))
images.append(load_and_resize('ss1.png'))
images.append(load_and_resize('ss2.png'))
# 标签
labels = [0, 0, 1, 1]
label_map = {0: 'fmjj', 1: 'ss'}
# 加载待预测图像
predict_image = load_and_resize('fmjj.png')
# 创建 FisherFaces 识别器
recognizer = cv2.face.FisherFaceRecognizer_create()
# 训练
recognizer.train(images, np.array(labels))
# 预测
label, confidence = recognizer.predict(predict_image)
print('识别结果:', label_map[label])
print('置信度:', confidence)
# 显示结果
result_img = cv2.imread('fmjj.png').copy()
cv2.putText(result_img, label_map[label], (10, 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 0, 255), 2)
cv2.imshow('识别结果', result_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
四、三种算法对比总结
| 对比维度 | Eigenfaces | FisherFaces | LBPH |
|---|---|---|---|
| 核心原理 | PCA 主成分分析 | LDA 线性判别分析 | 局部二值模式直方图 |
| 特征类型 | 全局特征(特征脸) | 全局特征(费舍尔脸) | 局部纹理特征 |
| 是否使用标签 | 否(无监督) | 是(有监督) | 是(有监督) |
| 降维效果 | 优秀 | 优秀 | 不适用(直方图) |
| 光照鲁棒性 | 较差 | 中等 | 优秀 |
| 表情鲁棒性 | 较差 | 中等 | 优秀 |
| 姿态鲁棒性 | 较差 | 中等 | 良好 |
| 计算复杂度 | 较低 | 中等 | 较低 |
| 适用场景 | 大规模数据集、光照可控 | 注重分类性能 | 复杂环境、实时识别 |
Eigenfaces:适合处理大规模数据集,对光照和表情变化不敏感的场景,或作为基线算法快速验证。
FisherFaces:适合需要较高分类精度的任务,尤其当各类别样本分布较为清晰时,识别效果优于 Eigenfaces。
LBPH:适合复杂环境(光照、姿态、表情变化较大)下的人脸识别,鲁棒性强,且计算效率高,适合实时应用。
