【计算机视觉】人脸识别三大经典算法:LBPH、Eigenfaces、FisherFaces 原理与实战

人脸识别三大经典算法:LBPH、Eigenfaces、FisherFaces

  • [一、LBPH 算法(局部二值模式直方图)](#一、LBPH 算法(局部二值模式直方图))
    • [1. 基本原理](#1. 基本原理)
    • [2. 实现步骤](#2. 实现步骤)
    • [3. 代码实现](#3. 代码实现)
  • [二、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. 实现步骤

核心流程

  1. LBP 编码:以每个像素为中心,将其与周围邻域像素的灰度值进行比较,根据大小关系生成二进制编码,得到整幅图像的 LBP 编码图。

  2. 分块直方图统计:将 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:适合复杂环境(光照、姿态、表情变化较大)下的人脸识别,鲁棒性强,且计算效率高,适合实时应用。

相关推荐
SelectDB25 分钟前
数据不能出境的数仓选型与迁移落地:四问框架、可复算成本与迁移三段式
人工智能
李青菜31 分钟前
一个人 + AI,用 Tauri 2 和 Rust 写了个开源的 Windows 效率工具:提醒 + 笔记 + 启动器
人工智能
泯泷37 分钟前
做 AI 产品,路线图该数“实验”,而不是数“功能”
人工智能·llm·产品
无咎.lsy44 分钟前
《机器学习》笔记
笔记·机器学习
百度Geek说1 小时前
AI 内容核查怎么做:智能内容 AI 核查系统实践
人工智能
武子康1 小时前
Qwen-Drive 到底是什么:4B 级 VLM 如何成为驾驶策略底座
人工智能·算法·机器学习
落798.1 小时前
《启元 PrimeSim 如何用生成视频评估机器人策略》
人工智能·机器人·启元·具身应用
老纪的技术唠嗑局2 小时前
token 暴降75%!减少长程 Agent 任务中的重复开销,PowerContext v1.5.0 发布
人工智能
智塑未来2 小时前
明源云AI走播机器人,打造智能直播新体验
人工智能·机器人
brave10252 小时前
LLMGuide 大模型面试指南
人工智能·ai·面试·ai编程