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

系列直达

相关推荐
Hi202402172 小时前
Vortex CUDA 生态适配:让 CUDA C、CUTLASS 与 Triton 在 RISC-V GPGPU 上运行
人工智能·risc-v·gpgpu
龙腾AI白云5 小时前
AI检索增强生成(RAG):解决大模型幻觉的核心落地技术
数据库·人工智能·机器学习·知识图谱
tiankongdeyige5 小时前
游戏战斗系统学习第2篇:有限状态机 (FSM)
学习·游戏·typescript
云票5 小时前
企业对接AI合同审查系统的工程实践
人工智能
admin and root6 小时前
「AI安全篇」实战AntiDebug自动化JS逆向加解密MCP
javascript·人工智能·网络安全·自动化·漏洞挖掘·cnvd·src赏金
智能RPA6 小时前
智能体自动化平台与主数据管理平台(MDM)对比评测
人工智能·自动化·agent·rpa
跨境小彭6 小时前
Temu拉美站点铺货实操复盘:手动复制痛点与批量自动化解决方案
服务器·人工智能·搜索引擎·自动化·temu电商运营
封印师请假去地球钓鱼6 小时前
边解边变的问题:从“决策依赖“一词出发
人工智能·算法
AI搅拌机7 小时前
ComfyUI管理大师:安全稳定升级+切换指定版本!
人工智能
浅安的邂逅7 小时前
20929-OpenAI 一天踩三脚急刹:暂停前沿训练、叫停 Astra、披露越权访问澳政府网站
人工智能·大模型·ai编程·行业动态·ai日报