2. YOLOv5训练自定义数据集(口罩检测)

任务目标

本案例将使用LabelImg标注口罩佩戴数据集(佩戴/未佩戴两类),基于YOLOv5训练自定义检测模型,最终实现图片与视频中的口罩佩戴检测。完成本案例后,您将获得一个可直接调用的best.pt权重文件及配套检测脚本。

环境与依赖

  • Python 3.8+,PyTorch ≥1.8
  • YOLOv5官方仓库(v6.0或v7.0均可)
  • LabelImg标注工具(pip install labelImg)
  • 硬件建议:NVIDIA GPU(显存≥4GB),CPU可训练但速度极慢

数据集准备与标注

  1. 创建数据集根目录mask_dataset/,内部结构如下:
mask_dataset/
├── images/
│   ├── train/    # 训练图片(建议≥300张)
│   └── val/      # 验证图片(建议≥50张)
├── labels/
│   ├── train/    # 训练标注txt
│   └── val/      # 验证标注txt
└── mask.yaml     # 数据集配置文件
  1. 使用LabelImg标注:类别填写mask(佩戴)和no_mask(未佩戴),标注格式选择YOLO,保存后自动生成与图片同名的.txt文件。
  2. 编写mask.yaml:
# mask.yaml
train: mask_dataset/images/train
val: mask_dataset/images/val
nc: 2
names: ['mask', 'no_mask']

完整训练与检测代码

以下脚本整合了数据集划分、训练启动与检测调用,保存为train_mask.py:

import os
import random
import shutil
from pathlib import Path

# ========== 1. 数据集自动划分(若已手动划分可跳过) ==========
def split_dataset(img_root, val_ratio=0.15):
    """将img_root下所有图片按比例划分为train/val,并生成对应空label目录"""
    all_imgs = list(Path(img_root).glob('*.jpg')) + list(Path(img_root).glob('*.png'))
    random.shuffle(all_imgs)
    val_num = int(len(all_imgs) * val_ratio)

    for split, imgs in [('val', all_imgs[:val_num]), ('train', all_imgs[val_num:])]:
        img_dir = Path(f'mask_dataset/images/{split}')
        lbl_dir = Path(f'mask_dataset/labels/{split}')
        img_dir.mkdir(parents=True, exist_ok=True)
        lbl_dir.mkdir(parents=True, exist_ok=True)
        for img in imgs:
            shutil.copy(img, img_dir / img.name)
            # 若已有标注则复制,否则留空等待标注
            lbl = img.with_suffix('.txt')
            if lbl.exists():
                shutil.copy(lbl, lbl_dir / lbl.name)

# ========== 2. 训练入口 ==========
def train():
    # 克隆YOLOv5仓库(首次运行)
    if not Path('yolov5').exists():
        os.system('git clone https://github.com/ultralytics/yolov5.git')
    os.chdir('yolov5')
    os.system('pip install -r requirements.txt')

    # 开始训练:输入尺寸640,batch=16,epochs=100
    cmd = (
        'python train.py '
        '--data ../mask_dataset/mask.yaml '
        '--weights yolov5s.pt '
        '--img 640 '
        '--batch 16 '
        '--epochs 100 '
        '--name mask_exp'
    )
    os.system(cmd)

# ========== 3. 检测推理 ==========
def detect(source):
    """source可为图片路径、视频路径或0(摄像头)"""
    os.chdir('yolov5')
    cmd = (
        'python detect.py '
        f'--weights runs/train/mask_exp/weights/best.pt '
        f'--source "{source}" '
        '--conf-thres 0.5 '
        '--save-txt'
    )
    os.system(cmd)
    print(f'检测结果已保存至 yolov5/runs/detect/')

if __name__ == '__main__':
    # 首次运行:将原始图片放入raw_imgs/后执行划分
    # split_dataset('raw_imgs')
    train()
    # 训练完成后测试单张图片
    # detect('path/to/test.jpg')

运行与验证

  1. 数据准备:将所有原始图片放入raw_imgs/目录,用LabelImg完成标注后,取消注释split_dataset('raw_imgs')执行一次划分。
  2. 开始训练:运行python train_mask.py,训练过程中终端会实时显示mAP、loss等指标。
  3. 验证通过标准:训练完成后检查yolov5/runs/train/mask_exp/weights/best.pt是否存在,且训练日志中mAP@0.5达到0.85以上(若数据集质量良好)。
  4. 效果测试:执行detect('test.jpg'),查看yolov5/runs/detect/下输出图片,观察是否准确框出佩戴口罩/未佩戴口罩的人脸,类别标签正确。

常见问题

  • 显存不足:降低--batch至8或4,或减小--img至416。
  • 标注类别不匹配:LabelImg中类别名称必须与mask.yaml的names完全一致。
  • 训练不收敛:检查标注框是否过小或过大,确保标注框紧贴目标;增加训练轮次至150。
YOLOv5口罩检测训练流程 ① 数据准备 • 采集人脸图片 ≥350张 • LabelImg标注两类: mask / no_mask • 生成YOLO格式txt ② 数据集划分 • images/train (85%) • images/val (15%) • labels/ 对应存放 • 编写 mask.yaml ③ YOLOv5训练 • 加载 yolov5s.pt 预训练 • img=640, batch=16 • epochs=100 • 输出 best.pt / last.pt ④ 推理检测与验证 • 加载 best.pt 权重 • 输入:图片 / 视频 / 摄像头 • 判定:mAP@0.5 ≥ 0.85 • 输出:标注框 + 类别 + 置信度 数据不足/效果差 → 补充标注 关键成功指标 mAP@0.5 ≥ 0.85 完整闭环:标注 → 训练 → 验证 → 部署