ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

YOLOv5口罩检测全链路实战:从数据清洗到摄像头部署

YOLOv5口罩检测全链路实战:从数据清洗到摄像头部署 简介本资源是一套基于YOLOv5实现的口罩佩戴检测完整项目专为高校计算机视觉课程设计与期末大作业打造面向具备Python基础和PyTorch入门经验的学习者解决公共场所人员口罩佩戴状态识别这一典型目标检测应用场景。压缩包共20个文件包含8个核心Python脚本如train.py、detect.py、export.py等、4个预训练及微调模型权重best.pt、yolov5s.pt、cs1.6.pt、kid.pt、1张示例图像ico.jpg、1个Docker部署配置Dockerfile以及Jupyter Notebook教程、Spec打包配置、Git相关配置等全面覆盖训练、推理、导出与容器化部署全流程总大小50.58MB。目前已有304人学习下载。用户可直接运行无需修改获得高分课程设计所需的全部代码、数据、模型与说明文档尤其适合快速复现、理解YOLOv5在轻量级检测任务中的工程实践细节并参考mask_kid.py等模块掌握自定义数据集适配与评估逻辑。1. 这不是调个模型就能交差的期末作业YOLOv5口罩检测必须跑通“数据→训练→推理→验证”全链路很多同学拿到“基于YOLOv5的口罩佩戴检测源码全部数据期末大作业.zip”后直接解压、pip install -r requirements.txt、python train.py结果卡在CUDA out of memory或训练完的模型在测试图上把口罩框成头发、把下巴识别成未戴——这不是代码有bug而是对YOLOv5在真实场景下的数据敏感性、标注规范性和部署约束缺乏系统认知。这个标题里的“全部数据”往往包含光照不均的教室监控截图、侧脸/低头/遮挡严重的课堂实拍片段而“源码”若未经适配其默认超参数如imgsz640、batch_size16在学生本机GTX 1650显卡上必然OOM。它真正要解决的是如何用有限算力在非标准采集条件下让YOLOv5稳定输出可被教师验收的检测结果。适合计算机视觉入门者、课程设计需快速落地者、以及想借该任务吃透目标检测工程闭环的初阶算法实践者。2. 从原始数据到YOLOv5可读格式标注质量决定模型上限不是所有“全部数据”都开箱即用2.1 先验判断检查ZIP包内数据结构是否符合YOLOv5规范YOLOv5要求数据集严格遵循/images/train、/images/val、/labels/train、/labels/val四目录结构且每张图片必须有同名.txt标签文件内容为class_id center_x center_y width height归一化坐标。常见陷阱是原始数据含.jpg和.jpeg混存YOLOv5默认只读.jpg标签文件中class_id写成0口罩和1未戴但data.yaml里names: [mask, no_mask]顺序错位图片分辨率差异极大如320×240到1920×1080直接resize会模糊小目标。提示用以下命令批量检查标签合法性避免训练中途报错# 检查所有txt文件是否为空或格式错误 find ./labels -name *.txt | while read f; do if [ ! -s $f ]; then echo EMPTY: $f; continue; fi if ! head -1 $f | grep -qE ^[0-9] [0-9.] [0-9.] [0-9.] [0-9.]$; then echo FORMAT_ERR: $f; cat $f | head -3; fi done2.2 标注清洗用OpenCV脚本过滤低质量样本“全部数据”常含大量无效帧纯黑/过曝图像、人脸占比5%的远景、严重运动模糊。手动剔除效率低需自动化预筛# clean_dataset.py import cv2 import numpy as np import os def is_valid_image(img_path): img cv2.imread(img_path) if img is None: return False # 检查亮度直方图均值低于20为过暗高于230为过曝 gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) mean_brightness np.mean(gray) if mean_brightness 20 or mean_brightness 230: return False # 检查模糊度Laplacian方差低于100视为模糊 laplacian_var cv2.Laplacian(gray, cv2.CV_64F).var() if laplacian_var 100: return False # 检查人脸区域占比需先运行MTCNN或Haar级联粗检 face_cascade cv2.CascadeClassifier(cv2.data.haarcascades haarcascade_frontalface_default.xml) faces face_cascade.detectMultiScale(gray, 1.1, 4) if len(faces) 0: return False total_face_area sum(w*h for (x,y,w,h) in faces) img_area img.shape[0] * img.shape[1] if total_face_area / img_area 0.005: # 人脸占比0.5% return False return True # 批量处理 for img_path in [./images/train/*.jpg, ./images/val/*.jpg]: for p in glob.glob(img_path): if not is_valid_image(p): txt_path p.replace(images, labels).replace(.jpg, .txt) os.remove(p) if os.path.exists(txt_path): os.remove(txt_path) print(fREMOVED: {p})2.2.1 关键参数说明mean_brightness阈值20/230基于教室常见光照设定过暗易漏检过曝丢失纹理laplacian_var 100学生手机拍摄视频帧的典型模糊下限低于此值检测框抖动明显total_face_area / img_area 0.005排除走廊远景等无效场景确保模型聚焦于“可判别口罩”的人脸尺度。2.3 数据增强策略针对课堂场景定制AugmentationsYOLOv5默认的train.py使用--hyp data/hyps/hyp.scratch-low.yaml但该配置对口罩检测存在缺陷hsv_h: 0.015色相扰动过大会使医用蓝口罩变紫与背景混淆mosaic: 1.0马赛克增强在多人同框时易将A的口罩拼到B脸上产生错误监督信号。应修改data/hyps/hyp.mask.yaml参数原值推荐值原因hsv_h0.0150.005医用口罩色域窄微调即可mosaic1.00.5降低多人场景误标风险degrees10.00.0课堂场景人脸基本正向旋转无意义且增噪translate0.10.05防止口罩移出边界导致标签截断注意修改后需在train.py中显式指定--hyp data/hyps/hyp.mask.yaml否则仍加载默认配置。3. 训练过程可控化避开显存爆炸、loss震荡、mAP停滞三大雷区3.1 显存优化GTX 1650/RTX 3050级别显卡的最小可行配置学生本机常见显存为4GBYOLOv5s默认batch_size16必OOM。不能简单调小batch需同步调整学习率和迭代次数# 在4GB显存上稳定训练YOLOv5s的命令关键参数加粗 python train.py \ --data data/mask.yaml \ --cfg models/yolov5s.yaml \ --weights \ # 不加载预训练权重避免显存峰值 --batch-size **8** \ # 从16降至8 --img 640 \ --epochs 100 \ --name mask_yolov5s_4g \ --hyp data/hyps/hyp.mask.yaml \ --lr0 **0.001** \ # batch减半lr0同步减半线性缩放规则 --lrf 0.1 \ # 终止学习率0.001*0.10.0001 --cache # 启用内存缓存减少IO压力3.1.1 参数逻辑说明--weights 空字符串表示从零初始化虽收敛慢但显存占用比加载yolov5s.pt~140MB低30%--lr0 0.001YOLOv5默认为0.01按batch_size比例缩放8/160.5 → 0.01×0.50.005但实测课堂数据需更保守故设0.001--cache将图片解码后缓存至RAM避免每次epoch重复解码对机械硬盘提升显著。3.2 Loss曲线诊断区分正常收敛与训练失效训练中需实时监控train_batch0.jpg首batch预测图和results.pngloss/mAP曲线。典型问题及对策现象原因解决方案box_loss持续3.0且不下降标签坐标越界如center_x1.0或存在负值运行python utils/general.py --check-dataset data/mask.yaml校验cls_loss在0.5附近震荡类别不平衡未戴口罩样本远少于戴口罩在data/mask.yaml中添加class_weights: [1.0, 2.5]未戴类权重×2.5mAP0.5第20轮后停滞在0.65学习率衰减过早将--lrf 0.1改为--lrf 0.01延长高lr训练阶段3.3 验证集构建必须包含“最难样本”才能反映真实能力仅用随机划分的val集会高估性能。需人工构造三类难例放入/images/val遮挡类手扶眼镜、长发遮半脸、口罩滑落至鼻尖光照类背光导致人脸全黑、窗边强反光尺度类前排人脸占图30%后排仅占2%需保留原图勿resize。验证时用以下命令生成详细报告python val.py \ --data data/mask.yaml \ --weights runs/train/mask_yolov5s_4g/weights/best.pt \ --task test \ # 使用test子集即人工难例集 --save-txt \ --save-hybrid \ # 同时保存置信度0.5和0.1的检测结果 --conf 0.25 # 降低置信度阈值暴露漏检输出的test_results.txt中重点看Recall召回率若难例集召回率0.7说明模型泛化不足需回退到2.2节增强数据。4. 推理与可视化让检测结果经得起课堂演示不只是控制台输出4.1 实时摄像头检测用OpenCV绕过YOLOv5默认的image-only限制YOLOv5官方detect.py仅支持图片/视频文件但期末答辩需现场调用摄像头。需改造detect.py# 在detect.py末尾添加 if __name__ __main__: parser argparse.ArgumentParser() # ...原有参数定义... parser.add_argument(--source, typestr, default0, helpsource) # 默认0摄像头 opt parser.parse_args() # 替换原source处理逻辑 source str(opt.source) if source.isdigit(): # 是摄像头ID cap cv2.VideoCapture(int(source)) assert cap.isOpened(), fCannot open camera {source} while True: ret, img0 cap.read() if not ret: break # 调用YOLOv5检测复用原detect逻辑 img letterbox(img0, new_shapeopt.img_size)[0] img img[:, :, ::-1].transpose(2, 0, 1) # BGR to RGB img np.ascontiguousarray(img) img torch.from_numpy(img).to(device).float() / 255.0 if img.ndimension() 3: img img.unsqueeze(0) pred model(img, augmentopt.augment)[0] pred non_max_suppression(pred, opt.conf_thres, opt.iou_thres) # 绘制结果 for i, det in enumerate(pred): # detections per image if len(det): for *xyxy, conf, cls in reversed(det): label f{names[int(cls)]} {conf:.2f} plot_one_box(xyxy, img0, labellabel, colorcolors[int(cls)], line_thickness2) cv2.imshow(YOLOv5 Mask Detection, img0) if cv2.waitKey(1) ord(q): break cap.release() cv2.destroyAllWindows()4.1.1 关键适配点letterbox函数需从utils.datasets导入确保缩放不拉伸plot_one_box需传入img0原始BGR图而非img归一化tensor否则显示黑屏cv2.waitKey(1)设为1ms保证60FPS流畅ord(q)退出符合答辩操作习惯。4.2 结果可视化增强让老师一眼看懂检测逻辑默认框线太细2px答辩投影时难以辨识。修改utils.plots.plot_one_boxdef plot_one_box(x, im, color(128, 128, 128), labelNone, line_thickness3): # line_thickness从2→3 # 原有代码... cv2.rectangle(im, c1, c2, color, thicknessline_thickness, lineTypecv2.LINE_AA) if label: tf max(line_thickness-1, 1) # 字体粗细 w, h cv2.getTextSize(label, 0, fontScaleline_thickness/3, thicknesstf)[0] # 字体大小随线宽自适应 c2 c1[0] w, c1[1] - h - 3 cv2.rectangle(im, c1, c2, color, -1, cv2.LINE_AA) # 填充背景 cv2.putText(im, label, (c1[0], c1[1] - 2), 0, line_thickness/3, [225, 255, 255], thicknesstf, lineTypecv2.LINE_AA)提示修改后重新运行detect.py --source 0摄像头画面将显示加粗边框高对比度标签即使教室灯光全开也清晰可辨。5. 期末交付物清单与答辩话术让“源码数据”真正成为你的技术资产5.1 必交文件结构教师验收核心项按学校模板要求ZIP包内必须包含以下5类文件缺一不可目录/文件作用检查要点/docs/README.md项目说明文档需含环境配置命令、训练命令、摄像头演示命令三行可复制代码/runs/train/xxx/weights/best.pt最佳模型权重文件大小应在13.8MBYOLOv5s±0.5MB过大说明未剪枝/data/mask.yaml数据集配置train:路径必须为相对路径如../images/train禁用绝对路径/detect_webcam.py摄像头检测脚本文件名明确不含_backup等冗余后缀/results/test_results.txt难例集测试报告需包含Precision、Recall、mAP0.5三行数值5.2 答辩高频问题应答策略教师常问“为什么不用YOLOv8”、“准确率怎么验证的”需用技术事实回应关于模型选型“YOLOv5在PyTorch生态中教程最丰富其export.py可直接转ONNX便于后续部署到树莓派毕设延伸方向而YOLOv8的Triton部署文档尚不完善。”关于准确率“我构建了30张课堂真实难例图遮挡/背光/小脸在test_results.txt中召回率0.78证明模型在实际场景有效若仅用官网mAP指标可能因测试集简单而虚高。”关于数据来源“所有图像来自公开数据集WIDER Face裁剪本班同学授权拍摄标签由3人交叉标注IoU一致性达0.92用labelImg的Validate Labels功能计算。”5.3 一个让答辩加分的具体技巧动态置信度滑块在detect_webcam.py中加入键盘控制按/-键实时调节置信度阈值展示模型鲁棒性# 在摄像头循环内添加 conf_threshold 0.25 while True: # ...检测逻辑... pred non_max_suppression(pred, conf_threshold, opt.iou_thres) # 使用动态阈值 key cv2.waitKey(1) 0xFF if key ord(): conf_threshold min(0.95, conf_threshold 0.05) print(fConfidence threshold: {conf_threshold:.2f}) elif key ord(-): conf_threshold max(0.05, conf_threshold - 0.05) print(fConfidence threshold: {conf_threshold:.2f}) elif key ord(q): break演示时先设conf0.25展示高召回多框再按升至0.6展示高精度少而准直观体现参数对结果的影响——这比单纯说“我调过参”更有说服力。本文还有配套的精品资源点击获取
返回列表