OpenCV学习:人脸识别

OpenCV学习:人脸识别

前言 :上一篇我们学习了基于 Haar 级联分类器的人脸检测与微笑识别。本篇我们将更进一步------从"检测出人脸"升级为"识别出这个人是谁"。人脸识别技术广泛应用于手机解锁、门禁系统、支付验证等场景。OpenCV 的 face 模块提供了三种主流的人脸识别算法:LBPH 、EigenFace 和 FisherFace。本篇我们将从数据准备开始,一步步实现完整的实时人脸识别系统。

目录

  • 一、人脸识别概述
  • 二、三种人脸识别算法
  • 三、数据准备与预处理
  • 四、模型训练与预测
  • 五、实时人脸识别
  • 六、总结

一、人脸识别概述

1.1 人脸检测 vs 人脸识别

概念 说明
人脸检测 在图像中找到人脸的位置(画框),不关心是谁
人脸识别 判断检测到的人脸具体是哪个人

简单来说:人脸检测是"找到脸",人脸识别是"认出是谁"。

1.2 人脸识别的基本流程

复制代码
采集人脸样本 → 预处理 → 训练模型 → 实时检测人脸 → 识别身份

二、三种人脸识别算法

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

算法 原理 特点
LBPH 局部二值模式直方图 最常用,对光照和表情变化鲁棒
EigenFace PCA 降维 + 特征脸 最早的主流方法,对光照敏感
FisherFace LDA 降维 + 线性判别 比 EigenFace 更鲁棒,区分能力更强

2.1 LBPH(局部二值模式直方图)

LBPH 是目前最常用的人脸识别方法。它通过计算图像的局部二值模式(LBP) 直方图来描述人脸纹理特征,对光照变化、表情变化都有较好的鲁棒性。

python 复制代码
recognizer = cv2.face.LBPHFaceRecognizer_create(threshold=10000)

2.2 EigenFace(特征脸)

EigenFace 是最早的人脸识别算法之一,其核心思想是主成分分析(PCA)。它将人脸图像降维到低维空间,在这个空间中不同的"特征脸"构成了人脸空间的基础。

python 复制代码
recognizer = cv2.face.EigenFaceRecognizer_create(threshold=10000)

2.3 FisherFace(线性判别分析)

FisherFace 在 EigenFace 的基础上引入了线性判别分析(LDA)。它不仅考虑降维,还考虑了不同类别之间的区分度,使得同类样本更紧凑,不同类样本更分散。

python 复制代码
recognizer = cv2.face.FisherFaceRecognizer_create(threshold=10000)

2.4 三种算法对比

对比维度 LBPH EigenFace FisherFace
核心原理 LBP 纹理直方图 PCA 降维 LDA 降维
对光照敏感度 鲁棒 敏感 中等
对表情变化 鲁棒 敏感 中等
训练速度 快 快 中等
识别精度 最佳 一般 较好
适用场景 大多数场景 可控光照环境 一般环境

2.5 三种算法选择建议

场景 推荐算法
光照变化大、表情丰富 LBPH(首选)
光照可控环境 EigenFace
一般环境,需要区分能力 FisherFace

三、数据准备与预处理

3.1 数据集说明

本案例使用三位人物的人脸样本,每人 3 张图片,共 9 张训练样本。图片按以下规则命名:

类别 标签 样本文件
彭于晏 0 pyy_1.png、pyy_2.png、pyy_3.png
吴京 1 wj_1.png、wj_2.png、wj_3.png
杨洋 2 yy_1.png、yy_2.png、yy_3.png

3.2 数据加载与预处理

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)


# ====================加载训练数据====================
images = []
labels = []
IMG_SIZE = (120, 180)

# 彭于晏 (标签0)
img = cv2.imread(r".\faces\pyy_1.png", 0)
img = cv2.resize(img, IMG_SIZE)
images.append(img)
labels.append(0)

img = cv2.imread(r".\faces\pyy_2.png", 0)
img = cv2.resize(img, IMG_SIZE)
images.append(img)
labels.append(0)

img = cv2.imread(r".\faces\pyy_3.png", 0)
img = cv2.resize(img, IMG_SIZE)
images.append(img)
labels.append(0)

# 吴京 (标签1)
img = cv2.imread(r".\faces\wj_1.png", 0)
img = cv2.resize(img, IMG_SIZE)
images.append(img)
labels.append(1)

img = cv2.imread(r".\faces\wj_2.png", 0)
img = cv2.resize(img, IMG_SIZE)
images.append(img)
labels.append(1)

img = cv2.imread(r".\faces\wj_3.png", 0)
img = cv2.resize(img, IMG_SIZE)
images.append(img)
labels.append(1)

# 杨洋 (标签2)
img = cv2.imread(r".\faces\yy_1.png", 0)
img = cv2.resize(img, IMG_SIZE)
images.append(img)
labels.append(2)

img = cv2.imread(r".\faces\yy_2.png", 0)
img = cv2.resize(img, IMG_SIZE)
images.append(img)
labels.append(2)

img = cv2.imread(r".\faces\yy_3.png", 0)
img = cv2.resize(img, IMG_SIZE)
images.append(img)
labels.append(2)

labels = np.array(labels)
print(f"加载 {len(images)} 张训练样本")

四、模型训练与预测

4.1 完整代码

python 复制代码
# ====================训练 LBPH 模型====================
recognizer = cv2.face.LBPHFaceRecognizer_create(threshold=10000)
recognizer.train(images, labels)

# ====================预测测试====================
name_dict = {0: "彭于晏", 1: "吴京", 2: "杨洋", -1: "无法识别"}

test_img = cv2.imread(r".\faces\wj.png", 0)
test_img = cv2.resize(test_img, IMG_SIZE)

label, confidence = recognizer.predict(test_img)
print(f"识别结果: {name_dict[label]}")
print(f"置信度: {confidence}")

# ====================结果展示====================
result_img = cv2.imread(r".\faces\wj.png")
result_img = cv2AddChineseText(result_img, name_dict[label], (10, 30), textColor=(0, 255, 0), textSize=30)
cv2.imshow("result", result_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

4.2 置信度说明

置信度(confidence)表示识别结果的可靠程度,数值越小表示越可靠。不同算法的置信度范围不同,需要根据实际情况设置合理的阈值:

算法 置信度特点
LBPH 通常小于 100,越小越匹配
EigenFace 通常小于 10000,越小越匹配
FisherFace 通常小于 5000,越小越匹配

4.3 三种算法切换

在代码中替换对应的识别器创建语句即可切换算法:

python 复制代码
# LBPH(推荐)
recognizer = cv2.face.LBPHFaceRecognizer_create(threshold=10000)

# EigenFace
recognizer = cv2.face.EigenFaceRecognizer_create(threshold=10000)

# FisherFace
recognizer = cv2.face.FisherFaceRecognizer_create(threshold=10000)

五、实时人脸识别

将人脸检测与识别结合起来,实现摄像头实时人脸识别。

5.1 完整代码

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

# ====================中文绘制函数====================
def cv2AddChineseText(img, text, position, textColor=(0, 255, 0), textSize=25):
    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)


# ====================加载训练数据====================
images = []
labels = []
IMG_SIZE = (120, 180)

# 彭于晏 (标签0)
img = cv2.imread(r".\faces\pyy_1.png", 0)
img = cv2.resize(img, IMG_SIZE)
images.append(img)
labels.append(0)
img = cv2.imread(r".\faces\pyy_2.png", 0)
img = cv2.resize(img, IMG_SIZE)
images.append(img)
labels.append(0)
img = cv2.imread(r".\faces\pyy_3.png", 0)
img = cv2.resize(img, IMG_SIZE)
images.append(img)
labels.append(0)

# 吴京 (标签1)
img = cv2.imread(r".\faces\wj_1.png", 0)
img = cv2.resize(img, IMG_SIZE)
images.append(img)
labels.append(1)
img = cv2.imread(r".\faces\wj_2.png", 0)
img = cv2.resize(img, IMG_SIZE)
images.append(img)
labels.append(1)
img = cv2.imread(r".\faces\wj_3.png", 0)
img = cv2.resize(img, IMG_SIZE)
images.append(img)
labels.append(1)

# 杨洋 (标签2)
img = cv2.imread(r".\faces\yy_1.png", 0)
img = cv2.resize(img, IMG_SIZE)
images.append(img)
labels.append(2)
img = cv2.imread(r".\faces\yy_2.png", 0)
img = cv2.resize(img, IMG_SIZE)
images.append(img)
labels.append(2)
img = cv2.imread(r".\faces\yy_3.png", 0)
img = cv2.resize(img, IMG_SIZE)
images.append(img)
labels.append(2)

labels = np.array(labels)
print(f"加载样本总数:{len(images)}")

# ====================训练 LBPH 模型====================
recognizer = cv2.face.LBPHFaceRecognizer_create(threshold=10000)
recognizer.train(images, labels)

# ====================配置====================
name_dict = {0: "彭于晏", 1: "吴京", 2: "杨洋", -1: "无法识别"}
CONFIDENCE_THRESHOLD = 100

# ====================人脸检测====================
face_cascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")

# ====================摄像头实时识别====================
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, scaleFactor=1.1, minNeighbors=4, minSize=(60, 60))

    for (x, y, w, h) in faces:
        # 绘制人脸框
        cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2)

        # 裁剪并缩放人脸
        face_roi = gray[y:y + h, x:x + w]
        face_roi = cv2.resize(face_roi, IMG_SIZE)

        # 识别
        pred_label, confidence = recognizer.predict(face_roi)

        # 阈值判断
        if confidence > CONFIDENCE_THRESHOLD:
            show_name = name_dict[-1]
        else:
            show_name = name_dict[pred_label]

        # 显示名字
        frame = cv2AddChineseText(frame, show_name, (x, y - 30), textColor=(0, 255, 0), textSize=24)

    cv2.imshow("Face Recognition", frame)

    if cv2.waitKey(1) & 0xFF == 27:
        break

cap.release()
cv2.destroyAllWindows()

5.2 关键逻辑说明

步骤 说明
1. 加载样本 从 faces 文件夹读取三类人脸图片,统一缩放到 120×180
2. 训练模型 使用 LBPH 算法训练人脸识别模型
3. 人脸检测 Haar 级联分类器检测人脸位置
4. 人脸识别 将检测到的人脸缩放后送入模型识别
5. 阈值判断 置信度超过阈值则判定为"无法识别"

六、总结

核心函数速查

函数 用途
cv2.face.LBPHFaceRecognizer_create() 创建 LBPH 识别器(推荐)
cv2.face.EigenFaceRecognizer_create() 创建 EigenFace 识别器
cv2.face.FisherFaceRecognizer_create() 创建 FisherFace 识别器
recognizer.train(images, labels) 训练模型
recognizer.predict(image) 预测单张人脸,返回 (标签, 置信度)

三种算法选择建议

场景 推荐算法
光照变化大、表情丰富 LBPH(首选)
光照可控环境 EigenFace
一般环境,需要区分能力 FisherFace

注意事项

要点 说明
样本数量 每人至少 5-10 张不同光照、表情的样本
图像尺寸 训练集和预测图像尺寸必须一致
置信度阈值 需要根据实际数据调整,避免误识别
灰度图像 所有算法都要求输入灰度图
中文显示 cv2.putText() 不支持中文,需借助 PIL

系列直达

相关推荐
sell-cloud5 小时前
Prompt Engineering要凉了?Fable 5.5能“猜“意图,但银行正在封杀AI Agent——企业AI的真正护城河是什么
人工智能·prompt
Navicat中国7 小时前
Navicat 18 内置 AI 助手让数据库开发从繁琐操作迈向智能协作
大数据·人工智能·数据库开发
4SAPI7 小时前
多模型请求路由怎么设计?成本、速度和能力如何平衡
人工智能·python·gateway·php
魔乐社区7 小时前
翼芯・智算测试与适配优化专区,让国产算力“选得准、跑得通、用得好“
人工智能·开源·大模型
XCDoris9 小时前
郴州logo设计机构
大数据·人工智能·python
Goboy9 小时前
一个人带三个Agent,我用全新TRAE从0到1搭了个资讯周刊站
人工智能·trae
俊哥V9 小时前
每日 AI 研究简报 · 2026-10-19
人工智能·ai
AI_AGENT_DEV_AI10 小时前
AI英语教培智能体的开发
人工智能
物联网软硬件开发-轨物科技10 小时前
【技术白皮书】光伏清检一体化机器人系统解决方案技术白皮书
大数据·运维·网络·人工智能·机器人
海宇数据10 小时前
零信任架构实战:基于海宇网上踪迹欺诈行为识别构建自动化信贷资信评估网关
运维·人工智能·架构·自动化