尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

基于YOLOv8的安全网漏洞检测:从数据集训练到可视化部署全流程实践

基于YOLOv8的安全网漏洞检测:从数据集训练到可视化部署全流程实践 简介一套基于YOLOv8的工地安全网漏洞检测完整项目面向计算机视觉、深度学习方向的毕业设计或课程设计开发者可用作快速搭建可运行的检测系统并产出答辩所需的各类指标图表。压缩包体积15.91MB共8个文件包含3个Python脚本、3个模型权重文件和2个txt说明文档Python脚本分别对应模型训练、视频检测与可视化界面权重文件内置预训练模型与训练完成的最佳权重说明文档提供部署步骤和项目备注。资源经测试运行成功已有33人学习下载。项目集成了可视化页面、完整数据集及部署教程可生成精确率-召回率曲线、混淆矩阵、F1分数曲线、验证集预测结果和标签分布图。功能完善、操作简单适合在此基础上扩展其他功能也适合作为毕设、课设或项目初期立项演示拿来即可用、便于参考学习。1. 从安全帽开始安全网漏洞检测为什么需要目标检测在建筑工地巡检中最容易漏掉的不是工具乱放而是高层脚手架外侧的密目安全网。一张直径不到10厘米的破损在高空看下去只是一个小黑点却可能成为坠物突破口。我去年帮朋友处理过土建工地的安全巡检需求当时还在用人工放大图片逐格排查一天最多检查两栋楼漏检率很高。于是我们决定用YOLOv8做自动检测专门识别安全网上的漏洞。这个项目正是那套方案的完整交付包——包含训练好的best.pt权重、yolov8n和yolo11n预训练模型、带标注的完整数据集、可视化界面Visual_interface.py以及视频检测脚本Detection_video.py。训练脚本train_mode.py跑完会自动生成损失曲线、混淆矩阵、F1分数曲线、PR曲线和验证集预测结果答辩时直接能用。对想快速复现目标检测项目的在校生来说这套资源比到处拼凑代码靠谱得多。2. YOLOv8的检测原理与数据集的正确打开方式2.1 从C2f到解耦头YOLOv8到底改了什么很多同学拿到项目后第一件事就是直接训练结果loss曲线乱飞也不知道为什么。我建议先花半小时把YOLOv8的网络结构理清。YOLOv8继续沿用CSPDarknet作为骨干网络但把原本YOLOv5里的C3模块换成了C2f模块。C2f的设计思路是借鉴了ELAN通过多个分支的堆叠和concat让梯度在传递时保留更多中间信息在参数量增加不明显的情况下对小目标的特征提取更友好。这一点恰好契合安全网漏洞场景——漏网上的小破洞往往只有几十个像素如果特征图下采样次数太多小目标信息早就丢了。头部方面YOLOv8把YOLOv5的Coupled-Head改成了Decoupled-Head分类分支和回归分支互不干扰并去掉了基于Anchor的预测方式转为Anchor-Free。每个特征图位置直接回归到目标的左上角和右下角距离配合TaskAlignedAssigner的标签分配策略让正样本的选择更贴近真实目标边界。这部分就是常说的“YOLOv8 head改进”如果用官方结构图对比看会发现Neck部分仍然是PANet只是C2f替换了原来的CBL和C3。损失函数上也做了不小调整。分类采用BCE Loss回归采用CIoU Loss加上DFLDistribution Focal Loss的变体。DFL让网络输出一个分布而不是一个确定值对目标边界框回归的精细度有明显帮助。这些细节虽然不直接影响你怎么运行train_mode.py但决定你在调整超参数时能不能准确判断是哪一环节出了问题。2.2 数据集的目录结构images和labels缺一不可这个项目的完整数据集是直接可用的解压后大概的结构是dataset/ ├── images/ │ ├── train/ │ │ ├── img_001.jpg │ │ └── ... │ └── val/ ├── labels/ │ ├── train/ │ │ ├── img_001.txt │ │ └── ... │ └── val/ └── data.yamlfind dataset -type f | wc -l上面命令会统计数据集总文件数。如果images和labels的文件对不上后面训练会直接报“No labels found”。建议先跑一段检查脚本把没有对应标签的图片挑出来import os from pathlib import Path img_dir Path(dataset/images/train) label_dir Path(dataset/labels/train) missing [p.name for p in img_dir.glob(*.jpg) if not (label_dir / p.with_suffix(.txt).name).exists()] print(missing labels:, len(missing), missing[:10])这段脚本的逻辑很简单遍历images/train下所有.jpg文件检查labels/train里是否存在同名.txt。p.with_suffix(.txt)的作用是把后缀从.jpg换成.txt这样不需要手动拼接文件名。如果输出了大量缺失文件就要检查是不是数据集在网盘解压时被误删了或者路径缩进层级不对。2.3 标签格式与归一化坐标YOLO系列标签统一是纯文本格式每一行代表一个目标0 0.5234 0.3652 0.0418 0.0521这一行的含义是类别id、归一化后的中心点x坐标、归一化后的中心点y坐标、归一化宽度、归一化高度。类别id从0开始这个项目里我们只关注“漏洞”这一个类别所以大多数标签的起始数字是0。如果你想在同一个框架里继续识别安全带、安全帽只需要修改data.yaml里的names列表并重新标注即可。假设你要把归一化坐标还原成像素坐标可以这样import cv2 img cv2.imread(dataset/images/train/img_001.jpg) h, w img.shape[:2] with open(dataset/labels/train/img_001.txt) as f: for line in f: cls, x_c, y_c, bw, bh map(float, line.split()) x1 int((x_c - bw / 2) * w) y1 int((y_c - bh / 2) * h) x2 int((x_c bw / 2) * w) y2 int((y_c bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 0, 255), 2) cv2.imwrite(check.jpg, img)这里map(float, line.split())将每一行的字符串拆开后全部转成浮点然后通过bx, by中心点加减半宽半高得到边界坐标。注意还原后目标框可能超出原图边界这是因为标注时并没有做边界裁切但训练时YOLO会自动忽略越界部分不影响结果。2.4 标签分布图与类别不均衡检查项目自带的标签分布图会在训练过程中自动生成但你也可以在训练前用matplotlib自己画一张看看各类目标数量和面积分布import glob import matplotlib.pyplot as plt sizes [] for txt_file in glob.glob(dataset/labels/train/*.txt): with open(txt_file) as f: for line in f: parts line.strip().split() if len(parts) 5: bw float(parts[3]) bh float(parts[4]) sizes.append(bw * bh) # 占全图面积比例 plt.hist(sizes, bins50) plt.xlabel(bbox area ratio) plt.ylabel(count) plt.show()这个直方图能告诉你绝大多数目标是小目标还是大目标。如果面积比例集中在0.01以下说明模型对小目标非常敏感后期训练位图像素建议在640以上或者在增强参数里增加mosaic的概率以提升小目标性能。这也是为什么这个项目默认推荐640x640输入而不是416。3. 把训练跑明白train_mode.py、超参数与曲线解读3.1 train_mode.py 的代码结构直接打开项目的train_mode.py你会发现核心其实只有几行。我把常用的训练流程拆开写方便你修改from ultralytics import YOLO if __name__ __main__: model YOLO(yolov8n.pt) # 加载预训练权重 model.train( datadata.yaml, # 数据集配置文件 epochs100, # 训练轮数 imgsz640, # 输入尺寸 batch16, # 批大小 device0, # 0号GPU workers4, # 数据加载进程数 lr00.01, # 初始学习率 patience20, # 早停轮数 cos_lrTrue, # 余弦退火 projectruns/train, nameexp_yolo8n )这里的YOLO(yolov8n.pt)会自动加载预训练权重如果你已经有yolov8n.pt则直接加载。有些网络环境下载慢可以提前把权重放到项目根目录。datadata.yaml是数据集的总入口里面至少包含三行path指向数据集根目录train和val指向图片子目录的路径。device0表示用第一张显卡如果你只有CPU改成devicecpu但训练速度会慢很多。batch size是性价比最高的参数。你的显存如果小于8GB请把batch降到8imgsz降到640否则会出现CUDA out of memory。注意一个容易忽略的点workers在Windows上不要设置大于2否则会反复报数据加载溢出。3.2 数据增强参数怎么调才能不破坏安全网结构数据增强不是越多越好。对工地安全网这种纹理密集、边界不规则的物体过强的旋转或透视变换容易把原本清晰的破损区域扭曲成随机噪声。下面是我在训练时常用的增强配置放在train()里即可hsv_h0.015, # 色相偏移 hsv_s0.5, # 饱和度变化 hsv_v0.3, # 明度变化 degrees10.0, # 旋转角度适当限制 translate0.1, # 平移比例 scale0.3, # 缩放范围 mosaic0.8, # Mosaic拼接概率 mixup0.1 # Mixup增强参数的意义直接映射到ultralytics源码的augmenter中。degrees10.0意味着随机旋转角度在-10到10度之间这样不会把安全网的网眼形状旋转成乱麻。mosaic0.8表示有80%概率把四张图拼成一张提升模型对拥挤场景的鲁棒性但对正样本覆盖要求也更高如果训练集中目标本来就少建议降到0.5。3.3 训练完成后生成的核心指标图表这个项目最值得展示给答辩老师的就是训练结果自动生成的图表。运行完train_mode.py后在runs/train/exp下会出现这些文件文件名内容用途results.png损失曲线、mAP50、mAP50-95看模型收敛趋势confusion_matrix.png混淆矩阵看哪些类别互相混淆F1_curve.png不同置信度下的F1分数选合适置信度阈值PR_curve.png精确率-召回率曲线评估类别性能val_batch_samples.jpg验证集预测框对比直观展示检测效果labels.jpg标签分布图检查标注质量如果你想自己重新绘制损失曲线或者需要把曲线整合到论文里可以直接读取results.csvimport pandas as pd import matplotlib.pyplot as plt df pd.read_csv(runs/train/exp/results.csv) plt.figure(figsize(8, 5)) plt.plot(df[epoch], df[train/box_loss], labelbox loss) plt.plot(df[epoch], df[val/box_loss], labelval box loss) plt.xlabel(epoch) plt.ylabel(loss) plt.legend() plt.grid(True) plt.show()注意results.csv的列名在ultralytics 8.x不同小版本中略有差异读取前先print(df.columns)看看。train/box_loss就是边界框回归损失val/box_loss是验证集上相同项。如果两条曲线持续下降且间距不大说明模型拟合正常如果val loss在某个epoch后返身向上就是过拟合的前兆应该提前停止或降学习率。3.4 验证与测试别只看mAP还要算漏检率训练结束后的验证推荐用以下命令yolo detect val modelruns/train/exp/weights/best.pt datadata.yaml脚本执行完成后控制台会输出mAP50、mAP50-95、precision、recall四个核心指标。但在工地安全网场景我更关心recall因为漏掉一个漏洞可能意味着安全事故。如果recall低于0.8建议降低置信度阈值重新测试或者把训练集里难样本再多标注一些。此时可以看看PR曲线的平衡点F1_curve.png直接给出最优置信度阈值通常落在0.2-0.3之间。注意best.pt是基于验证集mAP选出的它不一定对应最后一轮epoch。所以做最终效果评估时一定用best.pt而不要自作主张换成last.pt。4. 从图片到视频Detection_video.py 与 Visual_interface.py 实战4.1 图片推理用best.pt检测单张安全网图片训练完成后最快的测试方式是直接用ultralytics的API跑一张图from ultralytics import YOLO model YOLO(runs/train/exp/weights/best.pt) results model.predict( sourcetest_images/001.jpg, conf0.25, iou0.45, saveTrue, save_txtFalse, projectruns/detect, nameexp ) for r in results: boxes r.boxes for box in boxes: x1, y1, x2, y2 box.xyxy[0].tolist() conf box.conf[0].item() cls int(box.cls[0].item()) print(fclass{cls}, conf{conf:.3f}, bbox({x1:.0f},{y1:.0f},{x2:.0f},{y2:.0f}))conf0.25表示把置信度低于0.25的框全部丢弃iou0.45是NMS的IoU阈值。安全网漏洞之间距离很近且形状不规则如果检测框重叠严重适当降低iou到0.3可以保留更多候选框。保存的结果默认在runs/detect/exp下每张图都会标注好坐标和类别。4.2 Detection_video.py将视频流变成实时检测项目里的Detection_video.py处理的是视频输入。它的结构无非是读取视频帧、推理、绘制结果、写入输出。一个简化但可运行的版本如下import cv2 from ultralytics import YOLO model YOLO(best.pt) cap cv2.VideoCapture(input_video.mp4) fps cap.get(cv2.CAP_PROP_FPS) w int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) h int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) out cv2.VideoWriter(output_video.mp4, cv2.VideoWriter_fourcc(*mp4v), fps, (w, h)) while cap.isOpened(): ret, frame cap.read() if not ret: break results model.predict(frame, conf0.3, imgsz640) annotated results[0].plot() out.write(annotated) cv2.imshow(detect, annotated) if cv2.waitKey(1) 27: break cap.release(); out.release(); cv2.destroyAllWindows()这个循环每读一帧就做一次推理results[0].plot()会返回已经画好框的新画面。需要注意CPU上跑yolov8n在640分辨率下也只有8-12 FPS如果瓶颈明显可以尝试把imgsz降到480或者把输入帧等比缩小后再推理然后对坐标做放大还原。4.3 Visual_interface.py 的可视化界面要怎么组织虽然是“可视化界面”但它不是复杂的前端页面而是基于Python GUI库的桌面程序。项目里的Visual_interface.py我推测用的是Tkinter或PyQt5。一个合理的结构是左侧是检测区域右侧是参数面板包括置信度滑杆、模型选择下拉框、运行按钮。我仿照这个思路写一个框架你可以对照自己的界面来理解import tkinter as tk from tkinter import filedialog, Scale from ultralytics import YOLO from PIL import Image, ImageTk class App: def __init__(self, root): self.root root self.model YOLO(best.pt) self.conf_th 0.25 self.panel tk.Label(root) self.panel.pack(sideleft) scale Scale(root, from_0.05, to0.9, resolution0.05, orienthorizontal, commandself.update_conf) scale.set(self.conf_th) scale.pack() tk.Button(root, text选择图片, commandself.load_image).pack() def update_conf(self, val): self.conf_th float(val) def load_image(self): path filedialog.askopenfilename() if path: results self.model.predict(path, confself.conf_th) annotated results[0].plot() # 用PIL转成tkinter可显示格式后刷新self.panel root tk.Tk() App(root) root.mainloop()核心是用Scale控件把置信度阈值动态写入self.conf_th用户一滑滑杆下一次检测就用新的阈值。如果要检测实时摄像头只需要把load_image换成VideoCapture循环并在刷新Label时用root.after(10, update_frame)避免界面卡死。这套界面展示给人看时重点不是美化而是让操作者能直观感受到置信度阈值变化对漏检率的影响。4.4 界面中置信度滑杆的调优策略演示时很多人会把置信度调到0.5以上觉得这样框更准。但实际上在安全网漏洞场景0.15-0.35才是合理区间。高置信度会漏掉大量小破损而0.1以下会出现过多误检。建议界面中提供两把滑杆一把调置信度一把调IoU这样在答辩现场可以展示不同参数组合下的检测差异评委看到的是一个能“调参”的系统而不是一条写死的流水线。5. 部署与性能优化低配机器也能跑的加速技巧5.1 将模型导出为ONNX格式提速如果部署机器没有GPU纯CPU推理yolov8n的耗时在150-300ms之间用ONNX Runtime可以把时间压到80-120ms。导出命令yolo export modelbest.pt formatonnx opset12 simplifyTrue导出后项目文件夹会多出一个best.onnx用这个文件进行推理import onnxruntime as ort import cv2 import numpy as np sess ort.InferenceSession(best.onnx, providers[CPUExecutionProvider]) input_name sess.get_inputs()[0].name input_shape sess.get_inputs()[0].shape # [1,3,640,640] img cv2.imread(test.jpg) img_resized cv2.resize(img, (640, 640)) img_blob img_resized[:, :, ::-1].transpose(2, 0, 1).astype(np.float32) / 255.0 img_blob np.expand_dims(img_blob, axis0) outputs sess.run(None, {input_name: img_blob})注意这里的预处理顺序BGR转RGB用[:, :, ::-1]再transpose(2,0,1)变成CHW最后归一化除以255。模型输出是多维数组不同版本ultralytics输出的格式可能不同需要后处理解析boxes。如果是新手直接用YOLO(best.onnx)也能跑但速度提升有限因为ultralytics内部做后处理仍然较慢。5.2 显存不够时的三个降级方案问题现象推荐做法显存溢出CUDA out of memory减小batch到4imgsz降到512训练太慢一个epoch要半小时改用yolov8n开启amp混合精度推理卡顿FPS低于5导出TensorRT或ONNX开启FP16如果你的GTX 1660 Ti只有6GB显存建议使用yolov8n和batch8混合精度训练可以省约30%显存。如果实在带不动mosaic设置mosaic0。5.3 常见报错排查速查表报错信息原因解决命令/方法CUDA out of memorybatch过大调小batch输入nvidia-smi确认占用No labels found in ...标签路径错误检查data.yaml的train/val配置FileNotFoundError权重路径不对将best.pt放在当前目录或完整路径AttributeError: NoneType object has no attribute shape视频读取失败用opencv检查cap.isOpened()nvidia-smi是看显存占用最直接的工具。如果GPU显存没被占满但仍然报OOM多半是多个进程累计导致的重启Python环境即可。纠缠数据加载问题时把workers0如果不再报错说明是Windows下多进程数据加载的兼容性问题。5.4 验证加速的优雅做法前面提到的模型验证仍需要完整跑一遍验证集。如果只想快速验证模型有没有训练好可以用一个更小的子集yolo detect val modelbest.pt datadata.yaml splitval然后在data.yaml中把val指向一个只包含50张图的文件夹用batch1逐张推理。这样得到的recall虽然有波动但足以判断模型是否有严重的整体偏移。如果val集上某类recall为0优先检查训练集里该类图片是否过少或者标注框是否正确。安全网漏洞检测项目最后交付时建议把验证时生成的PR曲线和F1曲线图都放到项目docs目录这样评审老师打开就能看到评估流程而不是只看到一个孤立的mAP数值。本文还有配套的精品资源点击获取
返回列表