基于YOLO的安全帽佩戴检测系统实战:从数据集到部署全流程

发布时间:2026/9/8 14:12:11
基于YOLO的安全帽佩戴检测系统实战:从数据集到部署全流程 简介这是一套基于深度学习的安全帽佩戴检测毕业设计项目面向计算机视觉、Python开发方向的毕业生和工地安全智能化研究者。项目以YOLOv3-tiny为检测模型结合卷积神经网络对施工现场人员是否佩戴安全帽进行自动识别并提供可视化交互界面与数据库管理覆盖从图像标注、模型训练到系统部署的完整链路。压缩包共1530个文件约184.87MB以Python源码、YOLO模型权重与配置、前端页面js/css/html、数据库SQL及说明文档为主并包含运行截图与演示视频便于快速复现和二次开发。包内结构按功能模块划分附有详细设计文档、使用说明与部署脚本可帮助读者理解模型训练、图像预处理、目标检测结果存储等关键环节。资源已有975人学习适合需要参考完整毕业设计项目或学习深度学习落地实践的开发者。 搞毕业设计选安全帽佩戴检测这个方向我以为是挺明智的——计算机视觉属于当前深度学习里最好出成果的领域目标检测又有YOLO这种成熟工具链一个月左右就能跑通全流程。再加上工地、工厂、园区这些场景对安全帽检测确实有刚需答辩的时候讲应用价值也站得住脚。这篇就按我实际做过的一个完整项目来拆从数据集处理、模型训练、代码结构到数据库设计把那些网上资料不会明说的细节都过一遍。1. 项目到底在做什么技术路线怎么定1.1 核心需求拆解安全帽佩戴检测本质上是目标检测任务也就是在图片或视频帧里找出“人”和“安全帽”的位置再判断每个检测到的人头顶上有没有对应的帽子。这里有个关键点容易搞错检测目标不是单一类别而是要区分“戴了帽子的人”和“没戴帽子的人”两类。更细的做法是检测三类person人、helmet安全帽、head裸露的头部然后通过坐标匹配来判断每个人是否戴帽。我见过不少初稿把所有戴帽的人标成一类、没戴帽的人标成另一类效果其实也能用但泛化能力和可解释性略差。毕设答辩时导师可能会追问“你怎么判断一个人有没有戴帽”如果你用的是坐标匹配方案就能讲清楚先检测人再检测helmet和head然后用IoU判断每个person框内有没有helmet框有就是正样本。这个逻辑比单纯分类清晰得多。1.2 为什么选YOLO系列而不是Faster R-CNN或SSD目标检测模型三大家两阶段的Faster R-CNN、单阶段的SSD和YOLO。毕设场景我几乎无脑推荐YOLO理由有三单阶段推理快视频检测能跑到实时演示效果好。代码生态成熟Ultralytics的YOLOv5/v8仓库开箱即用训练、验证、导出一条龙。社区资料多踩坑容易找到解决方案答辩前临时调参也有据可查。具体选v5还是v8如果你的机器有NVIDIA显卡哪怕是4GB显存的GTX 1650YOLOv5s是性价比最高的选择——模型小、训练快、部署简单。v8的API设计更现代但在毕设这个体量下优势不明显。如果用的是纯CPU机器也别慌YOLOv5s用CPU训个几十轮也能收敛就是慢一些建议直接用官方预训练权重做迁移学习能省下大量时间。一个小建议选型时不要被“哪个模型精度更高”带偏毕设的核心是完整跑通链路并能自圆其说YOLOv5s足够你拿一个不错的成绩了。2. 数据准备别忽略数据集质量2.1 找数据和数据增强安全帽数据集公开的有SHWDSafety Helmet Wearing Dataset大概七千多张图标注了person、helmet、head三类基本够用。也可以去Roboflow Universe搜“Hard Hat Detection”那边有直接转好YOLO格式的版本下载即用。拿到数据第一件事不是急着训练而是看一下标注质量。我遇到过标注框偏移、类别标反、小目标漏标的情况这些会直接影响模型收敛。最简单的办法是写个脚本把标注框画到图上人工抽查。YOLO格式标注是txt文件每行五个数类别id、归一化中心点x、y、宽w、高h画框用OpenCV的rectangle就行。2.2 数据集结构长什么样训练前把数据按YOLO格式组织好目录结构如下safety_helmet/ ├── images/ │ ├── train/ # 约80% │ ├── val/ # 约20% │ └── test/ # 可选有测试集更好 ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ └── data.yamldata.yaml是YOLO的配置文件内容大致是train: ./images/train val: ./images/val nc: 3 names: [person, helmet, head]如果原始数据集是VOC格式xml标注或COCO格式json标注用ultralytics仓库里的转换脚本先转成YOLO txt格式别手动转容易出错。2.3 训练参数怎么定用官方预训练权重微调训练脚本核心参数参考python train.py --data data.yaml --weights yolov5s.pt --img 640 --batch-size 16 --epochs 150 --device 0参数说明img 640输入尺寸跟预训练保持一致效果最稳。batch-size显存允许范围内尽量大。8GB显存跑16差不多4GB显存建议8。epochs150轮在安全帽这种单场景数据集上足够太多反而过拟合。优化器默认SGD加动量就行不用折腾Adam。学习率设0.01配合warmupYOLOv5内部会自动调度。训练到一半可以关注一下val精度如果val mAP0.5能到0.85以上这项目检测效果在演示时已经足够“能打”了。3. 代码结构和检测逻辑实现3.1 整体代码架构毕业设计源代码不能只有训练脚本得有一个完整的工程结构建议按这个组织safety_helmet_detection/ ├── models/ # 模型相关 │ └── best.pt # 训练好的权重 ├── scripts/ # 工具脚本 │ ├── detect_video.py # 视频检测 │ ├── detect_image.py # 图片检测 │ └── detect_web.py # Web端检测服务 ├── utils/ # 工具函数 │ ├── db.py # 数据库操作 │ └── draw.py # 画框和结果渲染 ├── static/ # 前端静态文件 ├── templates/ # 网页模板 ├── app.py # Flask主程序 └── requirements.txt # 依赖清单这么分的好处是论文里写“系统模块划分”的时候直接有素材每个文件承担什么职责一目了然。3.2 检测推理代码怎么写用YOLOv5官方仓库的detect.py改就行核心就几步加载模型、读取图片/视频帧、推理、后处理。如果继承了官方仓库直接调用import torch from pathlib import Path model torch.hub.load(ultralytics/yolov5, custom, pathmodels/best.pt, force_reloadTrue) results model(frame)但torch.hub每次都要联网检查毕设现场演示时如果网络不稳会尴尬。稳妥做法是本地加载import torch model torch.load(models/best.pt, map_locationcpu)[model].float() model.eval() # 推理 results model(frame) # 解析检测结果 detections results.xyxy[0] # 每行: x1,y1,x2,y2,conf,class设备选择上先检测CUDA是否可用device torch.device(cuda if torch.cuda.is_available() else cpu) model.to(device)3.3 戴帽/未戴帽的判断逻辑前面说的坐标匹配代码实现大概长这样def judge_helmet(person_boxes, helmet_boxes, head_boxes): records [] for pbox in person_boxes: px1, py1, px2, py2 pbox[:4] has_helmet False for hbox in helmet_boxes: hx1, hy1, hx2, hy2 hbox[:4] # 计算helmet框与person框的IoU或用中心点是否在框内判断 if compute_iou(pbox, hbox) 0.1: has_helmet True break records.append({person_box: pbox, helmet: has_helmet}) return recordsIoU阈值不要设太高因为安全帽只占人框的上方一小部分完全重合的IoU本来就不大0.1左右是实践下来的合理区间。更精确的做法是只看人框上方1/3区域的帽子框这个可以自己调。4. 数据库设计与Web端展示4.1 数据库表怎么设计毕设要求“源码数据库”数据库不能只是建个表存两张图交差得体现设计感。以MySQL为例建议至少三张表用户表如果做登录功能检测记录表核心表用于记录每一次检测的结果报警记录表未佩戴安全帽的记录单独存检测记录表核心字段如下CREATE TABLE detect_record ( id INT AUTO_INCREMENT PRIMARY KEY, detect_time DATETIME DEFAULT CURRENT_TIMESTAMP, image_path VARCHAR(255), total_person INT, helmet_count INT, no_helmet_count INT, result_detail JSON, status TINYINT DEFAULT 0 );这里的result_detail字段存JSON记录每个人框的坐标和是否戴帽这样前端展示时有完整数据可用。用JSON是一个比较取巧但有实际价值的做法避免建一堆关联表同时也能解释为“NoSQL与关系型数据库的融合使用”答辩时反而是个加分项。报警记录表可以只存未戴帽的关键信息供后续查询CREATE TABLE alert_record ( id INT AUTO_INCREMENT PRIMARY KEY, detect_time DATETIME DEFAULT CURRENT_TIMESTAMP, image_path VARCHAR(255), person_location JSON, handled TINYINT DEFAULT 0 );4.2 数据库连接与操作封装Python连MySQL推荐用PyMySQL轻量且靠谱驱动安装pip install pymysql。连接池可以不用毕设单机应用直接每次获取连接就行。封装一个db.pyimport pymysql def get_connection(): conn pymysql.connect( hostlocalhost, userroot, passwordyour_password, databasesafety_helmet, charsetutf8mb4 ) return conn def insert_record(data): conn get_connection() try: with conn.cursor() as cursor: sql INSERT INTO detect_record (image_path, total_person, helmet_count, no_helmet_count, result_detail) VALUES (%s, %s, %s, %s, %s) cursor.execute(sql, (data[image_path], data[total_person], data[helmet_count], data[no_helmet_count], json.dumps(data[result_detail], ensure_asciiFalse))) conn.commit() finally: conn.close()注意result_detail是dict存之前记得json.dumps序列化取出时再json.loads反序列化。4.3 Web端怎么展示Flask是毕设Web端最合适的选择比起Django轻量得多。做两三个页面就够首页上传图片检测返回检测结果和画框后的图片。实时检测页调用摄像头或上传视频流边检测边展示。记录查询页从数据库读检测记录用表格展示历史数据。Flask路由实现图片检测的接口app.route(/detect, methods[POST]) def detect(): file request.files[image] # 保存上传图片 img_path os.path.join(static/upload, file.filename) file.save(img_path) # 调用检测函数 result_img, stats detect_image(img_path) # 保存检测结果到数据库 insert_record(stats) return render_template(result.html, image_pathimg_path, statsstats)前端页面用Bootstrap简单搭一下表格展示检测结果图片用img标签直接引用静态路径。实时视频流可以用Flask OpenCV每帧做推理加个线程和队列控制帧率不然容易堆帧导致延迟越来越大。5. 部署过程中容易踩的坑5.1 环境配置篇PyTorch安装时CUDa版本不匹配是最常见的坑。去官网安装命令测半天还是No CUDA GPUs Available先跑一句import torch print(torch.cuda.is_available())返回False基本就是torch版本和驱动的CUDA版本对不上。比如显卡驱动支持CUDA 11.8装的是CPU版torch当然用不了GPU。解决方式很粗暴去PyTorch官网选对应CUDA版本的安装命令先卸载原torch再装。显卡驱动本身没更新的话先到NVIDIA官网下载对应驱动装上再用nvidia-smi查看支持的CUDA版本最后选匹配的torch版本。5.2 训练和推理篇训练时loss变成NaN大概率是学习率太大或数据集有异常的标注坐标。先把lr降一个量级试试再检查一下数据集中有没有负数的标注坐标或宽度高度为零的情况。我排查过这类问题写脚本扫描一遍txt标注文件是最高效的方式。推理时检测不到任何目标或者检测结果全是人的框没有帽子的框先别急着怀疑模型十有八九是推理时类别过滤和置信度阈值问题。YOLOv5默认conf-thres0.25数据集如果小目标多适当调低到0.15试试。还有中文路径的坑模型加载、图片读取如果路径里有中文经常出现读取失败或结果存不上。项目所有路径统一用英文别问我怎么知道的。5.3 数据库访问篇Proxysql、SQLAlchemy这些先不管直接PyMySQL连接报错最常见的两种pymysql.err.OperationalError: (2003) — 服务没启动Windows下用net start mysqlLinux下用systemctl start mysql。pymysql.err.OperationalError: (1045) — 用户名密码错误用命令行客户端确认一下能登录再说。Authentication plugin caching_sha2_password — MySQL 8.0默认认证插件和PyMySQL不兼容建用户时指定mysql_native_password。6. 最后再分享一个提升答辩评分的小技巧做完基本功能后强烈建议加一个摄像头实时画面检测。就是检测视频流里每一帧的安全帽佩戴情况同时在画面上实时显示“已检测人数、未佩戴人数”的统计数字。这一下就把系统从“离线图片识别工具”提升到了“实时监控系统”的高度答辩时导师对实时性的追问就变成了你的主场。实现不复杂OpenCV读取摄像头帧进队列检测线程从队列取帧推理结果画框后经由Flask-SocketIO推到前端视口。帧率不追求高5到10帧就让人感觉是实时了关键是把架构说清楚采集、处理、推送、展示四层解耦。个人体会这类毕设项目最好的节奏不是先啃论文再写代码而是先花两周把主链跑通再用零碎时间打磨细节。安全帽检测的数据集、预训练模型、开源代码都很成熟你要做的不是从零发明而是把它内化成自己的能力然后论文里把每一个选择背后的逻辑讲清楚分数自然不会差。本文还有配套的精品资源点击获取

相关新闻