新闻详情

新闻详情

首页 / 资讯中心 / 详情

垃圾桶满溢检测数据集:YOLOv5三分类实战与避坑指南

发布时间:2026/9/26 2:53:59来源:尧图网络
垃圾桶满溢检测数据集:YOLOv5三分类实战与避坑指南
简介面向目标检测与垃圾分类场景的实用数据集包含满溢垃圾桶、未满溢垃圾桶和垃圾三个类别图像为400×500的RGB图片并按YOLOV5标准目录组织下载解压后可直接用于模型训练无需额外转换。资源包共2000个文件、约313MB其中1999个txt为各图片对应的标注文件并附有3类别的类别文本另提供1个Python可视化脚本可随机读取一张图片绘制边界框便于快速验证标注效果。数据已按YOLOV5惯例划分训练集与验证集训练集2680张图片及标签、验证集669张图片及标签可直接用于训练与评估流程。项目内show.py脚本无需修改即可运行帮助使用者直观检查数据质量。目前已有451人学习下载适合需要成熟标注数据集开展垃圾分类检测实验的学生、研究者与开发者。1. 垃圾桶满溢检测数据集为什么 3 类标注比 10 类更实用目标检测数据集(YOLOV5目录格式)垃圾桶满溢检测数据集3类别这个标题放到搜索页里很常见但真正拿到手里你会发现满溢检测的核心不是模型多强而是数据集怎么把“满溢”这个状态定义清楚。垃圾桶是固定场景里的静态物体检测任务从“物体有没有”变成了“状态是什么”所以 3 个类别反而比 10 个类别更好训练。适合正在用 YOLOv5 训练自己的数据集、又不想在环卫和物业场景里反复翻车的算法工程师。下面从目录格式、标注规则、训练参数到踩坑点给你一条可以直接复现的路径而不是只给一份“看起来能用”的压缩包。2. 先看懂 YOLOV5 目录格式一张图对应一个 txt坐标全部归一化拿到数据集先不要急着解压跑训练先看目录结构。YOLOV5 目录格式和 COCO、VOC 不一样它把标注信息拆成每个图片同名的 txt 文件统一放在 labels 目录下。不了解这一层后面 data.yaml 写错一个路径就是No labels found训练直接停摆。很多从公开数据集转过来的新手会把 VOC 的 XML 硬塞进 YOLOv5结果训练时一条标注都读不到这就是典型的“目录格式没先立住”。2.1 目录结构images 和 labels 必须严格对齐一份标准的 YOLOV5 目录格式数据集长这样dataset/ ├── images/ │ ├── train/ │ │ ├── img_001.jpg │ │ ├── img_002.jpg │ │ └── ... │ ├── val/ │ │ └── ... │ └── test/ │ └── ... ├── labels/ │ ├── train/ │ │ ├── img_001.txt │ │ ├── img_002.txt │ │ └── ... │ ├── val/ │ │ └── ... │ └── test/ │ └── ... ├── data.yaml └── classes.txtimages和labels下面要有相同的子目录名而且图片文件名和 txt 文件名必须完全一致包括大小写和后缀。比如图片是img_001.jpg对应标注就是img_001.txt。如果图片是.jpeg后缀txt 名的基准是去掉后缀后的主文件名跟后缀无关。txt 里没有内容说明这张图没有目标但是训练时 YOLOv5 会把这样图片当作背景图如果背景图太多模型会偏向“什么都不检”。这里有一个常见误解classes.txt不是 YOLOv5 训练必需的。真正决定类别的是data.yaml里的names列表。如果你拿到的数据集只有classes.txt也不要直接把它改成data.yaml因为 YOLOv5 的 train.py 只认 yaml 格式的配置文件。2.2 3 个类别怎么定normal、full、overflow标题里写的是“3类别”那这三类到底是什么必须在一开始就定死。按环卫巡检最常见的需求我一般建议这样定义类别编号类别名判定标准0normal垃圾桶内垃圾没有超过桶口平面桶盖能正常闭合桶周围没有散落垃圾1full垃圾已经堆到桶口平面以上桶盖无法闭合但垃圾还没有散落到桶外地面2overflow垃圾已经散落到桶外地面桶周围有明显堆弃物或者垃圾袋挂在桶边这个定义一定要落到标注规则上否则标注员会自由发挥。很多数据集翻车就翻在 full 和 overflow 的边界上有人觉得垃圾高过桶口就算 overflow有人觉得必须掉到地上才算 overflow。模型学到的边界是混乱的最后表现为同一段视频里状态在 full 和 overflow 之间来回跳。为什么是 3 类而不是更多因为满溢检测最终要触发的动作不一样normal 不用处理full 需要安排清运但可以缓几个小时overflow 需要尽快处理。类别设计要和业务动作一一对应而不是为了“看起来厉害”去细分垃圾类型。细分垃圾类型是垃圾分类检测的事和满溢检测是两个任务。2.3 标签文件里到底写了什么归一化坐标计算YOLOv5 的 txt 每一行代表一个目标框格式是# class_id x_center y_center width height # 坐标均为归一化值即像素值除以图片的宽或高 0 0.512345 0.678901 0.123456 0.234567 2 0.300000 0.800000 0.150000 0.200000第一列是类别编号后面四个数分别是目标框中心点的 x、中心点的 y、框宽、框高全部相对于图片尺寸做了归一化。比如一张 1920x1080 的图片某个垃圾桶框的左上角是 (500, 300)右下角是 (800, 600)那么x_center (500 800) / 2 / 1920 0.3385 y_center (300 600) / 2 / 1080 0.4167 width (800 - 500) / 1920 0.1563 height (600 - 300) / 1080 0.2778注意是中心点坐标不是左上角坐标。很多人手动改的时候把 x_min 和 y_min 直接写进去训练出来框全部偏到右下角。这种错误用可视化脚本一查就能发现后面会讲。还有一点坐标如果出现小于 0 或大于 1 的值YOLOv5 会把它当异常框过滤掉导致该目标直接不参与训练。所以转换脚本里必须做边界处理但不能简单地裁一刀了事因为这说明原始标注本身越界了最好回到原始图片上修正框再转换。2.4 从 VOC 标注转成 YOLOV5 格式转换脚本与边界处理如果拿到的数据集是 VOC 的 XML 格式需要用脚本转成 YOLOv5 的 txt。这里给一个我常用的转换核心函数import xml.etree.ElementTree as ET def voc_to_yolo(xml_path, out_txt_path, class_list): tree ET.parse(xml_path) root tree.getroot() img_w int(root.find(size/width).text) img_h int(root.find(size/height).text) lines [] for obj in root.iter(object): name obj.find(name).text if name not in class_list: continue class_id class_list.index(name) bndbox obj.find(bndbox) xmin float(bndbox.find(xmin).text) ymin float(bndbox.find(ymin).text) xmax float(bndbox.find(xmax).text) ymax float(bndbox.find(ymax).text) x_center ((xmin xmax) / 2) / img_w y_center ((ymin ymax) / 2) / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h # 防止单个标注越界导致整行被过滤 x_center max(0.0, min(1.0, x_center)) y_center max(0.0, min(1.0, y_center)) w max(0.0, min(1.0, w)) h max(0.0, min(1.0, h)) lines.append(f{class_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}) with open(out_txt_path, w) as f: f.write(\n.join(lines))这里class_list的顺序必须和data.yaml里的names一致否则类别号全错位。脚本里过滤掉了不在类别列表里的目标比如如果 XML 里混了person就不会写进 txt。边界处理我用了min/max裁剪但这只是兜底真的遇到越界框裁剪完看似合法实际上框已经不代表原目标了最好还是把图片和原框导出来人工看一眼。如果你拿到的数据本身就是 YOLOV5 目录格式比如这个垃圾桶满溢检测数据集已经分好了 images 和 labels那么转换步骤可以跳过。但建议你仍然抽查至少 10 张图的 txt因为公开数据集里经常混着空的、错位的、类别号对不上的文件提前发现比训练到一半再排查省事得多。3. 从采集到标注制作一份不翻车的垃圾桶满溢检测数据集数据集的质量决定了模型的上限这个话在满溢检测上尤其成立。因为垃圾桶本身是低动态目标真正变化的是垃圾的状态而状态识别对光照、角度、遮挡极其敏感。如果你只是在网上找了一堆“垃圾桶”图片随手标注一个“垃圾桶”类别那即使训练出模型也只是在检测“有垃圾桶”而不是在检测“垃圾桶满了”。这一步要把场景覆盖和状态边界都做到位。3.1 采集场景昼夜、天气、角度和遮挡一个都不能少满溢检测的摄像头通常装在环卫车、路灯杆、小区出入口、垃圾房旁边安装角度千奇百怪。我一般建议采集时至少覆盖这几个维度时间段白天、傍晚、夜间带灯光、夜间无灯光。夜间是个大坑很多项目白天 mAP 很高一上夜间摄像头就全线漏检。天气晴天、阴天、雨天。雨天的垃圾桶周围会有反光和水渍模型容易把反光当成垃圾。垃圾桶类型铁皮圆桶、塑料方桶、带盖桶、无盖桶、不同颜色的桶。颜色差异会影响模型对“垃圾溢出”的判断。拍摄角度平视、俯视、斜视。现实中摄像头经常是俯拍框的形状差别很大。距离近景、中景、远景。远景下垃圾桶可能只有几十个像素满溢和正常的差异更小。遮挡行人、车辆、树木遮挡以及垃圾桶被部分挡住的情况。不要只拍无遮挡的干净画面。采集数量上没有绝对标准但如果自己从头做建议每个类别至少要有 500 到 1000 个标注框不是图片数。一张图里往往有多个垃圾桶所以图片数可以比框数少。如果场景多宁可在夜间多拍些因为夜间样本一旦缺了后面想靠数据增强补回来很难。3.2 标注工具与状态边界LabelImg 保存 YOLO 格式标注工具最常见的是 LabelImg它可以直接保存 YOLO 格式的 txt不需要再转换。打开一张图画框选择类别保存这个流程对标注员几乎没有学习成本。如果你需要更强大的功能可以用 X-AnyLabeling 或者 Labelme但 LabelImg 在 YOLOv5 这个固定流程里已经够用。标注规则比工具更重要。给标注员发一份带图例的规则说明比发一个 README 有效得多。这里是我的经验版本只有明显可见的垃圾桶才标模糊到看不清状态的远处垃圾桶直接忽略不要硬标。框要贴着垃圾桶的外沿包含桶身和溢出物。注意 overflow 的框要覆盖散落在地面的垃圾而不是只框桶身。如果同一个桶同时存在 full 和 overflow 的特征按 overflow 标因为状态优先级最高。不要框影子不要框倒影不要把两个紧挨着的桶框成一个框。拿不准的边界按低一级标。比如垃圾高出桶口一点但不确定满没满标 full 而不是 overflow。这些规则要写进标注文档里。标注员如果只看类别名就会用自己脑补的“满了”来标最后你得到的标签噪声会直接变成模型输出的抖动。3.3 数据划分按场景分组不要让同一摄像头进两个集合训练集、验证集、测试集的划分看起来是几行代码的事但满溢检测数据集里有很多视频抽帧出来的图片如果直接随机划分同一摄像头同一时间段的前后帧会被拆到 train 和 val 里模型相当于提前看过验证集指标会虚高得离谱。正确做法是按场景分组划分。import os import random from shutil import copyfile random.seed(42) src_images raw_images src_labels yolo_labels train_ratio, val_ratio 0.8, 0.1 # 假设文件名前缀是摄像头ID日期例如 cam01_20240115_0001.jpg all_files [f for f in os.listdir(src_images) if f.endswith((.jpg, .png, .jpeg))] groups {} for f in all_files: group_key f.split(_)[0] _ f.split(_)[1] # 按摄像头日期分组 groups.setdefault(group_key, []).append(f) group_keys list(groups.keys()) random.shuffle(group_keys) train_groups group_keys[:int(len(group_keys) * train_ratio)] val_groups group_keys[int(len(group_keys) * train_ratio):int(len(group_keys) * (train_ratio val_ratio))] test_groups group_keys[int(len(group_keys) * (train_ratio val_ratio)):] for split, gkeys in [(train, train_groups), (val, val_groups), (test, test_groups)]: os.makedirs(fdataset/images/{split}, exist_okTrue) os.makedirs(fdataset/labels/{split}, exist_okTrue) for gk in gkeys: for f in groups[gk]: base, ext os.path.splitext(f) copyfile(os.path.join(src_images, f), fdataset/images/{split}/{f}) txt os.path.join(src_labels, base .txt) if os.path.exists(txt): copyfile(txt, fdataset/labels/{split}/{base}.txt)这段代码的关键是按摄像头ID_日期分组后再把组整体划分到 train、val、test。这样同一个摄像头同一天的连续帧不会同时出现在训练集和验证集里。如果你是从视频里抽帧不要把连续帧全部放进去可以每隔 5 帧抽一张减少冗余。还有一点没有对应 txt 的图片也会被复制到 images 里但不会复制标签。如果这类图片太多训练集里背景图比例会过高模型会变得“不敢检测”。建议单独统计一下背景图数量控制在总数 10% 以内。3.4 可视化检查标注坐标还原到图片上看训练前必须做一次可视化检查把 txt 坐标还原到图片上确认框的位置和类别没有错位。很多问题光看数据统计是看不出来的比如框整体偏移、类别号对不上、框只框住半个桶这些只能通过看图发现。import cv2 import os def draw_boxes(img_path, txt_path, class_names): img cv2.imread(img_path) h, w img.shape[:2] if not os.path.exists(txt_path): return img with open(txt_path) as f: for line in f: parts line.strip().split() if len(parts) ! 5: continue cls int(parts[0]) x_c, y_c, bw, bh map(float, parts[1:]) 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) # 防止画框时越界 x1 max(0, min(w, x1)) y1 max(0, min(h, y1)) x2 max(0, min(w, x2)) y2 max(0, min(h, y2)) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(img, class_names[cls], (x1, max(0, y1 - 5)), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) return img # 抽查 val 目录下的图片 class_names [normal, full, overflow] for img_name in os.listdir(dataset/images/val): base, _ os.path.splitext(img_name) img draw_boxes( fdataset/images/val/{img_name}, fdataset/labels/val/{base}.txt, class_names ) cv2.imwrite(fcheck/{base}_check.jpg, img)这段脚本会生成带框的图片重点看两类一类是框和桶的贴合度另一类是 full 和 overflow 的框有没有把散落的垃圾包含进去。如果发现大量框偏移到一个方向很可能是在转换坐标时把中心点写成了左上角回到归一化公式检查即可。可视化检查这一步不要省它能帮你省掉后面至少 3 轮无效训练。4. 用 YOLOv5 训练自己的数据集data.yaml 和训练参数数据准备好之后训练阶段真正要操心的是data.yaml、模型尺寸和超参数。很多数据集本身标注没问题但训练时因为 yaml 写错、batch 太大显存溢出、或者不知道看哪些指标导致反复跑实验却得不到一个稳定结果。这一章把训练前的配置和训练后的验收串起来。4.1 写 data.yaml路径用相对路径类别名顺序别乱YOLOv5 训练时读的是data.yaml不是classes.txt。一个能直接跑的 yaml 长这样# 数据集根目录可以填相对路径或绝对路径 path: ../dataset train: images/train val: images/val test: images/test nc: 3 names: 0: normal 1: full 2: overflowpath是数据集根目录train和val是相对于path的路径。我一般建议用相对路径写这样整个数据集拷到另一台机器上不用改配置换绝对路径。names的顺序必须和 txt 文件里的 class_id 一一对应如果0: normal而标注文件里0是 overflow那训练出来的模型预测结果会整体错位而且混淆矩阵上看不出来。写 yaml 时最容易踩的坑有两个一是train写成images/train/带末尾斜杠YOLOv5 也能接受但路径拼接时容易出问题二是nc和names的数量对不上YOLOv5 会在训练启动时报错或者干脆静默地只使用前nc个类别。写完 yaml 可以先用一行 Python 验证一下import yaml with open(data.yaml) as f: cfg yaml.safe_load(f) print(cfg[nc], len(cfg[names])) assert cfg[nc] len(cfg[names])4.2 选模型大小和预训练权重从 s 开始m 更稳YOLOv5 有n/s/m/l/x几个型号满溢检测的垃圾桶通常不是小目标但摄像头俯拍的时候桶的像素可能不大综合来看从yolov5s起步比较稳。如果推理设备是树莓派这类嵌入式板子选yolov5n压帧率如果显存够、对精度要求高可以上yolov5m。l和x在满溢检测这个任务上收益有限反而会把训练时间和部署体积拉高。预训练权重建议使用 COCO 上训好的yolov5s.pt。注意COCO 里的garbage bag或bottle类别权重对满溢检测只有迁移学习的意义不能直接拿来推理。因为满溢检测的输出类别是状态不是物体本身。第一次训练时用预训练权重可以显著提速但如果数据集很少预训练权重反而可能让模型陷入对 COCO 特征的过拟合这时候可以考虑从头训但需要更多 epoch。4.3 训练命令关键参数和显存踩坑训练命令是标准 YOLOv5 启动方式python train.py \ --data data.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 100 \ --workers 8 \ --project runs/train \ --name trash_overfill \ --hyp data/hyps/hyp.scratch-low.yaml--img 640表示把输入图片统一 resize 到 640x640YOLOv5 会自动加灰边保持原始比例。如果你的数据集里垃圾桶在远景下很小可以把--img提高到 1280但显存占用和训练时间会明显上升。--batch 16是一个安全起步值如果你在 8G 显存的卡上遇到CUDA out of memory直接减到 8 或 4不要硬扛。--workers 8是数据加载线程数Windows 上太高会卡死改成 4 或者 2 更稳。超参数文件默认用hyp.scratch-low.yaml就好。如果你的数据集小不要急着调学习率先跑一轮默认的看结果。满溢检测有一个值得关注的是--multi-scale开启后模型会随机缩放输入图对远景检测有好处但训练时间会增加。也可以加--label-smoothing 0.1对全和满这种状态型类别有时能提升一点鲁棒性但不是万能药。训练过程中如果 loss 始终不动先别急着调超参数检查一下数据集里是不是大量标签为空或者data.yaml的train路径下根本没图片。这是最常见的“玄学”问题九成是数据路径问题不是模型问题。4.4 训练产物先看哪些指标再决定要不要调训练结束后在runs/train/trash_overfill/下会生成weights/best.pt、weights/last.pt、results.png和confusion_matrix.png。先看results.png里三条曲线mAP_0.5、mAP_0.5:0.95、val_cls_loss。如果mAP_0.5和mAP_0.5:0.95还在上升说明欠拟合可以增加 epoch如果已经平了说明训练到位不要再硬跑。指标含义经验参考mAP0.5IoU 阈值 0.5 下的平均精度满溢检测建议至少 0.85mAP0.5:0.95更严格的 IoU 范围平均精度比 mAP0.5 低 0.1~0.2 正常Precision预测为正例中有多少正确低的时候误检多Recall实际正例有多少被检出低的时候漏检多对于满溢检测漏检和误检都很麻烦但漏检更致命。因为一个满溢的桶没检出来环卫调度系统就不会触发工单。如果 recall 比 precision 低不少优先补数据集里 overflow 的样本而不是去调置信度阈值。混淆矩阵也要看重点看 full 和 overflow 的互扰程度如果溢出样本大量被预测成 full说明标注时两者的边界没有拉开这时候加训练集不如先修标注规则。到这一步模型已经能跑通了。但训练完不是终点接上摄像头才是真正的开始。5. 避坑垃圾桶满溢检测数据集最容易翻车的 5 个细节这一章是血泪经验。我见过太多项目挂在同样的地方而且都是训练结束之后才暴露出来。下面这 5 个问题每一个都值得你在启动训练之前先对照检查一遍。5.1 训练报 No labels found目录和文件名不匹配现象python train.py启动后YOLOv5 直接提示No labels found in .../labels/train或者训练日志里Scanning labels显示 0 个标签但 images 目录里明明有 txt 文件。原因最常出现在两种情况。一是data.yaml里train写成了images/train但labels目录不在images/train同级路径下YOLOv5 会根据图片路径自动推断标签路径如果图片路径和标签路径相对关系不对就找不到。二是图片文件名和 txt 文件名大小写不一致比如图片是IMG_001.JPGtxt 是img_001.txtYOLOv5 在 Linux 下对大小写敏感直接跳过。解决先跑一个检查脚本列出所有缺少 txt 的图片文件import os for split in [train, val, test]: img_dir fdataset/images/{split} lbl_dir fdataset/labels/{split} missing [] for f in os.listdir(img_dir): base, _ os.path.splitext(f) if not os.path.exists(os.path.join(lbl_dir, base .txt)): missing.append(f) print(split, missing labels:, len(missing)) if len(missing) 20: print(missing)这个脚本会快速定位是文件名问题还是路径问题。如果缺失数量很大优先检查data.yaml的路径和目录结构而不是逐个改名。我一般会在训练前把这个脚本的结果存成日志免得后面想追溯都没有记录。5.2 full 和 overflow 分不清标注规则没有量化现象训练完看混淆矩阵full 和 overflow 的互混非常严重大约三成 overflow 被预测成 full。在视频实测里垃圾桶已经堆到地上了模型还输出 full。原因标注时没有一个可以量化的边界。标注员 A 认为垃圾掉了 3 块在地上就算 overflow标注员 B 坚持只要桶盖盖不上就算 overflow。模型同时学习到两套标准自然在两者之间摇摆。解决把判定标准写成“硬指标”。我的做法是以桶口平面为界桶口以下为 normal垃圾接触桶口平面以上但未接触地面为 full垃圾任何一部分接触地面或者垃圾袋/散落物超出桶身的垂直投影为 overflow。规则越具体越好甚至可以配图说明。如果两个标注员对同一张图的标注一致性测试达不到 95%就不要开始训练。5.3 夜间图片全部漏检场景比例严重失衡现象白天测试集上 mAP0.5 有 0.9夜间测试集直接掉到 0.3甚至垃圾桶完全检测不到。训练集图片数量明明有几千张为什么夜间效果这么差。原因大部分公开数据集和自采数据都偏重白天夜间图片可能只占 5%。YOLOv5 虽然有 Mosaic、HSV 等数据增强但 HSV 增强改变的是色相和饱和度模拟不了夜间整体低亮度、强噪点的视觉效果。解决采集时强制按场景配额一般我会要求夜间图片占比不低于 20%。如果实在补拍不了可以对夜间图做一次离线增强比如降低亮度、加高斯噪点、提高对比度把一张夜间图扩成 3 张参与训练。但增强只是补救最可靠的还是真实夜间样本。夜间漏检还有一个隐藏原因标注框在低亮度下看不清标注员凭感觉画框框偏了模型自然学不好。所以夜间图必须单独抽检可视化结果。5.4 验证集虚高同一场景的视频帧被切进 train 和 val现象训练时验证集 mAP 很高模型看起来完美但接到实际摄像头视频上表现很差同一个场景反复跳检测结果。原因数据划分时直接random.shuffle了所有图片而图片大多来自同一批视频抽帧。同一个摄像头同一个时间段的前后帧一张进了 train一张进了 val模型在训练时已经见过高度相似的画面验证集指标自然虚高。解决用第 3 章里的分组划分按摄像头 ID 和日期分 groupgroup 之间整体划分。如果没有摄像头 ID可以根据文件名的时间戳前缀分组或者按照拍摄地点手工分组。更严格一点测试集应该来自完全没参与训练的摄像头这样才贴近真实上线场景。验证集的作用是模拟没见过的环境不是考记忆。5.5 状态输出抖动标注边界不一致导致模型置信度摇摆现象模型在连续视频帧上同一垃圾桶的状态在 normal、full、overflow 之间来回跳单帧看置信度都不低但整体输出非常不稳定没法触发工单。原因除了前面说的标注规则不统一还有一个原因是垃圾桶状态本身在视频里是渐变的满溢不会在某一帧突然从 normal 变成 overflow。模型在边界附近置信度天然低如果没有时序处理输出就会抖。解决第一优先级是把标注规则拉齐减少训练标签里的噪声。第二是推理端加时序平滑比如用滑动窗口对最近 N 帧的状态投票输出出现次数最多的状态。这个技巧会在下一章详细展开。不要试图单靠提高置信度阈值来解决抖动因为阈值提高会导致状态切换响应变慢full 已经出现很久了还不触发。这些坑每一个都真实存在而且很多是训练之后才暴露的。提前检查它们比多跑 100 轮 epoch 有价值得多。6. 别只信 mAP用连续帧投票验证满溢检测才算落地训练跑完、best.pt 也出来了但如果只盯着测试集 mAP你很可能在真实视频流上摔跟头。满溢检测是一个典型的状态检测任务业务系统需要的是“稳定地知道这个桶现在是满还是溢”而不是每一帧都独立输出一个类别。解决抖动的最简单方法就是加一个连续帧投票模块。from collections import deque class FrameVote: def __init__(self, window5): self.window window self.queue deque(maxlenwindow) def add(self, detections): # detections: 当前帧的目标列表每个元素为 (class_id, conf) if not detections: self.queue.append(-1) return # 取当前帧置信度最高的目标类别 best max(detections, keylambda x: x[1]) self.queue.append(best[0]) def get_status(self): if len(self.queue) self.window: return None # 返回窗口内出现次数最多的状态 return max(set(self.queue), keyself.queue.count)这段代码会维护一个长度为 5 的队列每帧把最高置信度的类别放进去然后统计最近 5 帧里出现最多的状态作为最终输出。窗口太短比如 3 帧抖动压不明显窗口太长比如 10 帧状态变化响应慢垃圾桶已经 overflow 了还要等好几秒才触发。我一般从 5 帧开始调如果摄像头是 25fps5 帧意味着 0.2 秒内决策一次对工单系统足够快。验证的时候也不要只看单帧 mAP。拿一段包含“正常→满→溢”完整过程的视频跑模型记录每一帧的状态检查状态跃迁路径。好的结果应该是normal - full - overflow按顺序推进如果中间出现normal - overflow的跳变或者 full 和 overflow 反复交替说明标注边界仍然有噪声回去改标注规则而不是继续调投票窗口。这个习惯帮我在很多项目里避免了“测试集分数很好看上线后工单乱飞”的尴尬。我之前做过一个环卫项目模型在 mAP 上表现不错一接摄像头满溢状态在 normal 和 overflow 之间来回跳当时第一反应是调阈值折腾了两天都没改善。最后重新翻了标注文件才发现一批 overflow 的框只框了桶身没把地面散落垃圾包进去。重新修正后再配合 5 帧投票输出就稳了。这个教训让我现在做任何数据集第一件事永远是可视化检查加状态边界评审而不是急着跑训练。希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

claude-code-templates:构建稳定可预期的AI编程助手模板体系 2026/9/26 3:26:31

claude-code-templates:构建稳定可预期的AI编程助手模板体系

Claude Code 这类 CLI 编程助手真正用起来之后,第一周的新鲜感会很快被一个问题取代:怎么让输出稳定下来。能干的事确实很多,但每次都要把同样一大段需求描述重新敲一遍,还得反复纠正它“按项目规范来”“别写多余注释”“格式对齐…

阅读更多 →
Codex 额度不够用?我把 ChatGPT 网页版通过 TaoToken 接进本地项目 2026/9/26 3:26:30

Codex 额度不够用?我把 ChatGPT 网页版通过 TaoToken 接进本地项目

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
DeepSeek向左,Manus往右:TaoToken 统一 Key 下 16 条 AI 产品/组织/个人影响预测的配置骨架 2026/9/26 3:26:30

DeepSeek向左,Manus往右:TaoToken 统一 Key 下 16 条 AI 产品/组织/个人影响预测的配置骨架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
AI Infra实战:vLLM、SGLang推理引擎与PyTorch、Agent部署优化指南 2026/9/26 3:26:24

AI Infra实战:vLLM、SGLang推理引擎与PyTorch、Agent部署优化指南

1. AI infra到底在解决什么问题说实话,这两年AI行业最不缺的就是模型,缺的是能把模型老老实实跑起来、跑得稳的人。你去看各大厂的招聘岗位,AI infra方向的薪资一路走高,但真正懂行的人依然稀缺。所谓AI infra,落到日常…

阅读更多 →
Loop Engineering 实战:用 TaoToken 统一 Key 搭建编程智能体循环骨架 2026/9/26 3:26:24

Loop Engineering 实战:用 TaoToken 统一 Key 搭建编程智能体循环骨架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
Agent之Skills:Open Design 本地优先设计工作流配置与验证全攻略 2026/9/26 3:26:24

Agent之Skills:Open Design 本地优先设计工作流配置与验证全攻略

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉