OpenCV学习:人脸识别

OpenCV学习:人脸识别

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

目录

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

一、人脸识别概述

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.pngpyy_2.pngpyy_3.png
吴京 1 wj_1.pngwj_2.pngwj_3.png
杨洋 2 yy_1.pngyy_2.pngyy_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

系列直达

相关推荐
凌晨1681 小时前
OpenCV(十一)人脸识别三大算法LBPH、EigenFace、FisherFace
人工智能·opencv·算法
xqqxqxxq1 小时前
AI Agent学习:第四章小结及八道思考题(李博杰《深入理解 AI Agent》第四章观后总结)
大数据·人工智能·学习
YOLO数据集集合1 小时前
反无人机禁飞识别无人机检测数据集 | 反无人机 禁飞识别 低空安防 目标检测 无人机检测10756期
人工智能·目标检测·无人机
Willliam_william1 小时前
QEMU学习之路(13)— 在BusyBox中安装pciutils
学习
yyk333241 小时前
OpenCV中的LBPH人脸识别
人工智能·opencv·计算机视觉
天天代码码天天1 小时前
把 PP-OCR 塞进一个纯 C Runtime:从 Tiny 到 Medium,再到单文件 HTML OCR
人工智能
xsd202411181 小时前
Stremio-WebStremio:开源流媒体自由聚合平台
人工智能
Aloudata1 小时前
语义治理 vs 知识治理:AI 数据分析需要业务知识库还是可执行语义层
大数据·人工智能·数据分析·data agent·语义层
阿黎梨梨1 小时前
LangGraph 核心机制:从状态管理到人机协同
人工智能·langchain