OpenCV(十一)人脸识别三大算法LBPH、EigenFace、FisherFace

一、前言

继昨天学习了人脸检测(Haar级联分类器)之后,今天进一步深入人脸识别领域。与"检测"不同,"识别"是要判断这个人是谁,而不是仅仅找到人脸的位置。

OpenCV的face模块提供了三种经典的人脸识别算法:

  • LBPH(局部二值模式直方图)
  • EigenFace(特征脸)
  • FisherFace(费舍尔脸)

本文将逐一解析这三个算法的使用方法和核心区别,并附上完整可运行的代码。

二、环境准备

bash 复制代码
pip install opencv-python opencv-contrib-python numpy pillow

注意cv2.face 模块在 opencv-contrib-python 中,需要单独安装。

数据集准备

本文示例使用4张训练图片:

  • hg0.jpghg1.jpg → 胡歌(标签0)
  • pyy0.jpgpyy1.jpg → 彭于晏(标签1)
  • 待识别图片:hg.jpg(胡歌的另一张照片)

三、算法一:LBPH(局部二值模式直方图)

核心原理

LBPH将图像分成若干小区域,对每个区域计算局部二值模式(LBP)直方图,然后串联成特征向量。对光照变化有较强的鲁棒性,是目前实际应用中较常用的方法。

完整代码

python 复制代码
import cv2
import numpy as np

# 准备训练数据(灰度图)
images = []
images.append(cv2.imread('hg0.jpg', cv2.IMREAD_GRAYSCALE))
images.append(cv2.imread('hg1.jpg', cv2.IMREAD_GRAYSCALE))
images.append(cv2.imread('pyy0.jpg', cv2.IMREAD_GRAYSCALE))
images.append(cv2.imread('pyy1.jpg', cv2.IMREAD_GRAYSCALE))

labels = [0, 0, 1, 1]
dic = {0: 'hg', 1: 'pyy', -1: '无法识别'}

# 待识别图片
predict_image = cv2.imread('hg.jpg', 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("这人是:", dic[label])
print('置信度:', confidence)

关键参数说明

参数 说明
threshold=80 置信度阈值,低于阈值认为匹配成功,否则返回-1
confidence 数值越小表示匹配度越高(0为完美匹配)

运行结果

text 复制代码
这人是: hg
置信度: 0.0

四、算法二:EigenFace(特征脸)

核心原理

EigenFace基于主成分分析(PCA),将高维人脸图像降维到低维"特征空间",通过比较投影后的特征向量进行识别。需要所有训练图像尺寸一致。

完整代码

python 复制代码
import cv2
import numpy as np

images = []

# 统一尺寸为 120x180
a = cv2.imread('hg0.jpg', 0)
a = cv2.resize(a, (120, 180))
b = cv2.imread('hg1.jpg', 0)
b = cv2.resize(b, (120, 180))
c = cv2.imread('pyy0.jpg', 0)
c = cv2.resize(c, (120, 180))
d = cv2.imread('pyy1.jpg', 0)
d = cv2.resize(d, (120, 180))

images.extend([a, b, c, d])
labels = [0, 0, 1, 1]

pre_image = cv2.imread('hg.jpg', 0)
pre_image = cv2.resize(pre_image, (120, 180))

# 创建EigenFace识别器
recognizer = cv2.face.EigenFaceRecognizer_create()
recognizer.train(images, np.array(labels))

# confidence范围:0~20000,低于5000认为可靠
label, confidence = recognizer.predict(pre_image)
dic = {0: 'hg', 1: 'pyy', -1: '-1'}
print('这人是:', dic[label])
print('置信度为:', confidence)

# 在图片上标注
aa = cv2.putText(cv2.imread('hg.jpg'), dic[label], (10, 30), 
                 cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 0, 255), 2)
cv2.imshow('xx', aa)
cv2.waitKey(0)

关键参数说明

参数 说明
confidence 范围 0~20000,低于5000 认为结果可靠
尺寸要求 所有训练图片和待识别图片必须完全一致

五、算法三:FisherFace(费舍尔脸)

核心原理

FisherFace基于线性判别分析(LDA),不仅考虑降维,还考虑类间差异最大化、类内差异最小化,因此识别率通常高于EigenFace,尤其适合光照变化较大的场景。

完整代码

python 复制代码
import cv2
import numpy as np
from PIL import Image, ImageDraw, ImageFont

# 在图片上添加中文文字
def cv2AddChineseText(img, text, position, textColor=(0, 255, 0), textSize=30):
    if isinstance(img, np.ndarray):
        img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
    draw = ImageDraw.Draw(img)
    fontStyle = ImageFont.truetype("simsun.ttc", textSize, encoding="utf-8")
    draw.text(position, text, textColor, font=fontStyle)
    return cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)

# 读取并统一尺寸
def image_re(image):
    a = cv2.imread(image, 0)
    a = cv2.resize(a, (120, 180))
    images.append(a)

images = []
image_re('hg0.jpg')
image_re('hg1.jpg')
image_re('pyy0.jpg')
image_re('pyy1.jpg')

labels = [0, 0, 1, 1]

pre_image = cv2.imread('hg.jpg', 0)
pre_image = cv2.resize(pre_image, (120, 180))

# 创建FisherFace识别器(阈值5000)
recognizer = cv2.face.FisherFaceRecognizer_create(threshold=5000)
recognizer.train(images, np.array(labels))

label, confidence = recognizer.predict(pre_image)
dic = {0: '胡歌', 1: '彭于晏', -1: '无法识别'}
print('这人是:', dic[label])
print('置信度为:', confidence)

# 在图片上添加中文标注
image = cv2AddChineseText(cv2.imread('hg.jpg').copy(), dic[label], (30, 10), 
                          textColor=(255, 0, 0))
cv2.imshow('xx', image)
cv2.waitKey(0)

关键参数说明

参数 说明
threshold=5000 置信度阈值,高于阈值返回-1(无法识别)
confidence 越小匹配度越高,阈值需根据实际数据调整

中文显示技巧

使用 PIL 绘制中文文字,因为OpenCV的putText默认不支持中文。

六、三大算法对比总结

对比维度 LBPH EigenFace FisherFace
核心原理 局部二值模式 + 直方图 PCA主成分分析 LDA线性判别分析
训练速度 较快 中等
识别速度
阈值可调 (threshold) (固定判断标准) (threshold)
尺寸要求 无需统一 必须统一 必须统一
置信度意义 越小越好 越小越好 越小越好
适用场景 实际项目首选 学术研究/入门 光照变化较大场景

置信度范围参考

算法 置信度范围 可靠阈值
LBPH 0 ~ 理论无穷大 < 80(可调)
EigenFace 0 ~ 20000+ < 5000
FisherFace 0 ~ 理论无穷大 < 5000(可调)

七、常见问题与解决方案

1. AttributeError: module 'cv2' has no attribute 'face'

原因 :未安装 opencv-contrib-python

解决

bash 复制代码
pip install opencv-contrib-python

2. 所有图片尺寸不一致报错(EigenFace/FisherFace)

解决 :统一使用 cv2.resize() 调整尺寸

python 复制代码
img = cv2.imread('hg0.jpg', 0)
img = cv2.resize(img, (120, 180))

3. 阈值设置不当导致识别失败

  • LBPH:阈值过低会拒识,过高会误识,建议从 80 开始调试
  • FisherFace:阈值从 5000 开始调试

4. 训练样本太少导致识别率低

每种人物至少准备 2~5 张不同角度/表情的照片。

相关推荐
xqqxqxxq1 小时前
AI Agent学习:第四章小结及八道思考题(李博杰《深入理解 AI Agent》第四章观后总结)
大数据·人工智能·学习
YOLO数据集集合1 小时前
反无人机禁飞识别无人机检测数据集 | 反无人机 禁飞识别 低空安防 目标检测 无人机检测10756期
人工智能·目标检测·无人机
yyk333241 小时前
OpenCV中的LBPH人脸识别
人工智能·opencv·计算机视觉
天天代码码天天1 小时前
把 PP-OCR 塞进一个纯 C Runtime:从 Tiny 到 Medium,再到单文件 HTML OCR
人工智能
xsd202411181 小时前
Stremio-WebStremio:开源流媒体自由聚合平台
人工智能
Aloudata1 小时前
语义治理 vs 知识治理:AI 数据分析需要业务知识库还是可执行语义层
大数据·人工智能·数据分析·data agent·语义层
阿黎梨梨1 小时前
LangGraph 核心机制:从状态管理到人机协同
人工智能·langchain
小兵金林1 小时前
初识 Transformer
人工智能
小白的后端世界1 小时前
数据分析基础学习
人工智能·学习·数据分析