MB_LBP+PCA+SVM:传统人脸识别流程详解
2026/9/20 18:45:34 网站建设 项目流程

简介:面向人脸识别方向的研究者、算法初学者与模式识别课程学习者,这份PDF围绕多块局部二值模式(MB_LBP)与主成分分析(PCA)的融合算法展开。资源从LBP和PCA各自优缺点切入,说明MB_LBP如何通过块级平均灰度比较增强局部特征稳定性,再由PCA对人脸特征降维,最终使用SVM完成分类与识别;ORL人脸库实验显示,该组合方法比传统PCA识别率提升13%以上。压缩包共1个PDF文件,大小约850KB,内容包含算法原理、实现流程、实验数据与结论,结构完整,适合作为人脸识别课题的参考文献、算法对比实验的起点、组会汇报素材或课程报告写作参考。文中对姿态变化、光照变化等识别难点也给出了针对性分析,可帮助理解算法改进动机。已有126人学习,适合希望快速建立方法框架并进一步复现实验的读者。

1. 为什么人脸识别要回到 LBP 这条老路

2016 年这篇论文在 ORL 人脸库上把识别率抬高了 13%,放到今天看数字不算惊艳,但它的思路在深度学习普及之前,是工程落地最稳的一类方案:不做端到端学习,而是先用人工设计的特征描述人脸纹理,再用线性降维压缩特征维度,最后交给一个经典分类器完成判别。这套流程的价值在于可解释性和低资源依赖,即便现在用 OpenCV 或树莓派做离线人脸识别,依然绕不开 LBP 或其变体。MB_LBP 是对原始 LBP 的改进,核心改动只有一处——把「单个像素对单个像素」的比较换成「像素块平均灰度对像素块平均灰度」的比较。这个改动的直接收益是抗噪能力提升,代价是需要手动调分块大小。全文沿着特征提取、降维、分类这条主线展开,适合两类读者:一类是想复现传统人脸识别流程的入门者,另一类是在嵌入式设备上做实时识别、需要控制计算量的工程师。

2. LBP 到 MB_LBP:从像素比较到块均值比较

2.1 原始 LBP 的特征提取逻辑与噪声缺陷

原始 LBP 对图像中每个像素计算一个二进制编码。取当前像素的灰度值为阈值,与其半径为 R 的邻域内 P 个采样点的灰度值逐一比较,邻域灰度大于等于中心灰度记为 1,否则记为 0,按固定顺序排列得到一个 P 位二进制数,再转为十进制作为该像素的 LBP 值。这个编码描述的是局部纹理模式,对单调灰度变化不敏感,因此光照变化下仍能保持相对稳定。

但原始 LBP 的缺陷也很明显。它假设中心像素本身是可靠的,一旦中心像素恰好落在噪声点、反光区域或者传感器坏点上,比较结果会被整体带偏。另一个问题是采样点落在非整数坐标时需要使用插值,插值误差在小半径场景下会被放大。Ahonen 等人把人脸划分成不重叠区域,在每个区域内统计 LBP 直方图再拼接成特征向量,但这个做法解决不了单像素比较的不稳定性问题。

2.2 MB_LBP 的公式化描述与参数含义

MB_LBP 把比较粒度从像素提升到块。设中心块大小为s × s,其平均灰度为g_c,周围第 i 个块的大小同样为s × s,平均灰度为g_i,则中心像素的 MB_LBP 编码公式为:

MB_LBP(P, R, s) = Σ_{i=0}^{P-1} sign(g_i - g_c) · 2^i

其中sign(x)x ≥ 0时取 1,否则取 0。P表示周围块的数量,R表示周围块中心到中心块中心的距离。注意这里的 R 不再是像素半径,而是块中心间距,实际感受野比原始 LBP 大得多。论文中采用的矩形块划分方式,计算块均值后进行比较。

s = 1时,MB_LBP 退化为原始 LBP,所以原始 LBP 是 MB_LBP 的特例。增大 s 相当于对图像做了局部平滑,能抑制高频噪声,但 s 过大会把眼睛、鼻子边缘等真实纹理也抹掉,导致人脸看起来“粒度化”。分块大小是一个需要针对人脸库分辨率调节的超参数,论文实验部分对 ORL 库的 92×112 图像,块大小取 3×3 或 5×5 是比较合理的起点。

2.3 直方图特征的分块统计策略

提取完整张图的 MB_LBP 响应图后,还需要把响应图转化为特征向量。常见做法是把人脸图像划分为m × n个互不重叠的子区域,对每个子区域统计 256 维的 MB_LBP 直方图,再把所有子区域的直方图首尾拼接。若划分为4 × 4个子区域,最终特征维度是16 × 256 = 4096维。

这里有一个工程取舍:子区域划分越多,空间信息保留越完整,但特征维度越高,且每个子区域的统计样本越少,直方图越稀疏。论文采用固定划分,没有做自适应区域加权,这在实际使用中是可以优化的点——眼睛、鼻子区域对人脸识别贡献更大,可以赋予更高权重,而额头和下巴区域权重可以降低。

3. PCA 降维:消除冗余,保留主成分

3.1 PCA 作用于 MB_LBP 特征而非原始像素

论文的关键细节是:PCA 不是直接作用在原始人脸图像上,而是作用在 MB_LBP 直方图拼接后的高维特征上。这一步决定了整个算法的性质——MB_LBP 负责提取局部纹理信息,PCA 负责去除特征维度间的相关性并压缩数据。原始像素经过 PCA 得到的是特征脸(Eigenface),反映的是整体灰度分布;而 MB_LBP 特征经过 PCA 得到的是对局部纹理模式的主成分,两者语义不同。

3.2 协方差矩阵与特征降维的计算流程

假设训练集有 N 张人脸图像,每张图像经过 MB_LBP 处理后得到 D 维特征向量x_i,构成数据矩阵X ∈ R^{N×D}。PCA 的完整计算步骤如下:

  1. 去均值:计算所有训练样本的平均特征向量μ = (1/N) Σ x_i,每个样本减去平均特征x_i' = x_i - μ,目的是让后续协方差计算不受整体亮度偏移影响。
  2. 计算协方差矩阵C = (1/N) X'^T X',这里X'是去均值后的特征矩阵。协方差矩阵的对角线元素表示各维度的方差,非对角线元素表示维度间的协方差,PCA 的目标就是找到一组新基,使得数据在新基上的方差最大化、协方差最小化。
  3. 特征值分解:对协方差矩阵做特征值分解,得到特征值λ_1 ≥ λ_2 ≥ ... ≥ λ_D及对应的特征向量。特征值大小代表对应方向上方差的大小,即信息量的多少。
  4. 选择主成分个数 k:取前 k 个最大特征值对应的特征向量构成投影矩阵W ∈ R^{D×k},k 的选取通常根据累计贡献率Σ_{i=1}^k λ_i / Σ_{i=1}^D λ_i ≥ 0.95来决定。
  5. 投影降维:将原始特征x_i投影到新空间y_i = W^T x_i',得到 k 维向量作为最终的人脸特征表示。

3.3 为什么用奇异值分解而不是直接求协方差

当 D 远大于 N 时,协方差矩阵 C 的维度是D × D,直接求特征值分解的计算量过大。论文原文提到对协方差矩阵进行奇异值分解(SVD),这是一种等价但更稳定的数值计算方法。SVD 将数据矩阵X'分解为U Σ V^T,其中 V 的列向量就是协方差矩阵的特征向量,Σ 的对角元素是奇异值,等于特征值的平方根。使用 SVD 避免了显式构造协方差矩阵,数值稳定性更好,尤其在特征维度高、样本数少的情况下优势明显。实际实现中直接调用numpy.linalg.svd即可,不需要手写分解算法。

import numpy as np from sklearn.decomposition import PCA # X_mb_lbp 是 MB_LBP 特征矩阵,形状为 (N, D),N 为训练样本数 # 方法一:直接调用 sklearn 封装的 PCA pca = PCA(n_components=0.95) # 保留 95% 累计方差贡献率 X_pca = pca.fit_transform(X_mb_lbp) print(f"降维前特征维度: {X_mb_lbp.shape[1]}") print(f"降维后特征维度: {X_pca.shape[1]}") print(f"各主成分解释方差比: {pca.explained_variance_ratio_}") # 方法二:手动 SVD 实现,便于理解内部逻辑 X_mean = np.mean(X_mb_lbp, axis=0) X_centered = X_mb_lbp - X_mean U, S, Vt = np.linalg.svd(X_centered, full_matrices=False) # Vt 的行向量是特征向量,按对应奇异值大小降序排列 # 累计贡献率达到 95% 时所需的主成分个数 cumsum_ratio = np.cumsum(S**2) / np.sum(S**2) k = np.argmax(cumsum_ratio >= 0.95) + 1 W = Vt[:k].T # 投影矩阵,形状为 (D, k) X_pca_manual = X_centered @ W

代码中的n_components=0.95表示自动选择使累计方差贡献率达到 95% 的主成分个数,ORL 库上通常落在 40 到 80 之间。explained_variance_ratio_输出每个主成分单独解释的方差比例,前几个主成分占比很大,后续快速衰减,验证了人脸特征在低维空间具有集中分布的特性。手动 SVD 版本中,S**2对应特征值,通过累计占比曲线可以直观看到 k 的选取依据。两种方式结果一致,推荐使用 sklearn 版本做实验,手动版本用于理解原理。

4. SVM 分类器与 ORL 实验复现

4.1 SVM 的人脸识别原理与核函数选择

SVM 的核心思想是找到一个超平面,使得两类样本之间的间隔最大化。人脸识别场景下,降维后的特征向量输入 SVM,通过核函数把低维空间中的非线性可分问题映射到高维空间,在高维空间中构造线性分类超平面。论文采用的判别函数为:

f(x) = sign(Σ_{i=1}^{n} α_i y_i K(x_i, x) + b)

其中 K 是核函数,用于计算两个样本在高维空间中的内积。对于人脸特征这类高维小样本数据,径向基核函数(RBF)通常是默认选择:

K(x_i, x_j) = exp(-γ ||x_i - x_j||²)

RBF 核的优点是只有一个参数 γ 需要调,而且能把特征映射到无限维空间,表达能力比线性核强。但 γ 过大会导致过拟合——每个训练样本都成为支持向量,测试时泛化能力差;γ 过小则模型过于平滑,无法区分相近的人脸。论文没有给出具体的 γ 和 C 参数,这属于实现细节,使用网格搜索可以从数据中确定。

4.2 ORL 数据集上的训练流程

ORL 人脸库包含 40 个不同人的 400 张灰度图像,每人 10 张,分辨率为 92×112 像素。实验通常采用留出法,随机选取每人 5 张作为训练集,剩余 5 张作为测试集,这样训练集共 200 张,测试集共 200 张。完整训练流程分为特征提取、降维、分类三个环节:

import cv2 import numpy as np from sklearn import svm from sklearn.model_selection import GridSearchCV, train_test_split from sklearn.decomposition import PCA from sklearn.metrics import accuracy_score def mb_lbp_feature(image, block_size=3, sub_regions=(4, 4)): """提取 MB_LBP 特征,返回归一化直方图""" h, w = image.shape # 将图像划分为子区域,在每个子区域内逐像素计算 MB_LBP histograms = [] region_h, region_w = h // sub_regions[0], w // sub_regions[1] for i in range(sub_regions[0]): for j in range(sub_regions[1]): region = image[i*region_h:(i+1)*region_h, j*region_w:(j+1)*region_w] # 此处简化处理,实际 MB_LBP 需要对每个像素计算块均值比较 # 完整实现使用积分图加速块均值计算 hist, _ = np.histogram(region.ravel(), bins=256, range=(0, 256)) hist = hist / (np.sum(hist) + 1e-6) # 归一化消除光照幅度影响 histograms.extend(hist) return np.array(histograms) # 加载 ORL 数据集,images 为 (400, 92, 112) 数组,labels 为 (400,) 数组 # 假设 images 和 labels 已从 ORL 目录读取 X = np.array([mb_lbp_feature(img) for img in images]) y = labels # 划分训练集和测试集:每人 5 张训练,5 张测试 X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.5, stratify=y, random_state=42 ) # PCA 降维:在训练集上拟合,测试集用同一变换 pca = PCA(n_components=0.95, whiten=True) X_train_pca = pca.fit_transform(X_train) X_test_pca = pca.transform(X_test) print(f"降维后维度: {X_train_pca.shape[1]}") # 网格搜索找到最优 RBF 核参数 param_grid = {'C': [1, 10, 100], 'gamma': [0.001, 0.01, 0.1]} clf = GridSearchCV(svm.SVC(kernel='rbf'), param_grid, cv=5) clf.fit(X_train_pca, y_train) # 测试集上评估 y_pred = clf.predict(X_test_pca) acc = accuracy_score(y_test, y_pred) print(f"测试集识别率: {acc:.4f}") print(f"最优参数: {clf.best_params_}")

这段代码的要点在于:stratify=y保证训练集和测试集中每类样本比例相同,防止某个人的人脸全部落在训练集导致测试集失效;whiten=True对降维后的特征做标准化,使得各维度方差一致,避免数值范围差异影响 SVM 的间隔计算;网格搜索的C是误分类惩罚系数,C越大对错误分类的惩罚越重,决策边界越复杂。

4.3 识别率提升 13% 的构成分析

论文给出的对比是 MB_LBP+PCA 相对传统 PCA 识别率提升 13% 以上。这个提升来自两个环节的叠加:MB_LBP 特征比原始像素特征对光照和姿态变化更鲁棒,这是主要贡献;PCA 在 MB_LBP 特征上降维比在原始像素上降维保留了更多的判别信息。还有一个隐性因素是 SVM 的强分类能力——传统 PCA 方法通常配合最近邻分类器,SVM 的间隔最大化策略在小样本条件下比最近邻更稳定。

复现时需要注意,13% 的提升比例依赖具体的随机划分。如果训练集和测试集的划分不同,提升幅度会有波动。论文没有披露是否采用多次随机实验取平均值,实际复现建议做 5 次随机划分取均值,减少因划分偶然性带来的偏差。

5. 参数边界、光照场景与工程实现细节

5.1 分块大小的取值边界

MB_LBP 算法中分块大小直接决定感受野和抗噪能力。对于 92×112 分辨率的 ORL 图像,建议测试 1×1、3×3、5×5、7×7 四组取值。实验规律一般是:从 1×1 增大到 3×3 时,识别率上升,因为噪声被局部平均抑制;继续增大到 7×7 时,识别率开始下降,因为眼睛、嘴巴等关键纹理被过度平滑,个体差异性被抹除。如果人脸图像分辨率更高,比如 128×128 以上,可以尝试 5×5 到 9×9 的范围。

提示:分块大小的选取需要和人脸对齐质量联动。如果人脸检测框偏差较大,较小的分块反而对位置偏移更敏感,此时适当增大分块尺寸能提升鲁棒性。

5.2 主成分个数 k 的验证方法

PCA 降维的 k 值不一定要固定为 95% 累计贡献率,可以用单变量搜索的方式验证不同 k 下的识别率变化。在 ORL 库上,k 从 10 增长到 30 时识别率上升明显,30 到 80 之间趋于平缓,超过 80 后可能出现轻微下降——这是维度诅咒的表现,特征维度过高而训练样本有限,SVM 在高维空间中容易过拟合。绘制「k 值-识别率」曲线可以更直观地看到拐点位置,作为最终参数选择依据。

5.3 光照变化场景下的特征归一化

MB_LBP 对单调光照变化天然不敏感,因为比较操作去除了绝对灰度信息。但实际场景中光照往往是非均匀的,人脸一侧亮一侧暗。处理办法是在 MB_LBP 直方图归一化基础上,再做一次直方图均衡化或局部对比度归一化。另一种做法是把人脸图像划分成多个环形区域,对每个区域分别做灰度归一化,消除人脸两侧的光照梯度影响。这些改进方向在文章末尾提到了分块大小的讨论,但归一化策略同样值得关注。

5.4 计算效率对比与部署建议

原始像素 PCA 需要对 92×112=10304 维向量做协方差计算,而 MB_LBP 特征经过 PCA 降维后仅保留几十个维度,后续每次识别只涉及一次投影和一次 SVM 决策,计算量低一个数量级。如果部署到树莓派或移动端,建议进一步精简:用积分图加速 MB_LBP 的块均值计算,将每个子区域的直方图合并为统一编码映射表,减少循环次数。实际工程中还可以把人脸检测和人脸识别串联,在检测阶段用 Haar cascade 或 OpenCV 的 DNN 人脸检测器定位人脸,再裁剪送入 MB_LBP+PCA 流水线,整体帧率在树莓派 4 上可以达到每秒 8 到 12 帧。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询