简介传送带异物检测识别数据集专注于工业生产线场景下的目标检测任务可用于识别铁棍、垃圾等非预期物体面向计算机视觉开发者、工业质检算法工程师以及相关课题研究人员方便快速验证检测模型在真实监控画面上的表现。压缩包内共108个文件其中105张JPG图片来自不同时段的生产线监控视频抽帧涵盖白天、交接班等多样化画面另有3个JSON文件采用COCO格式标注包含类别与边界框信息可配合主流框架直接读取。资源整体约4.65MB轻量易下载。目前已有413人学习使用。通过该数据集与标注文件用户可以省去自行采集和标注的时间直接用于YOLO、Faster R-CNN、SSD等目标检测模型的训练和评估不同摄像头的拍摄角度和光线变化也为模型泛化能力测试提供了参考场景可据此分析传送带异物识别的难点为产线质检方案提供数据基础。1. 传送带异物检测识别数据集别急着找下载先弄懂这份 COCO JSON 能不能直接用于训练做工业质检的人对异物检测四个字都又爱又恨传送带上除了正品什么都有可能混进来——铁棍、纸团、塑料片、编织袋条甚至上一道工序掉下来的螺丝垫片。目标检测模型能不能在这里落地瓶颈从来不在算法而在数据。而传送带异物检测识别数据集这个关键词能搜到的东西多数以 COCO JSON 格式打包带好标注框。问题在于这些标注是用 COCO 的规则组织起来的和 YOLO 训练直接要的 txt 格式之间还有一层转换关系很多人就是倒在这层转换上的。COCO 是一个公开的目标检测数据集格式规范它把每张图的路径、尺寸、标注框、类别都写进一个大的 json 文件里结构稳定、字段清楚但直接拿来训练并不行。这篇我按自己做工业项目的经验从解读这份 json 开始把校验、转换、训练、踩坑一路写到现场部署。2. COCO JSON 格式拆解先搞懂标注文件里每一行在说什么2.1 COCO 数据集的信息结构从 images、annotations、categories 三个顶层字段开始拿到一份 COCO 格式的异物检测数据集第一件事不是急着去看图而是把 json 文件的结构打开看清楚。COCO JSON 是一整个字典顶层通常有 info、licenses、images、annotations、categories 五个键其中真正决定模型训练的只有后面三个。images 是一张列表里面每个元素对应一张图片包含 id、file_name、width、height 四个关键字段annotations 是另一张列表每个元素对应一个标注框包含 id、image_id、category_id、bbox、area 这些字段categories 则是类别字典的列表通常包含 id、name、supercategory。看一个实际标注的小例子会更直观。假设数据集里有一张生产线上拍到的传送带俯视图上面有一根铁棍和一个纸团对应的 json 片段大概是这个样子。这段结构里值得注意的细节是bbox 的四个数字依次是左上角 x 坐标、左上角 y 坐标、框宽度 w、框高度 h单位是像素但类型是浮点数。COCO 规范里允许小数坐标很多标注工具导出的也是小数这在后面转 YOLO 格式时会多一个取整还是保留的决策点。{ images: [ {id: 1, file_name: frame_0001.jpg, width: 1920, height: 1080} ], annotations: [ {id: 1, image_id: 1, category_id: 1, bbox: [120.5, 340.2, 860.1, 42.3], area: 36382.23}, {id: 2, image_id: 1, category_id: 2, bbox: [1500.1, 620.7, 96.3, 88.5], area: 8522.55} ], categories: [ {id: 1, name: iron_bar, supercategory: foreign_matter}, {id: 2, name: trash, supercategory: foreign_matter} ] }这里每个字段的语义要抠清楚image_id是把标注框和图片关联起来的外键没有它标注框就找不到对应的图category_id是类别在 categories 里的编号这个编号可以从 1 开始不连续但不能和 categories 里的 id 对不上area字段在 COCO 官方工具里会被用来筛选小目标但在 YOLO 训练流程里它基本不参与计算转格式时可以不保留。实际项目里我收到过不少标注文件images 是齐的annotations 里却混着个别不在 images 里的 image_id这种脏数据会在数据加载时直接报 KeyError而且报错位置离问题数据很远非常难排查。所以在动任何训练代码之前先把这个 json 当成数据库表来检查外键关系是省时间的第一步。2.2 类别定义与 ID 映射为什么建议把铁棍和垃圾分开再留一个未知异物类别怎么定直接决定了模型能学到什么边界。标题里写了可识别铁棍垃圾但落到 COCO 的 categories 字段时有一个很多人忽视的设计问题id在 COCO 里从 1 开始而在 YOLO 训练格式里类别编号必须从 0 开始。如果拿到手的 COCO json 里铁棍是category_id: 1垃圾是category_id: 2那么转换成 YOLO 标签时铁棍的类别编号要写成 0垃圾写成 1。这个减一操作看起来简单但一旦数据集里有三类、四类或者标注软件导出的 id 是从 0 起的映射关系就很容易错位。我的习惯是写转换脚本时强制用 categories 列表的索引顺序来重建映射而不是直接拿category_id减一前者的结果是确定的后者依赖标注工具的实现。另一个更贴近工业现场的问题是类别粒度。传送带上的垃圾其实是个很宽泛的概念纸团和塑料瓶盖在图像上差异极大放在同一个类里模型学的是它们和传送带背景的差异这在初期够用但一旦现场出现某种训练集里完全没有的垃圾形态模型大概率会漏。我的经验是如果数据集允许把类别拆成铁棍软质垃圾硬质碎片三到四类会更有价值。软质垃圾包括纸团、布料、塑料袋硬质碎片包括石子、金属片、玻璃渣。拆完之后训练阶段可以针对样本少的类做增强补偿部署阶段也能根据类别做不同的报警策略——铁棍对设备有物理损坏风险需要急停纸团可能只需要记录和吹除。还有一点值得专门说要不要加一个未知异物类。常见做法是加因为传送带异物检测本质上是个开放集问题总有没见过的垃圾形态。把这个类放进训练集有个副作用它会吸收大量难例导致其他类别的精确率下降。我一般会在数据集版本 v1 不加等上线后收集两个月的误检和漏检样本再决定是否引入。这个决策可以先不做但 categories 的supercategory字段建议统一写成foreign_matter为以后无论怎么调整类别结构都留好兼容空间。2.3 数据采集与标注工具从现场抽帧到生成 COCO 的完整流程这份数据集的标注格式是 COCO JSON但数据从哪来、怎么标才是决定它能不能用的根本。采集部分有个关键点传送带是运动的异物出现在画面里的姿态几乎每帧都不同如果按视频连续帧取数据相邻帧高度相似训练集的信息量会被严重高估。我之前做过一次统计连续帧采 1000 张图去重后有效样本不到 300 张因为在传送带速度恒定的情况下同一根铁棍会被拍到几十帧。正确做法是设定固定的抽帧间隔比如每 5 秒取一帧或者按传送带运行距离来抽样保证同一个物体最多只出现在两三帧里。另外一定要采至少 15% 的负样本也就是没有任何异物的空传送带图片负样本对减少误检的作用远比想象中大很多模型在现场疯狂报警就是因为训练集里全是正样本模型不知道没有异物长什么样。标注工具的选择上常见做法是用 Labelme 或 COCO Annotator。Labelme 默认导出的是自己的 JSON 格式需要写一次转换脚本转成 COCOCOCO Annotator 可以直接产出 COCO 格式用浏览器打开支持多人分任务标注比较适合几十万张图的中型项目。我自己的项目用的是 Labelme因为团队标注员更熟悉它的快捷键但每次标注完都要合并所有 JSON 文件再转 COCO这中间容易出编码问题后面避坑章节会专门说。标注规范里必须写死三点第一bbox 要框住目标的完整轮廓包括被遮挡时能推断出的部分而不是只画露出来的部分第二铁棍这种长条形目标框必须是贴合的矩形但允许它倾斜着被框成一个大矩形——这种情况下框里包含大量背景模型初始化时可能会被干扰这是旋转框检测能解决的问题但对于 v1 版本先把贴合度做好就够了第三目标被传送带边缘裁切时如果可见部分不足 30%直接跳过不标只标完整可见和大部分可见的目标避免给模型喂入大量残缺样例。3. 让数据先通过体检COCO 文件校验与转 YOLO 格式的实操脚本3.1 先跑一个 JSON 体检脚本检查结构、缺字段、BOM 与非法值从网上下载的或者标注团队交付的 COCO 文件质量参差不齐。常见的问题包括JSON 文件带 UTF-8 BOM 头导致json.load直接报错annotations 里的 image_id 指向了不存在的图片bbox 出现负值或超出图像边界某些标注框的 area 字段缺失或为 0。这些问题不是说模型完全不能训练而是会在训练过程中以各种奇怪的形式暴露出来比如 loss 突然变成 nan或者某个类别完全学不出来。所以在转换格式之前我会一律先把检测脚本跑一遍当作数据集体检。下面这个脚本在项目里我会保存为check_coco.py每次拿到新数据先跑一次。import json from pathlib import Path def check_coco(json_path): with open(json_path, r, encodingutf-8-sig) as f: coco json.load(f) images {img[id]: img for img in coco[images]} categories {cat[id]: cat[name] for cat in coco[categories]} print(f图片数量: {len(images)}, 标注框数量: {len(coco[annotations])}, 类别: {categories}) # 检查 image_id 和 category_id 的外键完整性 bad_image_ref, bad_cat_ref 0, 0 for ann in coco[annotations]: if ann[image_id] not in images: bad_image_ref 1 if ann[category_id] not in categories: bad_cat_ref 1 # 检查 bbox 是否越界、面积是否为负 bbox_out [] for ann in coco[annotations]: img images.get(ann[image_id]) if not img: continue x, y, w, h ann[bbox] if x 0 or y 0 or w 0 or h 0: bbox_out.append((ann[id], 非正尺寸)) elif x w img[width] or y h img[height]: bbox_out.append((ann[id], 越界)) print(f无效 image_id: {bad_image_ref}, 无效 category_id: {bad_cat_ref}, 异常 bbox: {len(bbox_out)}) for bid, reason in bbox_out[:10]: print(f annotation {bid}: {reason}) if __name__ __main__: check_coco(annotations/instances_train.json)逻辑说明用utf-8-sig编码打开 JSON 文件可以自动剥离 BOM 头这是从 Windows 上交付的标注文件最常踩的一个编码坑随后把 images 和 categories 构建成字典用image_id和category_id做外键检查能定位到 dangling referencebbox 检查过滤三类问题负起点、非正尺寸、超出图像边界。参数上可以通过命令行传入 json 路径也可以在脚本里写死先跑通一次。这个脚本跑出来的异常数量如果超过标注总数的 1%我一般会退回标注环节修数据而不是在训练时硬扛。还有一个容易被忽略的问题COCO 的 annotations 里的segmentation字段。在目标检测数据集中它可以是多边形坐标的嵌套列表也可以是多边形内部的 RLE 编码如果这份异物数据集只用于检测不使用实例分割可以完全忽略这个字段转换时直接跳过。但要注意的是很多标注工具导出 COCO 时会把segmentation字段写成空列表或 None这会造成 json 内容不一致转换脚本里读取字段时必须用ann.get(segmentation, [])的方式防 KeyError。3.2 把 COCO JSON 转成 YOLO 训练格式转换脚本与四个边界坑YOLO 系列的训练格式和 COCO 完全不同它是每个图片对应一个同名 txt 文件每行代表一个目标框格式是class_id x_center y_center width height其中中心点坐标和宽高都归一化到 0 到 1 之间。这个转换在逻辑上很简单但实操中几乎每个项目都会遇到问题。最常见的四个坑一是类别 ID 减一问题前面已经说过 COCO 的 id 从 1 开始而 YOLO 的 class_id 从 0 开始二是坐标变换公式容易写错需要把左上角坐标加宽高的一半得到中心点再除以图片宽度和高度归一化三是浮点数精度归一化后的值至少要保留 6 位小数否则小目标的定位精度会受影响四是文件名对齐问题——YOLO 的 txt 标签文件必须和图片放在同一个命名空间下如果图片叫frame_0001.jpg标签就必须叫frame_0001.txt但 COCO json 里的file_name可能带有子目录前缀转换时需要约定最终的数据目录结构。下面是我在项目里持续在用的转换脚本。它不是最简版本但把上面这些坑都堵住了输出目录结构可以直接喂给 YOLOv8 或其他 YOLO 版本使用。import json from pathlib import Path def coco_to_yolo(coco_path, img_root, out_root): with open(coco_path, r, encodingutf-8-sig) as f: coco json.load(f) images {img[id]: img for img in coco[images]} cats sorted(coco[categories], keylambda c: c[id]) # 用类别列表顺序重建从 COCO id 到 YOLO id 的映射 cat_id_map {cat[id]: idx for idx, cat in enumerate(cats)} out_root Path(out_root) (out_root / labels).mkdir(parentsTrue, exist_okTrue) # 按图聚合标注框 anns_by_img {} for ann in coco[annotations]: anns_by_img.setdefault(ann[image_id], []).append(ann) for img_id, anns in anns_by_img.items(): img images[img_id] stem Path(img[file_name]).stem label_path out_root / labels / f{stem}.txt lines [] w_img, h_img img[width], img[height] for ann in anns: x, y, bw, bh ann[bbox] cx (x bw / 2.0) / w_img cy (y bh / 2.0) / h_img nw bw / w_img nh bh / h_img # 过滤完全越界的框保留部分越界的框并做裁剪 if nw 0 or nh 0: continue cx min(max(cx, 0.0), 1.0) cy min(max(cy, 0.0), 1.0) lines.append(f{cat_id_map[ann[category_id]]} {cx:.6f} {cy:.6f} {nw:.6f} {nh:.6f}) label_path.write_text(\n.join(lines), encodingutf-8) print(f写入 {label_path} 共 {len(lines)} 个目标) if __name__ __main__: coco_to_yolo(annotations/instances_train.json, images, yolo_dataset)参数说明img_root是图片目录转换脚本本身不复制图片只负责生成标签图片软链到out_root/images下即可这样可以省一份存储空间cats排序后按索引映射确保cat_id_map稳定对cx和cy做了 0 到 1 的截断对完全越界的框直接丢弃这能避免 YOLO 训练时出现 anchor 匹配异常。转换完成后我会随机抽 20 张图做可视化检查把标注框画回图片上确认坐标没有错位。这一步必不可少因为脚本逻辑正确不代表原始标注就正确。3.3 数据划分与增强先按图片切分再用针对性增强缓解类别不平衡数据集的划分方式在目标检测里直接影响评估可信度。一个常见的错误做法是按标注框的数量做随机划分结果同一个铁棍出现在训练集和验证集的不同图片里导致验证指标虚高。因为传送带异物数据集里同一个物体经常出现在连续帧中按图片划分也不完全安全。我通常的做法是先用时间戳或视频片段编号把相近的帧分到同一个组按组划分确保训练集和验证集之间没有来自同一个物体运动轨迹的样本。如果数据集本身没有视频来源信息那就只能按图像哈希去重后随机按 8:1:1 划分训练、验证、测试并在训练时关闭 shuffle 的随机种子来保证可复现性。目标检测里类别不平衡是个老生常谈的问题但在传送带异物场景里格外严重——铁棍出现频率可能只有垃圾的十分之一而某些罕见垃圾可能只有十几个标注框。针对这种数据集单纯靠损失函数里的类别权重是救不回来的常见做法是在训练时做类别感知的采样让每个 batch 里都保证包含一定比例的少数类样本。YOLOv8 的数据加载器本身不直接支持这个功能我的处理是在预处理阶段把少数类样本重复复制几份或者用复制粘贴增强把铁棍的标注框连同像素区域剪贴到不含异物的背景图里这样既增加了样本量又保留了真实标注质量。复制粘贴增强在传送带场景特别好用因为传送带背景高度重复异物区域和背景的边界清晰粘贴一个铁棍到另一张空传送带图上视觉上几乎没有破绽。对于垃圾这类形状不规则的目标粘贴效果稍差但对训练而言也远好于没有样本。4. 用 YOLOv8 训练自己的数据集命令、参数与第一次评估4.1 第一步先把目录组织和数据配置做好再考虑调参YOLOv8 训练自己的数据集的目录结构以 data.yaml 为入口这个文件决定了训练时去哪里找图片和标签。很多初学者拿到 COCO 数据集转换完就直接开始训练结果报错找不到标签文件或者类别数量对不上绝大多数是 data.yaml 里路径写错或者类别列表顺序和转换脚本不一致。我统一用的目录布局是yolo_dataset 下包含 images 和 labels 两个目录每个目录里再按 train、val、test 分子目录图片路径用相对路径配合 data.yaml 里的绝对路径前缀这样换机器训练时只需要改一行配置。data.yaml 的内容很关键它把数据集的物理路径和类别语义绑定在一起。假设我们转换后的类别顺序是铁棍索引 0和垃圾索引 1data.yaml 里的 names 必须和这个顺序一致否则模型学到的标签就会张冠李戴。以下是一个可以直接用的最小配置训练和验证图片路径指向各自的子目录nc 表示类别数。# data.yaml path: /data/foreign_matter/yolo_dataset # 数据集根目录按机器改 train: images/train val: images/val test: images/test nc: 2 names: 0: iron_bar 1: trash逻辑说明path是根目录train和val是相对于根目录的子路径。这里有一个细节YOLOv8 允许 train 和 val 是图片文件列表的 txt 文件路径也允许是目录我个人推荐用目录省去了维护 txt 列表文件的麻烦。nc是类别总数必须和 names 的条目数一致names 的键值顺序必须是 0、1、2 这样的连续整数这个顺序直接对应训练输出的类别索引也对应标签文件里每行开头那个数字。然后就是启动训练。训练命令我在项目里是固定的写法第一次跑的时候先不加任何花哨的参数目标是跑通流程并获得一个基线指标。下面这个命令用 yolov8m 作为预训练权重输入图像尺寸设成 1280批次大小根据显存调整训练 150 个 epoch。yolo detect train \ data/data/foreign_matter/yolo_dataset/data.yaml \ modelyolov8m.pt \ epochs150 \ imgsz1280 \ batch16 \ device0 \ projectexperiments \ nameforeigm_matter_v1参数说明imgsz1280听上去只是分辨率但它决定小目标还能不能被模型看到。传送带异物检测的铁棍宽度可能只有 30 像素如果用默认的 640缩放到 1280 之后铁棍的特征还能保留下来一些。代价是显存占用翻倍batch 从 32 降到 16 是正常操作。project和name指定训练结果输出目录每次训练的结果都会存到这里包括最后的权重文件 weights/best.pt 和 weights/last.pt。第一次训练不必追求最优重点是确认 loss 曲线能够下降、验证集的 mAP 不是 0。如果显存不够跑 1280还有一个更通用的下位替代方案保持 imgsz640 训练然后在推理时用更大的 imgsz因为 YOLO 的推理分辨率可以和训练分辨率不一致。但要注意训练和推理分辨率差距太大会导致目标尺度失配小目标的召回率反而下降。升级显卡或者用切图训练是更治本的做法切图就是把 1920x1080 的原图切成四块 960x540 的图分别训练可以变相提高小目标的分辨率占比后面避坑章节会展开说。4.2 影响异物检测效果的关键参数imgsz、batch、anchor 与数据增强强度当基线跑通之后真正需要反复调的是下面这组参数。首先是imgsz它的影响在小目标场景里是决定性的。传送带异物数据集的宽度和高度与目标尺寸的比例跨度很大垃圾分类里既有几百像素的塑料瓶也有几十像素的碎石子如果模型只在 640 分辨率下训练感受野基本决定了碎石子这种小目标很难被正确检测。用 1280 训练之后小目标的召回率通常能提升十几个百分点这是我在多个工业视觉项目里反复验证过的结论不是玄学。第二个关键参数是 mosaic 数据增强。YOLOv8 默认开启 mosaic1.0它把四张图拼在一起训练对小目标检测很有帮助但对细长目标有副作用——铁棍一旦被拼图的边界切分训练样本里的目标形态就被破坏掉了。我的经验是把 mosaic 降到 0.5同时开启 copy_paste 增强也就是把少数类目标复制到其他图上对协调各类别样本数量更有效。YOLOv8 的增强参数可以在命令行直接覆盖比如mosaic0.5 copy_paste0.3。另外传送带现场的光照是相对固定的大幅度的 HSV 扰动反而会让模型学到不真实的变化所以我把 hsv_h、hsv_s、hsv_v 都调低到 0.01 左右保持背景纹理的稳定性。anchor 超参数往往被忽略但对长宽比极端的铁棍来说很关键。YOLOv8 在训练时默认会重新计算 anchor如果是自定义数据集训练日志里会出现 AutoAnchor 的信息。我的建议是让模型自动算一遍然后看一下打印出来的 anchor 尺寸如果最大 anchor 的宽高比和铁棍的长宽比差距太大手动指定一组带明显长条形状的 anchor 可以显著加速收敛。当然这属于进阶操作第一次跑不必动它。rag 还有一个容易翻车的地方是close_mosaic这个参数它控制在最后 10 个 epoch 关闭 mosaic 增强让模型在接近真实的分布上收敛。这个默认行为保持开启就好不要关掉否则模型会很长时间在拼接图上拟合推理时性能不佳。4.3 评估指标先看漏检率再看 mAP样本不均衡时的评估陷阱模型训练完后命令行会打印出一串指标其中 mAP50 和 mAP50-95 是最显眼的。但在异物检测这种类别极不均衡的工业场景里平均精度很容易欺骗人。如果垃圾有 1000 个样本铁棍只有 50 个样本模型把铁棍全部漏掉mAP50 仍然可能维持在一个不错的数值因为垃圾类别把整体指标拉上去了。所以在评估阶段我会先单独看每个类别的召回率尤其是铁棍和罕见垃圾的召回率确认模型没有把某个类别直接放弃掉。另一个评估陷阱是把验证集和训练集的类别分布搞成一样的。如果训练集里的图片大多只有垃圾验证集也这样分布模型大概率在真实场景里面对铁棍时表现骤降。所以划分数据集时就要刻意保证验证集里保留足够比例的稀有类别图片宁可验证集规模小一点也要让每个类别至少有 30 个样本。如果数据量实在不够可以用测试时增强对稀有类别的数据做多尺度推理也能得到更稳定的评估结果。评估阶段的阈值默认是 0.25我一般会另外导出一份置信度从 0.05 到 0.95 的 PR 曲线数据后续做阈值校准要用这比只看一个 mAP 数字可靠得多。5. 传送带异物数据集的 5 个常见坑与排查思路现象、原因、解法5.1 json 解析直接报错代码看起来没问题现象跑json.load时抛JSONDecodeError或者报错信息是json parse error: cannot deserialize value一类检查引号和括号都没有明显问题。原因这种问题十有八九出在编码和不可见字符上。Windows 上标注工具生成的 COCO 文件可能带 UTF-8 BOM 头encodingutf-8读出来第一个字符是\ufeffjson 解析器不认识它就报错另一类是文件里有全角引号是标注软件在 Windows 上写入时格式漂移或者有人手工编辑过 JSON 文件。解决读取文件时统一用encodingutf-8-sig而不是utf-8BOM 会被自动剥离。全角引号问题可以先跑一遍字符检查脚本把所有非 ASCII 的引号替换成标准引号再解析。我在实际项目中还遇到过 Windows 的记事本把 json 存成 UTF-16 的情况这种必须用转换工具统一转成 UTF-8 再做后续处理。血泪经验任何标注工具交付的 COCO 文件先脚本体检再动手永远不要相信应该没问题。5.2 bbox 越界或面积为 0训练 loss 变成 nan现象模型训练的 loss 曲线在某个 epoch 突然变成 nan或者某个类别的 AP 一直是 0检查数据时发现少量标注框的坐标是负数或者 w 和 h 为 0。原因标注工具在拖拽框时容易出现误操作或者程序导出时坐标计算错误。COCO 官方评测对这类问题是容忍的因为评测只算指标但 YOLO 训练时数据增强会把归一化坐标再做缩放和平移脏坐标会被放大成完全不合理的目标框直接导致数值溢出。解决在转换脚本里对 bbox 做检查按本文 3.1 节的方式先过滤完全越界的框再对部分越界的框做裁剪。关键点w和h必须严格大于 0面积为 0 的框直接丢弃不要保留后硬编码成最小尺寸那样会在训练时引入一个永远无法预测的噪声目标。5.3 铁棍这种细长目标在缩放后几乎看不见现象训练集单独看各类别 mAP 都正常但一到验证集铁棍的召回率明显低于垃圾把训练图片画出来看铁棍在 1280 分辨率下还能辨认但在模型实际输入的分辨率下非常细。原因铁棍的宽度只有 20 到 40 像素长宽比接近 1:20YOLO 的默认 anchor 是基于自然图像设定的对这种极端长宽比的回归目标anchor 匹配阶段的 IoU 很难达标导致大量铁棍样本在训练时作为背景被忽略。解决三个层面组合使用。第一是提升 imgsz这个前面提到了第二是使用切图策略把原图切成带重叠的块让铁棍在切块后的图上占据更多有效像素第三是检查自动生成的 anchor 尺寸如果训练日志里显示的 anchor 没有明显长条形的手动给 YOLO 配置一组比如在模型配置文件的 anchor 列表里加入长宽比为 1:8 和 1:16 的尺度。如果数据集里铁棍还有明显的倾斜角度并且多数是 45 度左右的斜向出现那么旋转目标检测是更好的方向但 v1 阶段先用切图和 anchor 调整就能拿到可用的效果。5.4 类别严重不平衡垃圾学得很好铁棍几乎不报现象训练完看每类的混淆矩阵垃圾的召回率在 0.9 以上铁棍只有 0.3加大训练轮数两个指标都不动。原因数据分布就是几百比几千模型交叉熵损失对多数类的梯度压制了少数类即使类别权重也无法完全纠正加上铁棍本身就是细长目标学习难度本来就比块状垃圾高双因素叠加导致这个结果。解决数据层面做复制粘贴增强把稀有类别的目标粘贴到空传送带背景图上训练层面对每个 batch 做类别感知采样让稀有类别在每个 batch 中的占比不低于 20%。这两步做完之后铁棍类别的召回率通常能从 0.3 提高到 0.7 以上。如果数据增强已经做足还不够最后的手段是采集更多铁棍样本这是成本最高但也最有效的方案不要指望模型能从无到有变出特征。5.5 现场漏检集中在光照变化段训练集里看不出问题现象模型在白天测试效果不错傍晚或者传送带上方灯光开启后漏检率突然升高同一批测试图片在训练时数据增强后的表现却正常。原因这是典型的域偏移。训练集抽帧时间集中在白天如果采样时没有覆盖不同时段的光照条件模型会把亮度当作背景特征的一部分一旦现场光照变化分布就和训练集产生了偏移。解决在采集阶段按时间段分层抽样早上、中午、傍晚、灯光全开四个条件下各抽一部分帧。如果数据集已经固定没有条件补采可以在训练时把亮度增强适当调到 0.05 到 0.1用数据增强模拟光照变化这个方法能缓解但不能根治。真正上线前最好留出一批涵盖不同光照条件的现场视频作为最终验收集用的是模型从未见过的金标准数据防的就是这种自欺欺人的评估。6. 从训练集到传送带现场用置信度阈值校准和样本回流兜底模型训练好只是第一步把权重放到传送带现场能稳定运行还要过两道坎一是置信度阈值怎么定二是现场漏检的样本怎么回流进训练集。置信度阈值不能直接用默认的 0.25。在实验室数据上0.25 可能达到最优的 F1但现场对误检的容忍度极低频繁报警会让工段长直接关掉系统。我的做法是留出 200 到 300 张现场图片包含正负样本跑一遍推理收集每个预测框的置信度然后用一小段脚本遍历不同阈值下的精确率和召回率找到目标漏检率和最大可接受误报数对应的阈值。下面的脚本就是做这个事的输入是模型跑出来的结果文件每行包含图片名、类别、置信度和坐标。import json def find_threshold(preds, gt, target_recall0.95): # preds: 模型输出每个元素是 [img_id, cls, conf, x, y, w, h] # gt: 真实标注按图片聚合后的字典 scores sorted([p[2] for p in preds], reverseTrue) best_t, best_f1 0.25, 0.0 for t in scores: tp fp 0 for img_id, cls, conf, *_ in preds: if conf t: continue if img_id in gt and cls in gt[img_id]: tp 1 else: fp 1 fn sum(len(v) for v in gt.values()) - tp recall tp / (tp fn) if (tp fn) else 0 precision tp / (tp fp) if (tp fp) else 0 if precision recall 0: f1 2 * precision * recall / (precision recall) else: f1 0 if recall target_recall and f1 best_f1: best_t, best_f1 t, f1 return best_t, best_f1参数说明target_recall0.95表示默认要求模型把 95% 的真实目标都找出来然后在这个前提下选 F1 最高的阈值。这个脚本的关键在于结果要和真实标注对齐这里用的是简单的图片 类别匹配更严格的做法是按 IoU 匹配预测框和真实框。实际场景里漏检的代价往往高于误检所以阈值不要只看 F1要按业务风险调低或调高。项目里最终选定的阈值往往比默认 0.25 高不少因为现场负样本占比远高于训练集。部署之后持续收集误检和漏检样本每个星期把新增样本合并进训练集重新训练一轮这种迭代习惯比任何调参都管用。我经历过最大的教训就是以为训练完权重就结束了结果现场跑了一个月漏检的塑料袋形态从来没见过模型毫无办法。这些现场样本才是数据集里最值钱的部分。希望这个方向能帮你在自己的生产线上少走两步弯路。本文还有配套的精品资源点击获取
企业数字化 ERP 产品动态
相关推荐
Linux signal函数详解:从入门到实战,避开信号处理常见坑 先纠正一个拼写问题:标题里的singal应该是signal,这是 Linux 下信号处理最常用的接口之一。我在不少新人的代码里见过这个拼写,编译直接报错,因为头文件里根本没有这个符号。signal函数虽然看起来只有一行声明,但背后牵… · 2026/9/23 18:05:19
C# Web Forms三合一后台系统:OA+CRM+ERP实战源码解析 简介:这是一套面向计算机专业本科生毕业设计与初学者进阶实践的C#全栈后台管理系统源码,融合OA、CRM与ERP三大企业级功能模块,适用于课程设计、毕设开发及中小型企业内部管理平台原型构建。资源共2000个文件,涵盖498个C#业务逻辑文… · 2026/9/23 18:05:13
Java端口扫描器教学实践:TCP/UDP协议解析与课设实现 简介:这是一份面向计算机网络课程学习者与初阶开发者的Java端口扫描器实践项目,聚焦TCP/UDP协议层探测能力训练,适用于课程设计、工程实训及毕设选题参考。资源包共12个文件,含2个核心Java源码(实现多线程扫描逻辑&… · 2026/9/23 18:05:13
3个步骤搞懂火热的死亡:前端避坑指南 3个步骤搞懂火热的死亡:前端避坑指南 刚学完 if-else 和循环,代码能跑,一搭项目就崩?别慌,这几乎是每个开发者的必经之路。很多新手卡在“语法会写,项目不会搭”的鸿沟里,反复查文档却找不到头绪。这篇避坑指南不讲虚的,直接拆解一个典型故… · 2026/9/23 20:21:26
意间AI绘画手写实现:3步搞定项目搭建避坑指南 意间AI绘画手写实现:3步搞定项目搭建避坑指南 刚毕业那会儿,我拿着Python语法书,看着满屏的 def 和 class ,脑子是清醒的,但手是废的。为什么?因为 学会语法却不知怎么搭项目 。你懂 for… · 2026/9/23 20:21:20
面试突击:手写实现“头很痛怎么办”背后的算法逻辑 面试突击:手写实现“头很痛怎么办”背后的算法逻辑 是不是感觉脑子像浆糊一样,看了一堆教程还是不会写项目?别慌,这其实是大多数开发者的通病。很多兄弟在掘金技术社区发帖吐槽,说面试时遇到“头很痛怎么办”这种看似无厘头的问题,直接懵圈。其实,这根… · 2026/9/23 20:20:59
华为浏览器下载源码图解原理与实战拆解 华为浏览器下载源码图解原理与实战拆解 学会语法却不知怎么搭项目?这是很多初学者的通病。看着文档里的 download() 方法,心里没底,不知道底层到底发生了什么。今天咱们不聊虚的,直接通过 图解原理… · 2026/9/23 20:20:44
2026最新李连杰海啸版本升级避坑指南:API全变后如何快速恢复 2026最新李连杰海啸版本升级避坑指南:API全变后如何快速恢复 版本升级后 API 全变了,项目直接崩盘,这是很多老手和新人都没预料到的噩梦。2026最新的李连杰海啸(Li Jianjie Tsunami,简称 LJT)框架在 3.0… · 2026/9/23 20:20:37
智能体编程基本设计 智能体分层架构与抽象接口设计汇总本文汇总内容:智能体框架现状、BaseAgent 抽象基类、两种架构对比(Agent→Tool / Agent→Skill→Tool),可直接保存为 agent_arch.md目录
智能体编程接口现状:无全局统一标准方案A&… · 2026/9/23 20:20:30
3招搞定手机怎么下载微信面试难题实战项目解析 3招搞定手机怎么下载微信面试难题实战项目解析 面试被问“手机怎么下载微信”背后的原理,90%的人答不上来。别笑,这看似弱智的问题,实则是考察你对移动应用分发机制、安全校验及网络协议理解的试金石。我带过不少校招新人,他们背了八股文,却连一个A… · 2026/9/23 0:00:03
你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 面试被问“高并发下如何保证消息不丢失”,你张口就是“用Redis”,结果面试官追问“如果Redis宕机了怎么办”,你瞬间卡壳。这种场景太常见了,很多新手在背八股文时,只记住了技术名词… · 2026/9/23 0:00:29