简介:这套基于YOLOv8的商场自动扶梯梳齿板异物卡滞预警系统,专为计算机视觉与深度学习方向的在校学生和入门开发者设计,可满足毕业设计、课程设计、大作业及项目初期演示等场景需求。资源共8个文件,压缩包约15.91MB,内部以Python源码、PyTorch模型权重和说明文档三类为主,py脚本实现模型训练、视频检测与可视化界面,pt权重提供训练好的模型文件,txt文档则包含部署指引和项目备注。目前已有36人学习下载。除核心代码外,还提供完整数据集和部署教程,运行后可生成核心指标曲线、混淆矩阵、F1分数曲线、精确率-召回率曲线、验证集预测结果及标签分布图等,覆盖训练评估全流程。整套代码已测试通过,结构清晰、上手简便,既可直接用于演示答辩,也便于在此基础上扩展其他目标检测场景。
1. 商场扶梯梳齿板卡异物,YOLOv8 这套预警方案能替你守住什么
商场扶梯一整天都在吞吐人流,梳齿板那一条缝每天被硬币、沙石、包装袋、发卡甚至高跟鞋跟塞进去。卡滞的后果不是简单的异响:梯级会被顶弯,梳齿会断齿,严重时直接急停把乘客困在半空。人工巡检有周期,维保不可能 24 小时盯着,这就是基于 YOLOv8 的扶梯梳齿板异物卡滞预警系统要补上的空档——用一只固定摄像头对准梳齿板入口,实时检测异物进入,在卡死之前弹窗报警并留档。整套东西包含训练好的权重、可视化界面和配套数据集,解压按教程部署就能跑,毕设课设够用,物业试点也能当原型。下面我从数据准备讲到界面部署,把每一步的参数和坑都摊开。
2. 系统拆解:从摄像头画面到异物预警的完整链路
2.1 梳齿板异物卡滞检测到底在检测什么
梳齿板位于扶梯上下两端,梯级运行到这里时,梯级齿槽与梳齿板上的齿条交错啮合,把乘客鞋底、推车轮子上夹带的杂物刮下来。正常的梳齿间隙只有几毫米,硬币、石子、钥匙这类硬物一旦卡进齿槽,就会在梯级继续运行时被反复挤压,轻则划伤齿面,重则卡断梳齿、顶弯梯级结构。检测任务要识别的不是"人",而是梳齿板入口处出现的、尺寸远小于梯级的异物。我做这个项目时把检测目标归成两类:硬质异物(硬币、钥匙、石子、发卡)和柔性异物(包装袋、纸巾、口罩)。两类物体的形变特征完全不同,但预警逻辑一致——只要异物出现在靠近梳齿板的区域,就该触发告警。
这个场景的难点在干扰太多。商场吊顶灯、玻璃幕墙反光、乘客身体遮挡,都会让画面忽明忽暗;梳齿板本身是密集的金属齿条,纹理重复且反光强,异物和齿槽的对比度经常很低。传统视觉方案用背景差法或帧间差分,在静止背景下还能用,但扶梯一运动、乘客一走动,背景就碎了,误报率压不下来。目标检测的思路不同:不去建模"背景",而是直接学习"异物长什么样"。只要训练数据里覆盖了足够多的光照、角度和遮挡情况,模型就能在复杂背景里把异物框出来。这也是这个课题选 YOLOv8 而不是传统图像处理的根本原因。
动手做之前要先明确一个边界:这个系统预警的是"异物卡滞"的早期阶段,即异物已经出现在梳齿板附近或刚卡入齿槽的画面,不是事后分析断齿的图像。采集数据时,要刻意拍"异物即将进入梳齿"和"异物已卡入齿槽"两个时刻。这两类样本缺一不可,否则模型学到的只是"地面有东西",而不是"这东西会卡进梳齿"。
2.2 为什么是 YOLOv8:anchor-free、多档模型、部署生态
YOLOv8 在 2023 年初由 Ultralytics 发布,相比 YOLOv5 最大的变化是检测头改成了 anchor-free,即不再预设一组固定宽高的锚框,而是让每个位置直接预测目标的存在概率和边框参数。对梳齿板异物这类目标尺寸变化大的场景——硬币只有几十像素,包装袋可能占画面五分之一——anchor-free 省去了针对数据集重新聚类锚框的步骤,训练配置更省事,收敛也更稳定。网上不少帖子问 yolov8 网络结构图,从结构上看,backbone 沿用了 C2f 结构,neck 是 PAN-FPN,这些在官方仓库的 yaml 文件里都能直接看到,不用迷信网上的讲解图。
损失函数层面,YOLOv8 把分类和回归拆开,分类用 BCE,边框回归用 CIoU 和 DFL。相比 YOLOv5 的 objectness 分支,去掉之后少了一个需要调的权重,训练时的损失曲线也更平滑。早期有人把 yolov8 的损失函数曲线图画出来,会发现 box_loss 和 cls_loss 分开显示,这就是拆开的设计。如果训练时某一路损失异常,可以单独定位是定位问题还是分类问题,排错成本低不少。
模型档位从 n、s、m、l 到 x。毕设项目用 n 或 s 档就够了。n 档参数量只有三百万左右,CPU 上也能跑到十几帧;s 档精度更好,在 GTX 1660 Ti 这类入门显卡上能跑 60 帧以上。l、x 档在精度上提升有限,推理延迟却成倍上涨,边缘设备扛不住。我做这类小目标检测时,习惯先拿 s 档做基准,看精确率和召回率哪个指标拖后腿,再决定要不要换模型。
有人问为什么不用 YOLOv5 或 YOLOv7。YOLOv5 在工程上很成熟,但它的 anchor-based 检测头需要根据数据集重新聚类锚框,换场景就要重算;YOLOv7 的 RepVGG 结构推理时虽快,训练时却要额外的重参数化步骤,调试不如 YOLOv8 直接。对毕设来讲,YOLOv8 的文档、示例和社区问答最齐全,遇到问题基本都能搜到现成答案,这一点在选择模型时比几个点的精度差更重要。部署生态也是理由,训练完的权重可以一行命令导出成 ONNX、TensorRT、OpenVINO 格式,方便后续接到边缘盒子或 RK3588 这类板子上。
2.3 系统模块划分与数据流
整个系统按数据流方向可以拆成五个模块:
摄像头采集:USB 摄像头或 RTSP 网络摄像头,对准梳齿板入口,固定机位、固定角度。画面里梳齿板最好占画面三分之一以上,且不要被扶手或行人完全遮挡。预制一个配置文件保存摄像头地址、分辨率和预览帧率,方便更换设备。
推理模块:YOLOv8 模型加载后对每帧做推理,输出目标的类别、置信度和边框坐标。建议把加载模型、预处理、推理、后处理封装成一个类,与界面逻辑解耦。后面想换更轻量的推理后端时,只改这个类就够了。
预警逻辑:根据置信度阈值过滤低置信度检测,再判断目标边框与梳齿板预警区域(ROI)的重叠关系。比如边框中心点落在 ROI 内且置信度超过 0.5,才触发报警。这个模块决定了系统会不会乱叫,是部署阶段调参的重点。
可视化界面:显示实时视频流、画检测框、滚动报警记录、提供启动/停止/暂停按钮。毕设演示时这块是最直观的工作成果,具体怎么搭在最后一章展开。
记录模块:报警时保存当前帧截图和日志条目,包含时间、类别、置信度,方便事后复盘和写论文的实验记录。
数据流就是:摄像头读帧 → 推理模块出检测结果 → 预警逻辑做 ROI 判断 → 界面刷新显示 → 触发报警时截图存档。训练和部署都围绕这条链路展开,下面三章分别讲数据集、训练和避坑。
硬件选型上,训练阶段用普通笔记本就能完成。推理阶段如果要现场长期跑,建议用一个带 NVIDIA GPU 的小主机或者 RK3588 开发板。CPU 机器跑 s 档模型也能到 10 帧左右,对于扶梯这种缓慢运动、异物卡滞过程持续数秒的场景,10 帧已经足够捕捉到异常,不需要追求 30 帧以上。
3. 准备数据集:标注规范与训练/验证集划分
3.1 数据来源与数据增强策略
做这个系统最缺的是数据。公开的扶梯异物数据集很少,常见做法是两条腿走路:找公开数据集里能用的部分,加上自己拍现场视频抽帧。Roboflow 上有一些 escalator 相关数据集,多为扶梯周围的行人或结构部件,异物的直接标注很少,但可以作为预训练或背景增强的补充。自己的数据靠手机或摄像头在真实扶梯口录视频,录 10 到 20 分钟不同光照时段的画面,比如上午、下午、傍晚各录一段,然后每隔几帧抽一张图。抽帧太密会导致相似样本过多,训练时模型过拟合到重复帧;太疏又浪费了视频里的有效信息,我一般每秒抽 1 到 2 帧。
抽帧之后先做一轮人工筛选,把模糊、过曝、完全被遮挡的图删掉,剩下的一般能有 300 到 500 张有效图片。这个数量做单类别检测勉强够,但想让模型换一个商场还能稳定工作,就必须做数据增强。YOLOv8 训练时自带马赛克增强、随机翻转、色调饱和度调整,这些默认参数在通用场景够用。建议再补两类和扶梯场景强相关的增强:亮度扰动(模拟白天黑夜光线变化)和随机噪声(模拟摄像头传感器噪点)。验证集里不要放增强后的图,否则指标虚高。
数据集处理流程里还有一个容易被忽略的点:要保留一部分完全不含异物的负样本视频帧。这些帧在训练时对应空的标签文件,作用是让模型学会"正常状态下不报警"。加了负样本之后,现场误报率通常能下降一半以上,具体方法放在部署避坑章里细说。
3.2 用 labelme 标注异物:类别定义与框选准则
数据准备好后,标注工具用 labelme 或 labelimg 都行。我偏好 labelme,因为它可以画多边形,有些异物形状不规则,多边形能让标注更贴合目标。YOLO 训练格式要求矩形框,多边形标注转矩形时,脚本取外接矩形就行。labelimg 更轻量,直接画矩形,转换时少一道工序。二选一即可,不必纠结。
类别定义上,我建议先统一成一个前景类,比如 foreign_object,不要一上来就分 coin、stone、trash 好几种。原因很简单:样本少时分类越细,每个类能分到的有效样本就越少,模型容易学偏。先保证"有没有异物"检测得准,毕设答辩被问到"能不能识别具体是什么异物"时,回答"当前版本先做单类别预警,多分类是后续扩展方向"是完全合理的。如果你手头数据量大,超过一千张,再拆成硬质异物(硬币、钥匙、石子)和柔性异物(包装袋、纸巾)两类,展示效果更好。
框选准则有两条硬规矩。一是框要紧贴异物本体,不要为了"保险"把异物周围一圈背景也框进去,背景像素进训练样本会拉低定位精度。二是同一张图里如果一个异物被扶手或乘客身体挡住一大半,直接跳过不标,标注残缺目标会让模型学到错误特征;只有露出超过一半的异物才值得标注。
标注过程建议一个人一口气标完,不要多人分工。两个人对"什么叫异物"的理解差异会直接反映在标签质量上,后期清洗的代价比重新标一次还大。标注完顺便做一轮观察:统计每个类别框数量,如果柔性异物占了九成而硬质异物只有几张图,优先补硬质异物的数据,类别不平衡在目标检测里比在分类里更致命。
labelme 的 JSON 字段是标准的,shapes 数组里每个对象包含 label、points、shape_type。shape_type 为 polygon 时 points 是多个点,为 rectangle 时 points 是两个对角点。转换脚本两种情况都能处理,因为外层逻辑都是对 points 取 min 和 max。如果你的数据里有 line 或 circle 类型的标注,转换时要单独处理,最简单的方式是标注时就只画 polygon 和 rectangle,统一格式。
3.3 转成 YOLO 格式并划分数据集
labelme 标注保存为 JSON 文件,YOLOv8 训练需要 txt 文件,每行五个数字:类别 ID、归一化的中心点 x、中心点 y、宽、高。转换脚本是处理数据集用于 yolov8 训练的标准动作:
import json import os def convert_labelme_to_yolo(json_path, save_path, classes): with open(json_path, "r", encoding="utf-8") as f: data = json.load(f) img_w, img_h = data["imageWidth"], data["imageHeight"] lines = [] for shape in data["shapes"]: if shape["label"] not in classes: continue class_id = classes.index(shape["label"]) xs = [p[0] for p in shape["points"]] ys = [p[1] for p in shape["points"]] x_min, x_max = min(xs), max(xs) y_min, y_max = min(ys), max(ys) box_w = x_max - x_min box_h = y_max - y_min x_center = (x_min + x_max) / 2 / img_w y_center = (y_min + y_max) / 2 / img_h box_w = box_w / img_w box_h = box_h / img_h lines.append(f"{class_id} {x_center:.6f} {y_center:.6f} {box_w:.6f} {box_h:.6f}") with open(save_path, "w", encoding="utf-8") as f: f.write("\n".join(lines)) classes = ["foreign_object"] json_dir = "labels_json" out_dir = "labels_yolo" os.makedirs(out_dir, exist_ok=True) for fn in os.listdir(json_dir): if fn.endswith(".json"): convert_labelme_to_yolo( os.path.join(json_dir, fn), os.path.join(out_dir, fn.replace(".json", ".txt")), classes, )脚本逻辑:读取 labelme 的 JSON,取出每个 shape 的多边形点坐标,算外接矩形的中心点、宽高,再归一化到 0 到 1。这里有一个容易踩的细节:JSON 里的坐标是原始图片像素坐标,归一化的分母必须用 JSON 里记录的 imageWidth 和 imageHeight,不能用你自己另存的图片尺寸。一旦图片被压缩过而代码用了新尺寸,坐标就全错位了,训练出来的框会整体偏移。
转换完做一次校验,遍历每个 txt,检查三项:是否存在对应同名图片、每行五个数是否都在 0 到 1 之间、类别 ID 是否越界。这一步用几行 Python 就能搞定,不需要专门工具。之后按 8:1:1 的比例把图片和对应 txt 分成 train/val/test 三个子集,放在同一个数据集根目录下。
数据集目录结构建议:
escalator_dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ └── labels/ ├── train/ ├── val/ └── test/这样 YOLOv8 训练时直接传根目录路径,它会自动去找 images 和 labels 下对应的子目录。注意 train/val/test 三个子集都要包含正样本和负样本(负样本 labels 下放空 txt),否则验证集里全是正样本,指标会虚高。
注意:负样本不是"没用的空文件",它是模型学会抑制误报的关键。批量转换时记得把没有异物的帧也复制到数据集中。
4. 训练 YOLOv8 模型:命令、参数与效果验证
4.1 环境搭建:CPU 怎么跑,GPU 怎么跑
这个项目对环境要求不高。纯 CPU 也能训练,只是慢一些,几百张图片、80 个 epoch,i5 级别 CPU 大概得跑一晚上;GPU 的话,GTX 1660 Ti 这种 6G 显存的卡就够用。网上搜 ubuntu20.04 搭建 yolov8 环境 CPU 版本的教程很多,Windows 也一样,核心就三步:建 conda 环境、装 PyTorch、装 ultralytics。
conda create -n escalator python=3.9 -y conda activate escalator pip install ultralytics pip install opencv-pythonultralytics 会自动带起 PyTorch。CPU 机器上 pip 默认装的 PyTorch 是 CPU 版,不用额外指定;如果有 NVIDIA 显卡,建议先按 PyTorch 官网生成的命令装 CUDA 版 PyTorch,再装 ultralytics,避免 pip 把 PyTorch 覆盖回 CPU 版。装完验证一下:
python -c "from ultralytics import YOLO; model = YOLO('yolov8n.pt'); print('ultralytics ok')"第一次运行会从官方下载 yolov8n.pt 权重,网络不通时会卡在下载那步,可以手动下载后放到当前目录。新手常犯的错是只装了 ultralytics 没装 torch,导入报 ModuleNotFoundError,建完环境先跑一下pip list | grep torch确认 PyTorch 在。
训练任务如果放在服务器上,建议用 tmux 或 screen 挂着,防止 SSH 断开导致训练中断。这也是我自己的血泪经验:有一回在服务器上跑了一下午,损失曲线已经降到理想区间,结果终端一断全部白算。从那以后我养成了训练必挂 tmux、每天看一眼日志的习惯。
4.2 训练命令与关键参数
数据集准备好后,写一个 data.yaml 指向数据集路径:
path: /path/to/escalator_dataset train: images/train val: images/val test: images/test nc: 1 names: ["foreign_object"]然后启动训练。毕设场景最常用的命令:
yolo detect train \ model=yolov8s.pt \ data=escalator_data.yaml \ epochs=80 \ imgsz=640 \ batch=16 \ device=0 \ patience=15 \ project=runs \ name=escalator_train启动命令里的参数含义,按我实际调参的经验逐个说:
| 参数 | 推荐值 | 作用与调参建议 |
|---|---|---|
| model | yolov8s.pt | 预训练权重,迁移学习起点;验证流程先用 yolov8n.pt |
| data | escalator_data.yaml | 数据集配置文件,路径必须写对 |
| epochs | 80 | 训练轮数,配合 patience 早停 |
| imgsz | 640 | 输入分辨率,小目标可试 800 或 960 |
| batch | 16 | 显存受限时降到 4 或 8 |
| patience | 15 | 验证集损失连续 15 轮不降则提前停止 |
| device | 0 或 cpu | GPU 编号,CPU 机器填 cpu |
| project/name | runs/escalator_train | 输出目录,best.pt 在这里生成 |
imgsz 是最值得单独调的参数。梳齿板异物普遍偏小,如果异物在画面里只有二三十个像素,640 可能不够,建议用 val 集跑一轮对比,mAP50 提升明显就保持高分辨率,提升不明显就退回 640 保速度。batch 受显存约束,6G 显存跑 s 档、640 分辨率,batch 16 基本是上限;启动时报 CUDA out of memory 就先把 batch 降到 4 或 8。batch 减半后学习率一般也要跟着降,否则收敛不稳定,但 YOLOv8 的默认学习率对 16 这个量级已经做过适配,小幅调整问题不大。
训练结束会在 runs/escalator_train 下生成 weights/best.pt 和 last.pt。best.pt 是验证集表现最好的权重,后续推理和部署都用它,不要贪 last.pt 那多出来的几步训练。
4.3 训练产物与效果验证
训练结束后,runs/escalator_train 下会生成一批文件,最值得看的是 results.csv、混淆矩阵图和验证集预测图。results.csv 每行是一个 epoch 的指标,包括训练损失、验证损失、精确率、召回率、mAP50,可以用 Python 画损失函数曲线放进论文:
import pandas as pd import matplotlib.pyplot as plt df = pd.read_csv("runs/escalator_train/results.csv") train_loss = df["train/box_loss"] val_loss = df["val/box_loss"] epochs = range(1, len(train_loss) + 1) plt.figure(figsize=(8, 5)) plt.plot(epochs, train_loss, label="train box loss") plt.plot(epochs, val_loss, label="val box loss") plt.xlabel("epoch") plt.ylabel("loss") plt.legend() plt.savefig("loss_curve.png", dpi=150)判断模型有没有学好的标准,不是训练损失趋近于零,而是验证损失和训练损失的间距。两边一起降、间距不大,说明拟合正常;训练损失一路降、验证损失在某个 epoch 后反弹,就是过拟合。过拟合时优先做三件事:增大 val 集比例、加强数据增强、修改 epochs 并让 patience 早停生效。
分类别统计一次 val 集上的检测结果,看每个类的精确率和召回率。单类别任务直接看 mAP50,能做 0.9 以上才算合格;如果只有 0.7 左右,不要急着调超参,回到数据检查标注质量,统计各类目标数量、删掉模糊样本、补拍稀少的异物类别。数据质量在目标检测里的影响永远大于超参,这是我做了几个 yolov8 训练自己的数据集的项目后最深的体会。
验证集预测图 val_batch_pred.jpg 也很直观,能看出模型在真实标注之外有没有漏检,框是不是贴住异物。如果框普遍偏大偏小,先检查标签转换脚本,多半是归一化或边界计算出了问题。
注意:首次运行训练命令时模型会下载预训练权重,网络环境差时建议用代理或离线方式预置好权重文件,避免卡在下载阶段。
5. 部署避坑:5 个让系统"跑不起来"或"乱报"的常见问题
5.1 训练第一个 epoch 损失就 NaN
现象:训练日志第一行 loss 显示 NaN,之后全是 NaN,训练白跑。
原因:最常见是学习率太大导致梯度爆炸;其次是标签文件里有非法值,比如归一化坐标超过 1、类别 ID 超出 nc 范围。
解决:先检查标签,逐行读 txt 确认五个数在合法区间。然后把马赛克增强临时关掉试试,YOLOv8 里训练参数传mosaic=0.0即可。关掉后能正常训练,说明是增强策略和脏数据不兼容,优先清理数据而不是调学习率。如果之前的实验改过 lr0,恢复默认 0.01 再跑。
5.2 界面一开推理就卡顿,帧率惨不忍睹
现象:程序启动后视频画面掉帧严重,拖动界面窗口像幻灯片。
原因:把视频帧读取和模型推理都写在界面主线程里。界面要刷新、推理要算,两个重活抢一个线程,界面自然卡死。
解决:用 QThread 拆分。一个线程负责读帧,一个线程负责模型推理,推理结果通过信号槽发回主线程更新界面。框架示意:
from PyQt5.QtCore import QThread, pyqtSignal import cv2 class InferenceThread(QThread): result_ready = pyqtSignal(object, list) def __init__(self, model, video_source): super().__init__() self.model = model self.cap = cv2.VideoCapture(video_source) self.running = True def run(self): while self.running: ret, frame = self.cap.read() if not ret: break results = self.model(frame) boxes = results[0].boxes.xyxy.cpu().numpy() self.result_ready.emit(frame, boxes) def stop(self): self.running = False self.wait()核心是 run 里只做读帧和推理,不碰界面控件;主线程的槽函数负责画框。实测里把读帧和推理拆出去后,界面帧率能从 5 帧跳到 20 帧以上。PyTorch 在 CPU 上进行多线程推理时,要设置 torch.set_num_threads 之类的值,否则线程切换会放大推理耗时。帧率这个东西有时比较玄学,同一个模型在不同机器上能差出一倍,但线程拆分的收益是稳定可复现的。
5.3 测试集指标漂亮,一到现场就翻车
现象:测试集 mAP50 有 0.95,拿到商场现场一试,黑色塑料袋、地上的水渍都触发报警,甚至漏掉真异物。
原因:训练集和现场数据分布不一致。训练数据里异物多摆在干净地砖上,背景简单;现场背景是运动中的梯级、金属反光、动态阴影,模型没见过,就把纹理近似的东西当成了异物。
解决:往训练集里补负样本。剪一段现场没有异物的正常视频,抽帧后在 labels 目录下放空 txt 文件,参与训练。负样本让模型学到"现场正常画面不算异物",这是目标检测项目落地最实用的一手。另一个做法是采集现场光照变化最大的时段补拍,把曝光、白平衡差异大的样本加进训练集。这类问题往往到现场实测才暴露,属于比较典型的部署翻车点,提前补负样本能省掉大半返工时间。
5.4 CUDA 显存不足直接退出
现象:训练到中途或验证时报 CUDA out of memory,进程退出,前功尽弃。
原因:imgsz 和 batch 的乘积超过显存容量。6G 显存跑 yolov8s,imgsz=640、batch=32 基本必爆。
解决:先把 batch 降到 8 或 4。还压不住就要降 imgsz,从 640 降到 512。注意 imgsz 降了之后小目标检测精度会受影响,所以训练时优先压 batch。Ultralytics 支持梯度累积,能缓解显存压力,但推理时的显存占用不会减少,验证和实际部署仍要保证显存有余量。
5.5 标签和图片错位,框画在完全不对的位置
现象:训练正常跑完,画出来的预测框明显不在目标上,但训练指标又正常。
原因:图片和标签文件名对不上,或数据集里某张图片被误删,训练脚本按文件名找标签时找不到对应文件,产生了错位。
解决:训练前用脚本统一校验。遍历 images 下所有图片,查 labels 目录下同名 txt 是否存在,把没有标签的图片和没有图片的 txt 全部列出来。这类问题通常是在拷贝、重命名文件之后才暴露,所以我把校验脚本写成独立小工具,每次数据集换机器都先跑一遍。校验脚本几行就能写完,别偷懒这一步。
6. 可视化界面与部署验证:让预警系统真正能用起来
6.1 可视化界面核心组件与线程模型
毕设里可视化界面是门面。常见实现用 PyQt5 或 Tkinter,Tkinter 内置省事,PyQt5 控件现代、对视频流更友好。界面至少要有四个区域:视频显示区、报警信息区、控制按钮区、状态栏。视频显示区用 QLabel 实时刷新帧,报警信息区是一个滚动列表,控制按钮负责启动、停止、暂停,状态栏显示当前置信度阈值和检测帧率。界面和推理线程之间用 PyQt5 的信号槽通信,推理线程发出携带检测结果的信号,主线程槽函数在画面里画框并更新报警列表。
置信度阈值不要写死,在界面上放一个滑块,运行时可以动态调整。演示时现场光线一变,0.5 的阈值可能就乱报,随时能往下拉到 0.6、往上推到 0.7,比改代码重启快得多。报警记录可以顺便保存成 CSV,答辩时打开一看,时间、类别、置信度清清楚楚。
6.2 部署验证:回放视频批量测试再上现场
部署不要直接拿摄像头对着梳齿板就开始调。我自己的习惯是先录一段现场视频,用脚本批量跑一遍离线检测,把每帧结果写进 CSV,统计漏报率和误报次数。这样做的好处是不用反复跑现场,就能对比不同置信度阈值的效果。阈值从 0.3 到 0.7 每隔 0.05 测一次,横轴是误报次数,纵轴是漏报数,挑两条线交叉位置附近的值当默认阈值。
最后说一个反复踩过的坑:摄像头安装角度不对,再好的模型也白搭。梳齿板在画面里偏一点,ROI 就要重新画,前一版标注的数据也可能对不上。所以部署第一步永远是固定机位、在界面里画一遍预警区域,再做模型调优。这个系统的每个模块拆开都不复杂,难的是把数据、训练、界面和现场情况串在一起。
希望这些从数据到部署的细节能帮你少走几步弯路,祝你的毕设或项目顺利跑起来。
本文还有配套的精品资源,点击获取