YOLOv5口罩检测完整实战(二):从现成数据集到训练、评估与摄像头识别

前言

在上一篇文章中,我们详细介绍了目标检测的基本概念、YOLO的核心思想以及YOLOv5的网络结构。本文正式进入完整实战阶段------使用一个已经标注好的口罩数据集训练YOLOv5s模型,实现maskno-mask两类目标的检测,并最终在图片和摄像头实时画面上验证模型效果。

真实的目标检测项目往往面临一个核心问题:数据集的目录结构、标签格式、配置文件三者之间必须严格对应,任何一处不匹配都会导致训练失败。本文将从数据集检查开始,逐步完成环境配置、模型训练、结果评估和摄像头部署的全流程。所有命令均按照实际工程支持的参数编写,确保代码可直接运行。

本文使用的是较早期的YOLOv5 2.0工程版代码,它与当前通过ultralytics包调用的新版接口不同,但目标检测的核心数据格式和训练逻辑完全一致,学习价值不受影响。

整篇代码严格遵循工程化规范,超参数统一配置,训练流程清晰可复现,可直接迁移至其他目标检测数据集的训练任务中。文章适合具备Python基础、希望系统掌握YOLOv5训练流程的开发者。

项目效果展示

运行camera_mask.py后,摄像头画面中每张人脸会被矩形框标注,戴口罩的人脸显示绿色边框和mask标签,未戴口罩的人脸显示红色边框和no-mask标签,画面流畅实时。按q键即可退出程序。

一、完整工程代码

项目目录结构

训练命令

yolov5_2_0目录下执行:

cmd 复制代码
python train.py --data ../MaskDataSet/data.yaml --cfg models/yolov5s.yaml --weights weights/yolov5s.pt --hyp hyp.yaml --epochs 200 --batch-size 4 --img-size 640 640 --device cpu

摄像头推理命令

cmd 复制代码
python camera_mask.py

二、技术原理概述

YOLOv5目标检测流程

YOLOv5从原始图片到检测结果经历以下步骤:

一次前向传播即可完成所有目标的定位和分类,这是YOLO能够实现实时检测的核心原因。

三、代码逐模块详细解析

3.1 依赖库与环境配置

python 复制代码
import numpy as np
import torch
import cv2
import os
import yaml

功能说明:导入项目所需的基础依赖库,这些库在后续的数据加载、模型训练、图像处理和配置解析中都会使用。

逐库解析

  • numpy:Python科学计算核心库,在YOLOv5中承担数组运算、坐标变换、损失计算等任务。训练过程中的数据加载和预处理大量依赖其高效的向量化操作。
  • torch:PyTorch深度学习框架的核心模块,提供了张量运算、自动求导、神经网络层定义等基础能力。YOLOv5的模型定义、前向传播和反向传播均基于PyTorch实现。
  • cv2(OpenCV):图像处理与可视化库,负责图片读取、视频帧捕获、图像预处理(缩放、色彩空间转换)以及检测结果的绘制(矩形框、文字标注)。
  • os:操作系统接口模块,用于文件路径拼接、目录遍历和文件存在性检查,在数据加载和结果保存中发挥重要作用。
  • yaml:YAML格式解析库,用于读取data.yamlhyp.yaml配置文件,将训练参数和数据集路径加载为Python字典。

调试提示 :在import torch后设置断点,执行torch.__version__查看PyTorch版本。若报错ModuleNotFoundError,说明当前Python环境中未安装PyTorch,需先激活正确的Conda环境或执行pip install torch

3.2 数据配置文件(data.yaml)

yaml 复制代码
train: ../MaskDataSet/train/images
val: ../MaskDataSet/valid/images
nc: 2
names: ['mask', 'no-mask']

功能说明data.yaml是连接数据集与训练脚本的桥梁,定义了训练集、验证集的图片路径、类别数量和类别名称。训练脚本启动时首先读取此文件。

参数说明

  • train:字符串类型,训练集图片目录的路径,相对于训练脚本运行时的工作目录。由于训练时在yolov5_2_0目录下执行命令,../MaskDataSet表示"上一级目录中的MaskDataSet文件夹"。
  • val:字符串类型,验证集图片目录的路径。
  • nc:整数类型,类别数量(number of classes)。本项目为2类:戴口罩和未戴口罩。
  • names:字符串列表,类别名称。顺序必须与标签文件中的class_id完全一致 ------标签中0对应列表第0项mask1对应第1项no-mask

调试提示 :若训练时出现No labels foundDataset not found错误,首先检查当前工作目录是否为yolov5_2_0。执行cd命令查看当前路径,若不是则切换到正确目录。

3.3 YOLO标签文件格式

每张图片对应一个同名的标签文件。例如train/images/person_001.jpg对应train/labels/person_001.txt

标签文件中每一行表示一个目标物体:

text 复制代码
class_id x_center y_center width height

参数说明

  • class_id:整数类型,类别编号,从0开始。本项目规定0=mask1=no-mask
  • x_center:浮点数,目标中心点的x坐标,归一化到0~1(实际像素坐标除以图片宽度)。
  • y_center:浮点数,目标中心点的y坐标,归一化到0~1(实际像素坐标除以图片高度)。
  • width:浮点数,目标宽度,归一化到0~1(实际像素宽度除以图片宽度)。
  • height:浮点数,目标高度,归一化到0~1(实际像素高度除以图片高度)。

示例标签文件内容:

text 复制代码
0 0.515625 0.462500 0.187500 0.325000
1 0.243750 0.510000 0.162500 0.290000

第一行表示类别0(mask),第二行表示类别1(no-mask)。一张图中有多个人脸就有多少行。

为什么坐标必须归一化:YOLO模型在训练时会动态调整输入图片的尺寸(通过Letterbox保持宽高比)。若坐标是绝对值(像素值),缩放后坐标将完全错位。归一化坐标使得标签与图片尺寸解耦,无论输入尺寸如何变化,坐标始终在0~1范围内有效,模型可直接使用。

3.4 训练命令逐项详解

cmd 复制代码
python train.py ^
  --data ../MaskDataSet/data.yaml ^
  --cfg models/yolov5s.yaml ^
  --weights weights/yolov5s.pt ^
  --hyp hyp.yaml ^
  --epochs 200 ^
  --batch-size 4 ^
  --img-size 640 640 ^
  --device cpu

功能说明train.py是YOLOv5的训练脚本,通过命令行参数控制训练的全部配置。以下逐项解释每个参数的作用和选择依据。

参数详解

  • --data:数据类型为字符串,无默认值(必填)。指定数据集配置文件的路径,脚本从此文件读取训练/验证目录、类别数和类别名。路径相对于运行命令时的工作目录。
  • --cfg:数据类型为字符串,无默认值(必填)。指定模型结构配置文件的路径,定义网络的层数、通道数等架构参数。本项目选择yolov5s.yaml------YOLOv5s是系列中参数最少、速度最快的版本。
  • --weights:数据类型为字符串,无默认值(必填)。指定初始化权重的路径。填写weights/yolov5s.pt表示从COCO预训练权重开始迁移学习,而非随机初始化。
  • --hyp:数据类型为字符串,默认hyp.yaml。超参数配置文件路径,控制学习率、动量、数据增强强度等训练细节。
  • --epochs:数据类型为整数,默认300。完整遍历训练集的次数。200个epoch意味着模型会200次看到全部训练图片,每次经过随机数据增强,相当于看到200倍的数据量。
  • --batch-size:数据类型为整数,默认16。每次迭代送入模型的图片数量。CPU环境下建议使用较小的值(如4),避免内存溢出。batch越大,每个epoch的迭代次数越少,但单次迭代内存占用越高。
  • --img-size:两个整数,默认640 640。分别指定训练和验证时的输入尺寸。640×640是YOLOv5的默认尺寸,在速度和精度之间取得平衡。
  • --device:数据类型为字符串,默认cpu。指定运算设备:cpu表示使用CPU,0表示使用第一块GPU,0,1表示使用多块GPU。

为什么选择YOLOv5s:YOLOv5s参数量最小,推理速度最快,适合在CPU上运行。对于仅有149张图片的小数据集,大模型(如YOLOv5x)更容易过拟合,且训练时间显著增加。

为什么从预训练权重开始:COCO数据集包含80个类别、超过30万张图片,模型已学会通用的边缘、纹理和物体结构特征。在小数据集上从零训练(随机初始化)几乎必然过拟合。迁移学习只需在口罩数据上微调少量参数,即可获得良好的泛化性能。

3.5 验证模型与分类别指标

cmd 复制代码
python test.py ^
  --weights runs\exp17\weights\best.pt ^
  --data ..\MaskDataSet\data.yaml ^
  --batch-size 4 ^
  --img-size 640 ^
  --conf-thres 0.001 ^
  --iou-thres 0.5 ^
  --device cpu ^
  --verbose

参数说明

  • --conf-thres 0.001:评估时使用极低的置信度阈值,目的是收集足够多的候选框来绘制完整的Precision-Recall曲线。这与实际展示结果时常用的0.25不同------评估需要覆盖所有可能的置信度水平。
  • --verbose:输出每个类别的独立指标,而非仅输出汇总的all行。在类别失衡时,汇总行会掩盖少数类的问题。

本项目的实际验证结果(exp17,200 epochs):

类别 Images Targets Precision Recall mAP@0.5 mAP@0.5:0.95
all 29 162 0.671 0.905 0.872 0.557
mask 29 142 0.819 0.880 0.913 0.588
no-mask 29 20 0.522 0.930 0.830 0.526

结果解读

总体mAP@0.5=0.872,表面上看效果不错,但不能因此认为模型在所有场景都表现良好。

no-mask的Recall为0.930,说明验证集中93%的未戴口罩目标被模型找到;但Precision仅0.522,说明该类别预测不够稳定,存在较多误报。验证集中只有20个no-mask框,样本规模不足以全面代表真实摄像头环境------这是当前模型的主要瓶颈。

图7 分类别指标输出截图(此处建议放置终端中test.py --verbose输出的表格截图,高亮显示no-mask行的Precision和Recall)

3.6 摄像头实时推理代码解析

python 复制代码
# 加载模型
model = attempt_load(str(WEIGHTS_PATH), map_location=DEVICE)
model.eval()

# 打开摄像头
cap = cv2.VideoCapture(0)

while True:
    ok, frame = cap.read()
    if not ok:
        break
    
    # Letterbox保持宽高比缩放
    img = letterbox(frame, new_shape=IMG_SIZE)[0]
    
    # BGR→RGB,HWC→CHW
    img = img[:, :, ::-1].transpose(2, 0, 1)
    img = np.ascontiguousarray(img)
    
    # 转为张量并归一化
    img_tensor = torch.from_numpy(img).to(DEVICE).float() / 255.0
    img_tensor = img_tensor.unsqueeze(0)
    
    # 推理
    with torch.no_grad():
        prediction = model(img_tensor)[0]
    
    # NMS去重
    prediction = non_max_suppression(prediction, conf_thres=NMS_CONF, iou_thres=IOU_THRESH)
    
    # 缩放坐标回原图并绘制
    # ...(绘制逻辑)
    
    cv2.imshow("Camera Face Landmark", frame)
    if cv2.waitKey(1) == 27:
        break

功能说明camera_mask.py读取摄像头每一帧,经过预处理后送入模型推理,最后在画面上绘制检测结果。

关键步骤解析

  1. model.eval():将模型切换到推理模式,调整BatchNorm和Dropout层的行为------BatchNorm使用训练时的全局统计量而非当前batch的统计量,Dropout层则完全关闭。这一步虽小,但直接影响推理结果的稳定性。
  2. letterbox(frame, new_shape=IMG_SIZE)[0]:保持宽高比缩放并补边,避免直接拉伸导致人脸比例失真。旧版YOLOv5 2.0的letterbox()不接受stride参数,这是旧版与新版的区别之一。
  3. img[:, :, ::-1].transpose(2, 0, 1):OpenCV读取的是BGR格式,模型训练时使用RGB格式,因此通过::-1反转通道顺序;同时将[H,W,C]转为[C,H,W]以满足PyTorch的输入要求。
  4. torch.no_grad():关闭梯度记录,大幅减少内存占用并加速推理。推理时不需要反向传播,因此无需记录中间变量的梯度。
  5. non_max_suppression:NMS去重,删除高重叠度的重复框,保留置信度最高的那个。

调试提示 :在prediction = model(img_tensor)[0]后设置断点,查看prediction的形状为[N, 6],其中6列分别为[x1, y1, x2, y2, conf, cls],N为检测到的目标数。若N=0,说明模型未检测到任何目标,可能是置信度阈值过高或画面中无人脸。

图8 摄像头实时检测运行截图(此处建议放置摄像头运行时终端和图像窗口的并列截图,显示检测结果和终端输出的帧率信息)

四、完整运行流程

第一步:安装依赖

bash 复制代码
pip install numpy torch opencv-python pyyaml

第二步:下载YOLOv5工程代码

从GitHub克隆YOLOv5 2.0版本或使用已有工程文件。

第三步:准备数据集

将标注好的口罩数据集按以下结构放置:

text 复制代码
MaskDataSet/
├── train/
│   ├── images/    # 训练图片
│   └── labels/    # 训练标签
├── valid/
│   ├── images/    # 验证图片
│   └── labels/    # 验证标签
└── data.yaml      # 配置文件

第四步:下载预训练权重

yolov5s.pt放入yolov5_2_0/weights/目录。

第五步:激活Conda环境(如使用Conda)

cmd 复制代码
conda activate pytorch

第六步:切换到工程目录并开始训练

cmd 复制代码
cd /d D:\Mask_YOLO\yolov5_2_0
python train.py --data ../MaskDataSet/data.yaml --cfg models/yolov5s.yaml --weights weights/yolov5s.pt --hyp hyp.yaml --epochs 200 --batch-size 4 --img-size 640 640 --device cpu

第七步:验证模型

cmd 复制代码
python test.py --weights runs/exp17/weights/best.pt --data ../MaskDataSet/data.yaml --verbose --device cpu

第八步:摄像头实时推理

cmd 复制代码
python camera_mask.py

q键退出程序。

五、常见问题与解决

问题1:ModuleNotFoundError: No module named 'torch'

原因:当前Python环境中未安装PyTorch。

解决方法 :先执行conda activate pytorch激活正确环境,或执行pip install torch安装PyTorch。

问题2:训练时报错No labels found

原因:数据集目录结构不正确,或图片与标签文件名不一致。

解决方法

  • 确认目录名为imageslabels,拼写无误
  • 确认每张图片都有同名(不含扩展名)的.txt标签文件
  • 确认从yolov5_2_0目录启动训练

问题3:训练时报错Dataset not found

原因data.yaml中的路径无法正确解析。

解决方法

  • 执行cd确认当前工作目录是否为yolov5_2_0
  • 检查data.yaml中的路径是否写为../MaskDataSet/train/images(相对路径)

问题4:类别名称显示反了

原因 :标签文件中的class_id与data.yaml中的names列表顺序不对应。

解决方法 :检查标签文件中0代表mask还是no-mask,确保names: ['mask', 'no-mask']中索引0对应mask。若标签中0实际为no-mask,应改为names: ['no-mask', 'mask']

问题5:摄像头无法打开

原因:摄像头被其他程序占用,或设备ID不正确。

解决方法

  • 关闭微信、会议软件等可能占用摄像头的程序
  • 尝试将cv2.VideoCapture(0)改为cv2.VideoCapture(1)
  • 检查Windows摄像头权限设置

问题6:CPU训练极慢

原因:CPU算力有限,200个epoch耗时数天。

解决方法

  • 安装GPU版PyTorch并使用--device 0
  • 减少epochs(如100)先验证流程
  • 减小--img-size(如416)
  • 减小--batch-size减少内存压力

问题7:训练日志显示0G

原因 :日志中的0G表示未使用GPU显存,说明当前运行在CPU上。

解决方法 :这不是错误。若想使用GPU,需安装CUDA版PyTorch并指定--device 0

问题8:运行test.py时报错np.int不存在

原因 :旧版YOLOv5代码使用了新版NumPy已移除的np.int

解决方法 :在test.py中找到np.int并替换为内置int

问题9:摄像头检测全部识别为mask

原因:类别失衡,no-mask样本太少;或训练数据与摄像头场景差异过大。

解决方法

  • 补充实际摄像头拍摄的no-mask样本重新训练
  • 验证集指标不代表真实场景效果,需实际测试

问题10:运行camera_mask.py报错letterbox()参数错误

原因 :新版教程中letterboxstride参数,但YOLOv5 2.0的letterbox()没有该参数。

解决方法 :将letterbox(frame, new_shape=IMG_SIZE, stride=stride)改为letterbox(frame, new_shape=IMG_SIZE)[0]

六、性能优化建议

CPU推理优化

  • 降低输入尺寸:IMG_SIZE从640降至416,可提升约40%推理速度,但可能降低小目标检测精度
  • 跳帧处理:每2~3帧执行一次检测,中间帧复用前一帧结果
  • 降低摄像头分辨率:cap.set(cv2.CAP_PROP_FRAME_WIDTH, 320)减少预处理计算量

GPU推理优化

  • 安装CUDA版PyTorch并指定--device 0
  • 使用半精度推理:model.half() + img_tensor.half()
  • 批量推理:多张图片合并为一个batch同时处理

训练优化

  • 使用GPU训练可大幅缩短训练时间(从数天缩短至数小时)
  • 适当增大batch size(如16或32)提升GPU利用率
  • 使用更小的模型(YOLOv5n)进一步加速

七、项目扩展方向

  • 增加错误佩戴检测 :新增incorrect-mask类别,检测口罩未遮住鼻子等错误佩戴情况
  • 多目标扩展:在口罩检测基础上增加人脸识别、情绪识别等模块,构建综合人脸分析系统
  • 批量处理:改造代码遍历文件夹内所有图片,实现批量自动判分
  • 导出ONNX加速:将PyTorch模型导出为ONNX格式,使用ONNX Runtime或TensorRT加速推理
  • 部署到边缘设备:将模型转换为TensorFlow Lite或NCNN格式,部署到手机或嵌入式设备
  • Web可视化:接入Flask或FastAPI,提供网页端上传图片进行检测的接口

八、总结

本文基于YOLOv5s和口罩数据集,完整实现了目标检测项目的全流程------从数据集准备、环境配置、模型训练到结果评估和摄像头实时部署。核心要点总结如下:

  1. 数据集规范 :图片、标签、data.yaml三者必须严格对应,标签使用从0开始的类别编号和归一化xywh坐标,这是训练能够正常启动的前提。
  2. 训练策略:小数据集必须从预训练权重开始迁移学习,而非随机初始化;使用YOLOv5s等小模型避免过拟合。
  3. 指标解读:不能只看总体mAP,必须查看每个类别的Precision和Recall------类别失衡时总体指标会隐藏少数类的问题。
  4. 推理一致性:训练和推理的预处理必须保持一致(都用Letterbox而非直接resize),否则目标形状改变会导致检测失败。
  5. 持续迭代:模型指标好不等于摄像头效果好,实际部署后需收集失败样本重新训练,形成"训练→部署→采集→再训练"的闭环。

读者可根据本文的工程框架,将自己的数据集替换进来,快速训练出适用于其他目标检测场景(如车辆检测、行人检测)的模型。

参考资料

相关推荐
海兰1 小时前
【思考】银行落地业务Agent的思考
人工智能·机器学习·agent
gwf2161 小时前
Soft-RoCE与Soft-iWARP深度解析:无硬件RDMA学习环境搭建(零基础必知必会)
人工智能·python·tcp/ip·tcp·tcpdump
云端漫步19871 小时前
HarmonyOS NEXT AI 智能生活助手:会话管理与聊天记录保存
人工智能·生活·harmonyos
AI行业学习1 小时前
Claude Code + cc-switch + Git + Node.js 一站式完整安装配置教程(2026最新·国内可用版)
人工智能·git·python·安全·node.js·html·notepad++
汽车仪器仪表相关领域1 小时前
NHA-604/605汽车排放气体测试仪:00级国标计量|多动力车型兼容|移动/固定双工况|智能联网尾气检测设备
大数据·人工智能·功能测试·安全·汽车·压力测试·可用性测试
c#上位机1 小时前
线扫相机之采集图像高度
数码相机·opencv·计算机视觉
科技园长1 小时前
睿视医疗与晓闻科技达成战略合作,推动宠物专用CT设备智能化、数字化全面升级
人工智能·科技·宠物
杰瑞学AI2 小时前
一个回答需要10分钟:飞书问答机器人踩坑实录——纯Agent自由检索,差点让我们的机器人“难产”
人工智能·机器人·prompt·transformer·飞书·ai-native