OpenCV人脸识别FisherFaces 算法:从原理到代码


前言

在人脸识别领域,FisherFaces 算法凭借有监督学习的优势,成为经典的判别式方法之一。


一、FisherFaces 算法核心原理

1. 算法思想:最大化类间差异,最小化类内差异

FisherFaces 基于线性判别分析(LDA),与 EigenFaces(PCA)的无监督降维不同,它是有监督学习方法,目标是找到一个投影方向。PCA方法是EigenFaces人脸识别的核心,但是其具有明显的缺点,在操作过程中会损失许多人脸的特征信息。因此在某些特殊的情况下,如果损失的信息刚好是用于分类的关键信息,必然导致结果预测错误。

Fisherfaces采用LDA(Linear Discriminant Analysis,线性判别分析)实现人脸识别。
其基本原理:在低维表示下,首先将训练集样本集投影到一条直线A上,让投影后的点满足:

  • 同类间的点尽可能地靠近,
  • 异类间的点尽可能地远离。
    加粗样式

2. 数学推导

  • 数据准备:假设训练集有(C)个类别(人脸身份),每个类别有 (n_i)张图像,总样本数(N=\sum n_i)
  • 计算类内散度矩阵
    ((S_W)):(S_W = \sum_{c=1}^C \sum_{x \in X_c} (x - \mu_c)(x - \mu_c)^T)((\mu_c)为第(c)类的均值向量)
  • 计算类间散度矩阵
    ((S_B)):(S_B = \sum_{c=1}^C n_c (\mu_c - \mu)(\mu_c - \mu)^T)((\mu)为所有样本的全局均值)
  • 广义特征值分解
    求解广义特征值问题 (S_B w = \lambda S_W w),提取前(d)个最大特征值对应的特征向量,构成投影矩阵(W)。

3. 与 EigenFaces 的核心区别

在这里插入图片描述

二、Python 实战

1. 环境准备

pip install opencv-python numpy matplotlib

依赖库:OpenCV(算法实现)、NumPy(数值计算)、Matplotlib(可视化)

2. 数据集准备

使用经典的ORL 人脸数据集(40 人,每人 10 张图像,尺寸 112×92),需提前解压到项目目录的ORL_faces文件夹。

3. 代码实现与分步解析

数据加载与预处理

import cv2
import numpy as np
import os
from matplotlib import pyplot as plt

4. 加载数据集(含标签)

def load_dataset(path):
    faces = []  # 存储人脸图像向量(一维)
    labels = []  # 存储标签(0~39对应40个人)
    label = 0    # 标签计数器

    # 遍历文件夹(每个子文件夹对应一个人)
    for root, dirs, files in os.walk(path):
        for file in files:
            img_path = os.path.join(root, file)
            # 灰度图读取并转为一维向量(112*92=10304维)
            img = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE)
            faces.append(img.flatten())
            labels.append(label)
        label += 1  # 切换到下一个人的标签
    return np.array(faces), np.array(labels)
  • 关键点:图像需统一尺寸并灰度化,转换为一维向量以便矩阵运算
  • 标签逻辑:每个子文件夹对应一个唯一标签(0 开始递增)

5.训练FisherFaces模型

def train_fisherfaces_model(faces, labels, num_components=39):  # 最大维度为C-1=39
    model = cv2.face.FisherFaceRecognizer_create(
        num_components=num_components,  # 保留的特征数量(不超过C-1)
        threshold=0.0  # 识别阈值(置信度低于该值则认为“未识别”)
    )
    model.train(faces, labels)  # 输入训练数据(样本矩阵,标签数组)
    return model

6.主程序:加载数据并训练

data_path = 'ORL_faces'
faces, labels = load_dataset(data_path)
fisherfaces_model = train_fisherfaces_model(faces, labels)
  • API 说明:cv2.face.FisherFaceRecognizer_create提供参数控制降维维度和识别阈值
  • 维度限制:由于 LDA 最大维度为类别数 - 1(40 人对应 39 维),num_components最大设为 39

7. 预测函数(返回标签和置信度)

def predict_face(model, test_face):
    # 注意:输入需是二维矩阵(n_samples, n_features)
    test_face_2d = test_face.reshape(1, -1)
    predicted_label, confidence = model.predict(test_face_2d)
    return predicted_label, confidence

8.选取第50张图像(属于第5个人,标签4)

test_index = 50
test_face = faces[test_index]
pred_label, conf = predict_face(fisherfaces_model, test_face)

print(f"预测标签:{pred_label},真实标签:{labels[test_index]}")
print(f"置信度(值越小越可靠):{conf:.2f}")
  • 置信度含义:FisherFaces 的置信度是预测时的距离度量值,值越小表示匹配越准确
  • 维度转换:输入模型的测试数据必须是二维矩阵(即使单样本也需 reshape 为 (1, n_features))

9.可视化平均脸和特征脸

def visualize_features(model, face_size=(112, 92)):
    mean_face = model.getMean().reshape(face_size)  # 全局平均脸
    eigenvectors = model.getEigenVectors()  # 获取投影矩阵(特征向量)

    plt.figure(figsize=(12, 6))
    
    # 显示平均脸
    plt.subplot(2, 5, 1)
    plt.imshow(mean_face, cmap='gray')
    plt.title("平均脸")
    
    # 显示前9个特征脸
    for i in range(9):
        eigenface = eigenvectors[i].reshape(face_size)
        plt.subplot(2, 5, i+2)
        plt.imshow(eigenface, cmap='gray')
        plt.title(f"特征脸{i+1}")
    
    plt.show()

visualize_features(fisherfaces_model)
  • 平均脸:所有训练样本的平均值,体现数据集整体特征
  • 特征脸:LDA 提取的判别式特征,可视化呈现对分类最关键的面部变化模式

三、优化技巧与典型问题处理

1. 参数调优关键点

num_components:通常设为类别数 - 1(如 40 人用 39 维),但可通过交叉验证选择最优值(如保留 20~35 维)
threshold:根据业务需求设定识别阈值(如置信度 > 500 时认为 “未知人脸”),需通过测试集确定合理范围

2. 数据增强策略

当训练数据不足时,可对图像进行:
添加高斯噪声、模糊处理
直方图均衡化(提升光照鲁棒性)

3. 常见报错处理

维度不匹配:确保输入模型的图像是一维向量(如 112×92→10304 维),且标签为整数数组
类别数过少:LDA 要求类别数≥2,单类别数据会导致算法失效

四、FisherFaces 的优缺点与适用场景

1. 核心优势

有监督学习:利用标签信息提升分类性能,优于 EigenFaces 等无监督方法
小样本高效:在类别数较多但每类样本少(如每人 3~5 张图像)时表现良好
轻量高效:模型复杂度低,适合嵌入式设备或实时识别场景

2. 局限性

维度限制:最大降维维度为类别数 - 1,当类别数极少时(如 2 类),仅能提取 1 维特征
对光照 / 姿态敏感:未显式处理图像变化因素,复杂场景下需结合预处理增强鲁棒性

3. 典型应用场景

中小规模人脸库的门禁系统(如企业、校园)
视频监控中的简单人脸分类(如员工 / 访客区分)
作为基线算法验证深度学习模型的改进效果

五、总结

FisherFaces 算法是传统人脸识别中 “判别式学习” 的代表,通过引入标签信息弥补了 PCA 的无监督缺陷。尽管在复杂场景下逐渐被深度学习取代,但其简洁的数学原理和轻量的实现方式,依然是理解人脸识别核心逻辑的重要切入点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值