ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

海洋垃圾检测数据集实战:VOC/COCO/YOLO格式转换与YOLO11三平台训练脚本

海洋垃圾检测数据集实战:VOC/COCO/YOLO格式转换与YOLO11三平台训练脚本 简介这份资源面向从事水下视觉与目标检测的开发者、研究生及工程团队提供一套真实拍摄的海洋海底垃圾检测数据集可用于海底监控场景下的垃圾识别项目也可作为通用水下垃圾检测数据的补充。数据集共1000张高质量图像覆盖海底塑料、铁罐、纸张、海洋生物与垃圾同框、水下探测器与垃圾同框、打光拍摄等多种场景标注包含plastic、bio、rov、metal、paper、wood、rubber、timestamp、unknown九个类别采用labelimg标注质量较高。资源以PDF形式交付文件总数1个大小约2.77MB内附数据集基本情况介绍与获取方式并同步提供VOC、COCO、YOLO三种主流格式标签可直接接入YOLO等算法训练。此外还附赠YOLO11一键训练脚本支持GPU、CPU及MacM芯片多平台方案并给出博主训练结果日志供参考。目前已有540人学习适合希望快速验证模型、复现训练流程并积累水下检测经验的读者。1. 海洋垃圾检测数据集1000 张图、三种标签格式与三平台训练脚本到底怎么用手里有一份标注好的海洋垃圾检测数据集1000 张图同时给了 VOC、COCO、YOLO 三种格式标签还配了支持 GPU、CPU、Mac 三平台的 YOLO11 一键训练脚本——这个组合对做目标检测落地的人来说省掉的不是一点半点时间。海洋垃圾检测本身是个很实际的方向海面漂浮物、岸边塑料瓶、渔网碎片这些目标尺度差异大、背景杂乱、反光干扰强用通用数据集训出来的模型往往直接翻车。1000 张图不算多但胜在场景聚焦、标签齐全适合做小目标检测的快速验证和迁移学习起点。这篇文章面向的是想拿这份数据直接跑通训练、又不想在格式转换和环境配置上反复踩坑的从业者从数据长什么样、三种格式怎么选、脚本怎么改参数一路讲到训练崩了怎么排查。2. 三种标签格式的取舍VOC、COCO、YOLO 各自适合什么场景拿到一份同时带 VOC、COCO、YOLO 三种格式标签的数据集第一反应不应该是全都要而是先搞清楚每种格式在训练链路里扮演什么角色。选错了格式轻则多写一堆转换脚本重则标签解析出错、训练时 loss 直接不降。2.1 VOC 格式的结构与适用边界VOC 格式的核心是每张图对应一个 XML 文件里面用object节点记录每个目标的类别名和边界框坐标坐标是绝对像素值原点在左上角。它的典型目录结构是Annotations/放 XML、JPEGImages/放原图、ImageSets/Main/放训练验证划分的 txt。annotation filenameocean_0001.jpg/filename size width1920/width height1080/height /size object nameplastic/name !-- 类别名注意大小写要和类别表一致 -- bndbox xmin312/xmin !-- 绝对像素坐标不是归一化值 -- ymin540/ymin xmax398/xmax ymax612/ymax /bndbox /object /annotationVOC 的好处是可读性强用 LabelImg 打标直接产出这个格式人工检查标签时一眼能看出框对不对。但它的短板也明显坐标是绝对像素换分辨率就要重算一个 XML 一个目标文件1000 张图就是 1000 个文件批量处理时 IO 开销不小。我一般把 VOC 当作原始标注存档真正训练前一定转成 YOLO 格式。2.2 COCO 格式的 JSON 组织方式COCO 格式把所有标注塞进一个 JSON 文件用images、annotations、categories三个数组互相通过 id 关联。边界框是[x, y, width, height]同样是绝对像素但原点在左上角、宽高而非右下角坐标。{ images: [ {id: 1, file_name: ocean_0001.jpg, width: 1920, height: 1080} ], annotations: [ {id: 1, image_id: 1, category_id: 1, bbox: [312, 540, 86, 72], // x, y, w, h 绝对像素 area: 6192, iscrowd: 0} ], categories: [ {id: 1, name: plastic} ] }COCO 格式的优势是生态广很多评估脚本、可视化工具、预训练模型都吃这个格式做 mAP 评测时尤其方便。缺点是单文件体积大1000 张图的标注 JSON 动辄几 MB手改容易出错必须靠脚本生成。如果你的下游要做标准 COCO 评测保留这份格式如果只是训 YOLO它更多是个中转站。2.3 YOLO 格式为什么是训练首选YOLO 格式每张图对应一个 txt每行一个目标类别索引 中心x 中心y 宽 高后四个值全部归一化到 0~1。这是它和 VOC/COCO 最本质的区别——归一化坐标让模型对输入分辨率不敏感换 640 还是 1280 训练都不用改标签。# ocean_0001.txt 0 0.1849 0.5333 0.0448 0.0667 # 类别索引 中心x 中心y 宽 高均为归一化值对应的data.yaml负责把类别索引映射回名字path: ./ocean_dataset train: images/train val: images/val nc: 4 # 类别数必须和实际类别数一致 names: # 索引顺序必须和 txt 里的数字对应 0: plastic 1: fishing_net 2: bottle 3: foam注意YOLO 格式最容易翻车的地方是类别索引和 names 顺序对不上。txt 里写 0names 里第 0 个却是别的类训练照样跑但模型学到的全是错的mAP 低到怀疑人生还找不到原因。三种格式的定位可以这样记VOC 是标注存档COCO 是评测通用货币YOLO 是训练直用格式。1000 张图的数据集我一般保留 VOC 原始档、生成 COCO 备用、训练只用 YOLO。3. 从 VOC 到 YOLO 的转换脚本与四个边界坑数据集虽然号称三种格式齐全但实际拿到手经常发现 YOLO 标签缺几张、或者类别名不统一。自己写一遍转换脚本比盲目信任现成标签靠谱得多。这一章把 VOC 转 YOLO 的完整脚本拆开讲顺带把四个最容易踩的边界坑说透。3.1 转换脚本的完整实现import os import xml.etree.ElementTree as ET from pathlib import Path # 类别名到索引的映射顺序必须和 data.yaml 的 names 完全一致 CLASS_MAP {plastic: 0, fishing_net: 1, bottle: 2, foam: 3} def voc_to_yolo(xml_dir, img_dir, out_dir): xml_dir, img_dir, out_dir Path(xml_dir), Path(img_dir), Path(out_dir) out_dir.mkdir(parentsTrue, exist_okTrue) skipped [] for xml_path in xml_dir.glob(*.xml): tree ET.parse(xml_path) root tree.getroot() size root.find(size) w int(size.find(width).text) h int(size.find(height).text) lines [] for obj in root.findall(object): name obj.find(name).text.strip() if name not in CLASS_MAP: # 坑1类别名不在映射表里 skipped.append((xml_path.name, name)) continue cls_id CLASS_MAP[name] box obj.find(bndbox) xmin float(box.find(xmin).text) ymin float(box.find(ymin).text) xmax float(box.find(xmax).text) ymax float(box.find(ymax).text) # 坑2坐标越界裁剪到图像范围内 xmin, ymin max(0, xmin), max(0, ymin) xmax, ymax min(w, xmax), min(h, ymax) # 坑3宽高为 0 的退化框直接丢弃 bw, bh xmax - xmin, ymax - ymin if bw 1 or bh 1: continue # 归一化中心点 宽高全部除以图像尺寸 cx (xmin xmax) / 2 / w cy (ymin ymax) / 2 / h lines.append(f{cls_id} {cx:.6f} {cy:.6f} {bw/w:.6f} {bh/h:.6f}) # 坑4没有有效目标的图生成空 txt 还是跳过 if not lines: continue out_file out_dir / (xml_path.stem .txt) out_file.write_text(\n.join(lines)) if skipped: print(f跳过的类别: {set(s for _, s in skipped)}) return len(list(out_dir.glob(*.txt))) if __name__ __main__: n voc_to_yolo(./Annotations, ./JPEGImages, ./labels) print(f转换完成共生成 {n} 个标签文件)脚本逻辑分四步解析 XML 拿到图像尺寸、遍历每个 object 取类别和框、裁剪越界坐标并丢弃退化框、归一化后写入 txt。CLASS_MAP是唯一需要你手动对齐的地方类别名一个字母都不能差。3.2 四个边界坑的具体表现坑一类别名大小写和空格不一致。现象是转换后某些类别的目标凭空消失脚本打印出跳过的类别名。原因是标注时有人写Plastic、有人写plastic带尾空格。解决方式是在CLASS_MAP查找前先strip()并统一小写或者干脆先跑一遍统计所有出现过的类别名。坑二坐标越界。现象是训练时 YOLO 报non-normalized coordinates或坐标大于 1 的警告。原因是标注框超出了图像边界LabelImg 有时允许拖到画布外。解决方式是像脚本里那样用max(0, ...)和min(w, ...)硬裁剪。坑三宽高为 0 的退化框。现象是训练 loss 出现 NaN。原因是标注时误点产生了一个点状框宽高算出来是 0归一化后除零。解决方式是丢弃bw 1 or bh 1的框。坑四空标签图的处理。现象是训练时提示某张图没有标签。这其实不算错误——YOLO 允许背景图存在但要求有对应的空 txt 文件。如果你的数据集里混了纯背景图要么生成空 txt要么从训练集里剔除别让图片和标签对不上号。3.3 转换后的自检清单转完不要直接开训先跑一遍自检# 检查图片和标签是否一一对应 python -c from pathlib import Path imgs {p.stem for p in Path(./images).glob(*.jpg)} lbls {p.stem for p in Path(./labels).glob(*.txt)} print(有图无标签:, imgs - lbls) print(有标签无图:, lbls - imgs) 再抽查几个 txt确认类别索引在0 ~ nc-1范围内、四个数值都在 0~1 之间。这一步花两分钟能省掉后面几小时的排查。4. YOLO11 一键训练脚本三平台参数怎么改一键脚本的价值在于把环境差异封装掉但一键不等于不用改。GPU、CPU、Mac 三种平台的差异主要体现在设备参数、批大小和精度设置上改错一个参数要么跑不起来要么慢到无法接受。4.1 脚本的核心结构与设备参数一个典型的一键训练脚本核心就是加载模型、指定数据配置、设置训练超参、启动训练四步from ultralytics import YOLO def train(device0, batch16, epochs100, imgsz640, ampTrue): model YOLO(yolo11n.pt) # 从预训练权重起步小数据集强烈建议 results model.train( data./ocean_dataset/data.yaml, epochsepochs, imgszimgsz, batchbatch, devicedevice, # 0 表示第一块 GPUcpu 表示纯 CPUmps 表示 Mac ampamp, # 混合精度CPU 和部分 Mac 上要关掉 workers8, # 数据加载线程数Windows 上建议降到 4 以下 project./runs, nameocean_yolo11, patience30, # 30 轮无提升就早停小数据集防过拟合 ) return results if __name__ __main__: train()device是最关键的参数NVIDIA GPU 填0或多卡0,1纯 CPU 填cpuApple Silicon 填mps。填错会直接报设备不可用。4.2 GPU、CPU、Mac 三平台的参数对照平台devicebatch 建议ampworkers备注NVIDIA GPU016~32True8显存不足就降 batch纯 CPUcpu4~8False41000 张图训 100 轮可能要数小时Apple Siliconmps8~16False4部分算子 MPS 不支持会回退 CPUGPU 上ampTrue能省显存、提速但如果你用的是很新的卡或很旧的驱动混合精度偶尔会出 NaN这时先关掉 amp 验证是不是精度问题。CPU 上开 amp 没意义反而可能因为算子不支持报错。Mac 的 MPS 后端对某些算子支持不全遇到NotImplementedError就临时切回 CPU 跑通流程。4.3 小数据集的关键超参调整1000 张图属于小数据集默认超参直接套容易过拟合。我一般会动这几个model.train( data./ocean_dataset/data.yaml, epochs150, # 小数据集多训几轮配合早停 imgsz640, # 海洋垃圾目标偏小可试 960 提升小目标召回 batch16, lr00.001, # 初始学习率小数据集比默认 0.01 更稳 lrf0.01, # 最终学习率系数 warmup_epochs5, # 预热轮数防止初期梯度爆炸 mosaic1.0, # 马赛克增强小数据集靠它扩样本 mixup0.1, # 混合增强别开太大否则小目标被淹没 degrees10.0, # 旋转增强海面目标方向随机适度旋转有用 fliplr0.5, # 水平翻转 )imgsz从 640 提到 960 对小目标检测帮助明显代价是显存和耗时上升GPU 显存不够就退回 640。mosaic和mixup是小数据集扩样本的主力但mixup开太大比如 0.5会让小目标在叠加图里变得模糊反而伤召回。提示改超参一次只改一个跑完对比 mAP 再决定留不留。一次改五个参数涨了跌了都不知道是谁的功劳。4.4 训练启动与日志观察脚本跑起来后重点盯三个指标box_loss是否稳定下降、mAP50是否在涨、cls_loss有没有异常波动。前 10 轮 loss 不降先查学习率是不是太大mAP 一直卡在很低的值回去查标签格式和类别映射loss 出现 NaN查退化框和 amp 设置。训练完的权重默认存在runs/ocean_yolo11/weights/best.pt拿它做推理验证。5. 训练不收敛、显存爆、mAP 上不去排查清单训练跑不起来或者效果差八成不是模型的问题而是数据或配置的锅。这一章按现象 → 原因 → 解决整理五条最常见的踩坑记录都是我在实际项目里真金白银换来的。现象一训练一开始 loss 就是 NaN。原因通常是标签里有退化框宽高为 0导致归一化除零或者学习率设得过大。解决方式是先跑第 3 章的自检脚本确认没有零宽高框再把lr0从默认值降到 0.001 试一轮。现象二显存爆掉报 CUDA out of memory。原因是 batch 太大或 imgsz 太高。解决方式是先把batch减半还爆就把imgsz从 960 降到 640再不行开ampTrue。GPU 显存是硬约束别硬扛。现象三mAP50 一直卡在 0.1 以下。这种学了但没完全学的情况九成是类别索引和 names 对不上或者标签根本没被正确读取。解决方式是随便挑一张训练图用训练好的模型推理看输出的类别名是不是你期望的再打开对应的 txt 确认类别索引范围。现象四CPU 上训练慢到无法接受。原因是 CPU 训练本身就是慢1000 张图 100 轮可能要跑一整天。解决方式是先用epochs10跑通流程验证代码没问题再决定要不要上 GPU如果只有 CPU把imgsz降到 416、batch降到 4牺牲精度换速度。现象五Mac 上 MPS 报算子不支持。现象是训练中途抛NotImplementedError。原因是 MPS 后端对某些算子还没实现。解决方式是临时把devicecpu跑通或者升级 PyTorch 到较新版本很多算子支持是逐步补上的。注意排查顺序永远是先数据、后配置、最后模型。数据错了换多大的模型都白搭。6. 用验证集反查标注质量一个被低估的进阶技巧训练跑通只是开始真正决定模型上限的是标注质量。1000 张图的数据集人工标注难免有漏标、错标、框不准的情况而这些错误在 loss 曲线上往往看不出来。我习惯在训练后做一件事用best.pt在验证集上推理把预测框和真实标签叠在同一张图上对比专门找模型预测对了但标签没有和标签有但模型死活不预测的图。from ultralytics import YOLO import cv2 model YOLO(runs/ocean_yolo11/weights/best.pt) results model.predict(./ocean_dataset/images/val, conf0.25, saveTrue) # 重点看两类图 # 1. 模型预测出目标但原标签没有 - 可能漏标 # 2. 原标签有目标但模型置信度极低 - 可能错标或框不准 for r in results: if len(r.boxes) 0: print(f无预测: {r.path}) # 这些图优先人工复查conf0.25是推理置信度门限调低如 0.1能捞出更多疑似漏标调高如 0.5只看高置信预测。这个技巧的本质是把模型当成一个标注质检员——模型在大量数据上学到的共性能反过来暴露单张图上的标注异常。我一般会挑出 20~30 张可疑图人工复查改完标签再训一轮mAP 往往能涨几个点。这个收益比调超参来得实在因为超参调的是怎么学标注质量决定的是学什么。血泪经验是别一上来就换更大的模型先把这 1000 张图的标签抠干净小模型也能跑出能用的效果。数据质量这件事没有后悔药越早查越省事。希望帮到你。本文还有配套的精品资源点击获取
返回列表