当前位置: 首页 > news >正文

OpenCV:人脸识别实战,3 种算法(LBPH/EigenFaces/FisherFaces)代码详解

目录

一、前置知识:环境搭建与核心概念

1.1 环境配置(关键版本)

1.2 人脸识别核心流程

二、算法原理与代码实战

2.1 LBPH 算法:抗光照 / 旋转,最实用的传统算法

2.2 EigenFaces 算法:基于 PCA 降维,适合小数据集

2.3 FisherFaces 算法:基于 LDA,类间区分度更高

三、三种算法对比与选型建议

四、常见问题与解决方案

五、扩展:从单张预测到实时摄像头识别


在计算机视觉领域,人脸识别是最经典且实用的技术之一。OpenCV 提供了 LBPH、EigenFaces、FisherFaces 三种成熟的人脸识别算法,无需复杂的深度学习框架,仅用传统机器学习就能实现高效人脸匹配。


一、前置知识:环境搭建与核心概念

在开始代码实战前,需先完成环境配置,并理解人脸识别的基本流程。

1.1 环境配置(关键版本)

OpenCV 的 face 模块在高版本中可能存在兼容性问题,推荐使用以下稳定版本:

# 安装核心库
pip install opencv-python==3.4.18.65
# 安装包含face模块的扩展库
pip install opencv-contrib-python==3.4.18.65
# 安装图像处理辅助库(用于中文显示)
pip install pillow numpy

1.2 人脸识别核心流程

所有算法的核心逻辑一致,分为 4 步:

  • 数据准备:收集同一人多张人脸图像(用于训练)和待识别人脸图像;
  • 模型训练:用训练集图像和对应标签(如 “0 - 李云龙”“1 - 赵刚”)训练识别器;
  • 预测匹配:将待识别人脸输入模型,计算匹配置信度;
  • 结果输出:根据置信度判断是否识别成功,输出对应人物名称。

二、算法原理与代码实战

下面分别讲解 LBPH、EigenFaces、FisherFaces 三种算法的原理、完整代码及关键参数说明,所有代码均可直接运行(需替换自己的人脸图像路径)。

2.1 LBPH 算法:抗光照 / 旋转,最实用的传统算法

原理核心

LBPH(局部二值模式直方图)通过 “像素对比编码 + 分区域统计” 实现鲁棒识别:

  • 像素编码:以每个像素为中心,对比周围 8 个像素灰度值,大于中心记 “1”,否则记 “0”,生成 8 位二进制码(如 00110101);
  • 分块统计:将编码后的图像分成 8×8 网格,统计每个网格的直方图,最终拼接成全局特征;
  • 匹配逻辑:通过对比两张人脸的特征直方图差异(置信度)判断是否为同一人,置信度<80 为可靠匹配

完整代码(带详细注释)

import cv2
import numpy as np# -------------------------- 1. 准备训练数据 --------------------------
# 存储训练图像(灰度图,减少计算量)
train_images = []
# 读取同一人多张图像(替换为你的图像路径)
train_images.append(cv2.imread('lyl1.png', cv2.IMREAD_GRAYSCALE))  # 李云龙1
train_images.append(cv2.imread('lyl2.png', cv2.IMREAD_GRAYSCALE))  # 李云龙2
train_images.append(cv2.imread('zg1.png', cv2.IMREAD_GRAYSCALE))   # 赵刚1
train_images.append(cv2.imread('zg2.png', cv2.IMREAD_GRAYSCALE))   # 赵刚2# 训练标签:与图像顺序对应(0=李云龙,1=赵刚)
train_labels = [0, 0, 1, 1]# 标签映射字典:将数字标签转为人名,-1表示无法识别
label_dict = {0: '李云龙', 1: '赵刚', -1: '无法识别'}# 待识别人脸(同样转为灰度图)
predict_image = cv2.imread('lyl_test.png', cv2.IMREAD_GRAYSCALE)# -------------------------- 2. 创建并训练LBPH识别器 --------------------------
# threshold=80:置信度阈值,超过80则判定为“无法识别”
recognizer = cv2.face.LBPHFaceRecognizer_create(threshold=80)
# 训练模型:输入训练图像和标签(标签需转为numpy数组)
recognizer.train(train_images, np.array(train_labels))# -------------------------- 3. 预测待识别人脸 --------------------------
# 返回两个结果:label=预测标签,confidence=置信度(越小匹配度越高)
predict_label, confidence = recognizer.predict(predict_image)# -------------------------- 4. 输出结果 --------------------------
print(f'识别结果:{label_dict[predict_label]}')
print(f'置信度(越小越准):{confidence:.2f}')# (可选)在原图上绘制识别结果(需先将灰度图转为彩色图)
predict_image_color = cv2.cvtColor(predict_image, cv2.COLOR_GRAY2BGR)
# 绘制文字:参数依次为“图像、文字、位置、字体、字号、颜色、线宽”
cv2.putText(predict_image_color, label_dict[predict_label], (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
# 显示结果窗口
cv2.imshow('LBPH人脸识别结果', predict_image_color)
# 等待按键关闭窗口(0表示无限等待)
cv2.waitKey(0)
# 释放窗口资源
cv2.destroyAllWindows()

2.2 EigenFaces 算法:基于 PCA 降维,适合小数据集

原理核心

EigenFaces(特征脸)基于 PCA(主成分分析)降维,保留人脸最关键的 “特征脸” 信息:

  • 数据降维:将所有训练人脸图像(如 120×180 像素 = 21600 维)投影到低维空间(如 80 维),保留 90% 以上的关键信息;
  • 特征脸生成:降维后得到的主成分就是 “特征脸”,普通人脸可看作特征脸的线性组合;
  • 匹配逻辑:计算待识别人脸与训练集在低维空间的距离,置信度<5000 为可靠匹配(阈值比 LBPH 大,因维度差异)。

关键注意点

EigenFaces 对图像尺寸敏感,所有训练图和待识别图必须统一尺寸(如 120×180),否则会报错。

完整代码(带详细注释)

import cv2
import numpy as np
from PIL import Image, ImageDraw, ImageFont  # 用于显示中文(OpenCV默认不支持中文)# -------------------------- 1. 准备训练数据(统一尺寸) --------------------------
train_images = []# 读取图像→转为灰度图→缩放为120×180(必须统一尺寸)
def preprocess_image(img_path):img = cv2.imread(img_path, 0)  # 0=灰度模式img_resized = cv2.resize(img, (120, 180))  # 统一尺寸:宽120,高180return img_resized# 加载训练图像(替换为你的路径)
train_images.append(preprocess_image('lyl1.png'))  # 李云龙1
train_images.append(preprocess_image('lyl2.png'))  # 李云龙2
train_images.append(preprocess_image('zg1.png'))   # 赵刚1
train_images.append(preprocess_image('zg2.png'))   # 赵刚2# 训练标签和映射字典
train_labels = [0, 0, 1, 1]
label_dict = {0: '李云龙', 1: '赵刚', -1: '无法识别'}# 预处理待识别人脸(同样统一尺寸)
predict_image = preprocess_image('zg_test.png')# -------------------------- 2. 创建并训练EigenFaces识别器 --------------------------
# num_components=80:保留80个主成分(特征脸),threshold=7000:置信度阈值
recognizer = cv2.face.EigenFaceRecognizer_create(num_components=80, threshold=7000)
recognizer.train(train_images, np.array(train_labels))# -------------------------- 3. 预测与结果输出 --------------------------
predict_label, confidence = recognizer.predict(predict_image)
print(f'识别结果:{label_dict[predict_label]}')
print(f'置信度(<5000可靠):{confidence:.2f}')# (可选)显示带中文的结果图(用PIL处理中文)
# 1. 将OpenCV图像转为PIL图像(需先转灰度为彩色)
predict_image_bgr = cv2.cvtColor(predict_image, cv2.COLOR_GRAY2BGR)
predict_image_rgb = cv2.cvtColor(predict_image_bgr, cv2.COLOR_BGR2RGB)
pil_img = Image.fromarray(predict_image_rgb)# 2. 绘制中文(需指定中文字体路径,Windows默认路径如下)
draw = ImageDraw.Draw(pil_img)
try:# 加载Windows自带黑体(路径根据系统调整)font = ImageFont.truetype("C:/Windows/Fonts/simhei.ttf", 24)
except IOError:# 若找不到中文字体,用英文字体兜底font = ImageFont.truetype("arial.ttf", 24)print("警告:未找到中文字体,将显示英文")# 绘制中文文字:位置(10,30),红色(255,0,0)
draw.text((10, 30), label_dict[predict_label], font=font, fill=(255, 0, 0))# 3. 转回OpenCV格式并显示
result_img = cv2.cvtColor(np.array(pil_img), cv2.COLOR_RGB2BGR)
cv2.imshow('EigenFaces人脸识别结果', result_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

2.3 FisherFaces 算法:基于 LDA,类间区分度更高

原理核心

FisherFaces 基于 LDA(线性判别分析),相比 EigenFaces 更关注 “类间差异”:

  • 优化目标:降维时不仅保留信息,还最大化不同类别(如李云龙 vs 赵刚)的距离,最小化同类内部的距离;
  • 适用场景:当训练集中不同人的人脸差异较小时,FisherFaces 识别准确率更高;
  • 匹配逻辑:置信度判断与 EigenFaces 类似,阈值建议设为 5000,低于则匹配成功。

完整代码(带详细注释)

import cv2
import numpy as np
from PIL import Image, ImageDraw, ImageFont# -------------------------- 1. 工具函数:预处理+中文绘制 --------------------------
# 统一图像尺寸并转为灰度图
def preprocess_image(img_path, size=(120, 180)):img = cv2.imread(img_path, 0)return cv2.resize(img, size)# 在图像上绘制中文
def add_chinese_text(img, text, pos=(10, 30), color=(255, 0, 0), font_size=24):# OpenCV→PILimg_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)pil_img = Image.fromarray(img_rgb)# 绘制中文draw = ImageDraw.Draw(pil_img)try:font = ImageFont.truetype("C:/Windows/Fonts/simhei.ttf", font_size)except IOError:font = ImageFont.truetype("arial.ttf", font_size)draw.text(pos, text, font=font, fill=color)# PIL→OpenCVreturn cv2.cvtColor(np.array(pil_img), cv2.COLOR_RGB2BGR)# -------------------------- 2. 数据准备 --------------------------
train_images = [preprocess_image('lyl1.png'),preprocess_image('lyl2.png'),preprocess_image('zg1.png'),preprocess_image('zg2.png')
]
train_labels = [0, 0, 1, 1]
label_dict = {0: '李云龙', 1: '赵刚', -1: '无法识别'}
predict_image = preprocess_image('lyl_test2.png')# -------------------------- 3. 训练与预测 --------------------------
# threshold=5000:FisherFaces阈值建议设为5000
recognizer = cv2.face.FisherFaceRecognizer_create(threshold=5000)
recognizer.train(train_images, np.array(train_labels))
predict_label, confidence = recognizer.predict(predict_image)# -------------------------- 4. 结果展示 --------------------------
print(f'识别结果:{label_dict[predict_label]}')
print(f'置信度(<5000可靠):{confidence:.2f}')# 显示带中文的结果图
predict_image_bgr = cv2.cvtColor(predict_image, cv2.COLOR_GRAY2BGR)
result_img = add_chinese_text(predict_image_bgr, label_dict[predict_label])
cv2.imshow('FisherFaces人脸识别结果', result_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

三、三种算法对比与选型建议

算法核心思想优势劣势适用场景
LBPH局部二值模式抗光照、旋转、缩放,无需统一尺寸对遮挡敏感实时监控、门禁识别
EigenFacesPCA 降维计算快,适合小数据集对光照敏感,需统一尺寸静态人脸库匹配
FisherFacesLDA 类间优化类间区分度高,准确率高需统一尺寸,对噪声敏感多人脸小样本精准识别

选型口诀

  • 实时场景选 LBPH(抗干扰强);
  • 小样本静态匹配选 EigenFaces(快);
  • 多人精准区分选 FisherFaces(准)。

四、常见问题与解决方案

1.报错 “face 模块不存在”:原因:安装的 opencv-python 不含 face 模块。解决:卸载后重新安装 opencv-contrib-python==3.4.18.65

2.中文显示乱码:原因:OpenCV 不支持中文字体。解决:用 PIL 库绘制中文,参考代码中的 add_chinese_text 函数。

3.识别准确率低:原因:训练样本少、图像光照差异大、未统一尺寸(Eigen/Fisher)。解决:

  • 每人至少提供 2-5 张不同角度 / 光照的图像;
  • 对图像进行灰度归一化(如 cv2.normalize);
  • Eigen/Fisher 算法严格统一图像尺寸。

五、扩展:从单张预测到实时摄像头识别

如果想实现实时摄像头人脸识别,只需在上述代码基础上添加 “摄像头读取” 循环,核心逻辑如下:

# 加载人脸检测器(OpenCV自带Haar级联分类器)
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')# 打开摄像头(0表示默认摄像头)
cap = cv2.VideoCapture(0)while True:# 读取一帧图像ret, frame = cap.read()if not ret:break  # 摄像头读取失败则退出# 检测人脸(灰度图检测更高效)gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)faces = face_cascade.detectMultiScale(gray, 1.1, 4)# 对每个检测到的人脸进行识别for (x, y, w, h) in faces:# 裁剪人脸区域并预处理face_roi = gray[y:y+h, x:x+w]face_roi = cv2.resize(face_roi, (120, 180))  # 统一尺寸(Eigen/Fisher需加)# 预测predict_label, confidence = recognizer.predict(face_roi)result_text = f'{label_dict[predict_label]}({confidence:.0f})'# 绘制人脸框和结果cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2)  # 绿色框frame = add_chinese_text(frame, result_text, (x, y-30))  # 文字在框上方# 显示实时画面cv2.imshow('实时人脸识别', frame)# 按ESC键退出(27是ESC的ASCII码)if cv2.waitKey(1) == 27:break# 释放资源
cap.release()
cv2.destroyAllWindows()
http://www.dtcms.com/a/395025.html

相关文章:

  • OneSignal PHP SDK v2 版本实现指南
  • Dockerfile构建镜像以及网络
  • 鸿蒙音乐播放器基础实现
  • Vue3》》Vite》》文件路由 vite-plugin-pages、布局系统 vite-plugin-vue-layouts
  • 深入解析 MySQL MVCC:高并发背后的数据时光机
  • 汽车冷却系统的冷却水管介绍
  • 基础架构设计
  • 从分散到统一:基于Vue3的地图模块重构之路
  • JVM实际内存占用
  • Spark SQL 桶抽样(Bucket Sampling)
  • 常见的【垃圾收集算法】
  • 如何解决 pip install 安装报错 ModuleNotFoundError: No module named ‘django’ 问题
  • jvm之【垃圾回收器】
  • Tomcat基础知识
  • Will、NGC游戏模拟器 Dolphin海豚模拟器2509最新版 电脑+安卓版 附游戏
  • ELK企业级日志分析系统详解:从入门到部署实践
  • 2025年Spring Security OAuth2实现github授权码模式登录
  • Kafka面试精讲 Day 22:Kafka Streams流处理
  • ELK大总结20250922
  • 基于Hadoop生态的汽车全生命周期数据分析与可视化平台-基于Python+Vue的二手车智能估价与市场分析系统
  • 基于TV模型利用Bregman分裂算法迭代对图像进行滤波和复原处理
  • 利用 Perfmon.exe 与 UMDH 组合分析 Windows 程序内存消耗
  • hello算法笔记 02
  • 二级域名解析与配置
  • 如何学习国库会计知识
  • 【读论文】压缩双梳光谱技术
  • Spark Structured Streaming端到端延迟优化实践指南
  • 【.NET实现输入法切换的多种方法解析】,第566篇
  • 性能测试-jmeter13-性能资源指标监控
  • 基于华为openEuler系统安装PDF查看器PdfDing