OpenCV 实现实时人脸检测

本文将从、核心原理、代码实现、功能优化四个维度,手把手教你实现基于 OpenCV+LBPH 的实时人脸检测,并解决中文标注显示的痛点,最终实现摄像头实时识别人脸并显示中文姓名的效果。

一、前置准备

  • 人脸样本图片:准备待识别人员的人脸照片,建议为灰度图 / 彩色图均可(代码会自动转灰度)、正面人脸、光照均匀,每个人员准备多张(2-5 张)不同角度 / 轻微表情的样本,命名如 1.jpg、2.jpg(人员 A),1.png、2.png(人员 B),放在代码同目录下;

  • Haar 级联分类器配置文件:下载haarcascade_frontalface_default.xml(OpenCV 官方人脸检测分类器),放在代码同目录下,可从OpenCV 官方仓库获取;

  • 中文字体文件:Windows 系统可直接使用系统自带字体,如黑体(simhei.ttf),路径默认为C:/Windows/Fonts/simhei.ttf;Linux/Mac 系统需自行指定中文字体路径(如思源黑体)。

二、核心原理详解

  1. 人脸检测:Haar 级联分类器

Haar 级联分类器是基于Adaboost 算法的特征分类器,通过提取人脸的灰度特征(如眼睛比脸颊暗、鼻梁比两侧亮),构建多层级的分类器,快速从图像中筛选出人脸区域。

  • 优势:检测速度快、轻量,无需 GPU,适合实时视频流处理;

  • 核心参数:scaleFactor(图像缩放比例)、minNeighbors(候选矩形的邻域阈值)、minSize(最小检测人脸尺寸),参数调优直接影响检测精度与速度。

  1. 人脸识别:LBPH 局部二值模式直方图

LBPH 是 OpenCV 内置的三大人脸识别算法(EigenFace、FisherFace、LBPH)中最实用的一种,专为灰度图设计,无需对人脸进行对齐 / 归一化预处理,对光照、轻微姿态变化鲁棒性强。

  • 核心原理:对人脸灰度图的每个像素,与周围 8 个像素比较生成二值码,统计局部区域的二值模式直方图,通过对比待识别人脸与训练样本的直方图相似度,判断身份;

  • 关键参数:threshold(识别阈值),置信度(匹配值)越小表示匹配度越高,超过阈值则判定为 "无法识别",本文设置阈值为 120(可根据样本情况调整);

  • 训练逻辑:将每个人员的多张人脸样本标注统一标签(如 0、1),通过train方法训练模型,模型会学习每个标签对应的人脸特征。

  1. OpenCV 中文绘制解决方案

OpenCV 的cv2.putText函数仅支持英文字符,无法直接绘制中文,核心解决思路是格式转换 + PIL 绘制:

  1. 将 OpenCV 的 BGR 格式图像转换为 PIL 的 RGB 格式(两者色彩通道顺序相反);

  2. 通过 PIL 的ImageFont加载中文字体,ImageDraw绘制中文文本;

  3. 将绘制完成的 PIL 图像转换回 OpenCV 的 BGR 格式,完成中文标注。

三、完整代码实现

1. 库导入

python 复制代码
import cv2  # 计算机视觉核心:检测、识别、视频采集、绘图
import numpy as np  # 图像数组处理、格式转换
from PIL import Image, ImageDraw, ImageFont  # 解决中文绘制问题

2. 全局参数配置

将易修改的参数集中配置,便于后续调试与扩展,包括人脸样本、标签映射、分类器路径、字体路径等。

python 复制代码
# 1. 加载人脸训练样本(灰度图模式,cv2.IMREAD_GRAYSCALE)
images = []
images.append(cv2.imread('1.jpg', cv2.IMREAD_GRAYSCALE))
images.append(cv2.imread('2.jpg', cv2.IMREAD_GRAYSCALE))
images.append(cv2.imread('1.png', cv2.IMREAD_GRAYSCALE))
images.append(cv2.imread('2.png', cv2.IMREAD_GRAYSCALE))

# 2. 加载Haar人脸检测分类器
faceCascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')

# 3. 样本标签:相同人员标注相同标签(0/1),与样本列表一一对应
labels = [0, 0, 1, 1]
# 4. 标签-姓名映射字典:-1为无法识别(超过阈值)
dic = {0: '林园昕', 1: '赵丽颖', -1: '无法识别'}

# 5. 中文字体路径(Windows黑体,根据系统调整)
FONT_PATH = "C:/Windows/Fonts/simhei.ttf"

注意 :样本列表images与标签列表labels的索引必须一一对应,否则训练模型会出现身份错乱

3.OpenCV 中文绘制函数

单独封装中文绘制函数,提高代码复用性,函数包含完整的参数说明,支持自定义字体大小、颜色、绘制位置。

python 复制代码
def cv2_draw_chinese(img, text, pos, font_path, font_size=20, color=(0, 0, 255)):
    # 步骤1:OpenCV BGR → PIL RGB(色彩通道转换)
    img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    pil_img = Image.fromarray(img_rgb)

    # 步骤2:创建PIL绘图对象,加载中文字体(必须指定大小,否则报错)
    draw = ImageDraw.Draw(pil_img)
    font = ImageFont.truetype(font_path, font_size, encoding="utf-8")

    # 步骤3:绘制中文(Pillow颜色为RGB,需转换OpenCV的BGR)
    draw.text(pos, text, fill=(color[2], color[1], color[0]), font=font)

    # 步骤4:PIL RGB → OpenCV BGR(转换回原格式)
    img_bgr = cv2.cvtColor(np.array(pil_img), cv2.COLOR_RGB2BGR)
    return img_bgr

注意:PIL 的颜色通道是 RGB,而 OpenCV 是 BGR,绘制时必须进行通道转换,否则颜色会出现错乱(如红色变成蓝色)。

4. 模型初始化与训练:LBPH 人脸识别模型

初始化 OpenCV 的 LBPH 人脸识别模型,设置识别阈值,并用准备好的人脸样本与标签训练模型,训练完成后即可用于实时识别。

python 复制代码
# 初始化LBPH人脸识别模型,设置识别阈值为120
recognizer = cv2.face.LBPHFaceRecognizer_create(threshold=120)
recognizer.train(images, np.array(labels))

5. 摄像头实时人脸检测与识别

实现视频帧采集、人脸检测、身份识别、绘图标注、快捷键退出的完整逻辑。

python 复制代码
cap=cv2.VideoCapture(0)

while True:
    ret,img=cap.read()#读取每一帧的画面
    if ret is None:
        break
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    faces = faceCascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=8, minSize=(7, 7))
    for (x, y, w, h) in faces:
        # 截取人脸区域(灰度图,用于识别)
        face_roi = gray[y:y + h, x:x + w]
        # 人脸识别:返回标签(label)和置信度(confidence)
        # 置信度越小,匹配度越高;超过阈值则返回标签-1
        label, confidence = recognizer.predict(face_roi)
        # 在彩色帧上绘制人脸矩形框(红色,线宽2)
        cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2)
        # 在人脸上方绘制识别结果(红色,字体大小0.9,线宽2)
        # cv2.putText(img, dic[label], (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 0, 255), 2)
        img = cv2_draw_chinese(
            img=img,
            text=dic[label],  # 你的中文字符(直接传字典值即可)
            pos=(x, y-20),  # 原绘制坐标
            font_path=FONT_PATH,
            font_size=22,  # 视觉效果匹配原cv2.putText的0.9
            color=(0, 0, 255)  # 原红色,保持一致
        )
    cv2.imshow('',img)
    key = cv2.waitKey(10)
    if key == 27:
        break
相关推荐
zhangfeng11332 小时前
大模型微调主要框架 Firefly vs LLaMA Factory 全方位对比表
人工智能·语言模型·开源·llama
cyyt2 小时前
深度学习周报(1.26~2.1)
人工智能·深度学习
YOLO视觉与编程2 小时前
yolo26目标检测可视化界面系统源码
人工智能·目标检测·计算机视觉
你大爷的,这都没注册了2 小时前
配置阿里百炼云平台的api_key
人工智能
Faker66363aaa2 小时前
青香蕉尺寸分类与检测:从小尺寸香蕉手识别到模型优化_cascade-rcnn_hrnetv2p-w40-20e_coco
人工智能·分类·数据挖掘
shangjian0072 小时前
AI-大语言模型LLM-模型微调8-进阶操作
人工智能·深度学习·语言模型
xindoo2 小时前
我用AI写了部小说,这里是整个过程
人工智能
传说故事2 小时前
【论文自动阅读】快速视频生成的过渡匹配蒸馏
人工智能·视频生成
OpenMiniServer2 小时前
石化能源文明 vs 电气化能源文明
大数据·人工智能·能源