简介本资源面向从事水下视觉与目标检测的算法工程师、研究生及竞赛选手提供一套真实场景海底鱼类检测数据集可用于海底监测场景下的鱼类识别项目也可作为通用鱼类检测数据的补充。数据集共1000张高质量图片覆盖浅海珊瑚礁、深海沉船周边、沙底海草区以及鱼类遮挡、严重遮挡等多种复杂场景统一划分为“Fish”单一类别采用labelimg标注并同步提供VOC(xml)、COCO(json)、YOLO(txt)三种主流格式可直接投入YOLO等算法训练。资源包为1个PDF文件大小约3.81MB内含数据集基本情况介绍与获取方式并附赠YOLO11一键训练脚本支持GPU、CPU及MacM芯片多平台训练方案同时提供博主训练结果日志供参考。目前已有90人学习适合希望快速验证模型、复现训练流程并积累水下检测经验的读者。1. 海底鱼类检测数据集1000 张图、三格式标签与 YOLO11 一键训练脚本做水下目标检测的同行大多有过这种经历模型在公开的 COCO 上跑得挺欢一换到水下场景就集体失灵鱼体轮廓糊、背景偏蓝绿、目标重叠严重标注还经常只有一种格式想换框架就得重标一遍。这份海底鱼类检测数据集就是冲着这个痛点来的——1000 张真实水下图像每张都配了 VOC、COCO、YOLO 三种格式的标签外加一份 YOLO11 一键训练脚本。它适合三类人刚入门目标检测想找个垂直场景练手的新手、做海洋牧场或水下机器人视觉的工程从业者、以及需要快速验证某个改进模块在真实数据上是否有效的研究者。数据集规模不大但胜在格式齐全、开箱即用省掉最耗时的数据清洗和格式转换环节。2. 三格式标签怎么选VOC、COCO、YOLO 的差异与转换逻辑拿到数据集第一件事不是急着训练而是搞清楚三种标签格式各自适合什么场景。选错了格式后面要么多写转换脚本要么在评估阶段对不上指标。2.1 三种格式的坐标表示与适用框架VOC 格式用 XML 存储坐标是绝对像素值结构是xmin ymin xmax ymax一个文件对应一张图。它的好处是可读性强标注工具支持最广LabelImg、Labelme 都能直接导出。缺点是文件数量翻倍1000 张图就是 1000 个 XML批量处理时 IO 压力明显。COCO 格式用单个 JSON 文件存所有标注坐标是[x, y, width, height]绝对像素通过images、annotations、categories三个字段关联。它适合做多任务检测分割关键点和需要统一管理的场景但 JSON 文件一旦损坏整个数据集标注全丢所以务必保留备份。YOLO 格式是每张图对应一个.txt每行class_id x_center y_center width height全部归一化到 0~1。它直接喂给 YOLO 系列训练不需要额外解析。缺点是类别是数字索引脱离classes.txt就不知道数字代表什么鱼。格式坐标类型存储方式直接适配框架典型坑VOC绝对像素每图一个 XMLFaster R-CNN、SSD文件多路径易错COCO绝对像素单 JSONDetectron2、MMDetectionJSON 损坏全丢YOLO归一化每图一个 txtYOLOv5/v8/v11类别索引需对照2.2 格式转换的核心代码与参数说明数据集虽然三格式齐全但实际项目中经常需要自己再转一次比如把 VOC 转成 YOLO 做数据增强后再转回去。下面这段脚本处理 VOC 到 YOLO 的转换重点在归一化和类别映射。import xml.etree.ElementTree as ET import os # 类别列表顺序必须与训练时 data.yaml 的 names 一致 classes [fish] # 若有多类鱼按实际顺序填写 def voc_to_yolo(xml_path, img_w, img_h, output_txt): tree ET.parse(xml_path) root tree.getroot() lines [] for obj in root.iter(object): cls_name obj.find(name).text if cls_name not in classes: continue # 跳过未定义类别避免索引越界 cls_id classes.index(cls_name) bbox obj.find(bndbox) xmin float(bbox.find(xmin).text) ymin float(bbox.find(ymin).text) xmax float(bbox.find(xmax).text) ymax float(bbox.find(ymax).text) # 归一化并转为中心点宽高 x_center (xmin xmax) / 2.0 / img_w y_center (ymin ymax) / 2.0 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}) with open(output_txt, w) as f: f.write(\n.join(lines))这段代码的关键参数有三个classes列表决定类别索引必须和后续data.yaml里的names严格对应img_w和img_h必须从对应图像读取不能硬编码因为水下图像分辨率可能不统一归一化保留 6 位小数是 YOLO 官方推荐精度位数太少会导致小目标框偏移。常见做法是先用 OpenCV 批量读取图像尺寸再逐张转换避免手动填错。注意VOC 的 xmin/ymin 是左上角xmax/ymax 是右下角转换时不要搞反否则框会翻转到图像外。2.3 COCO 与 YOLO 互转时容易忽略的细节COCO 转 YOLO 时annotations里的bbox是[x, y, width, height]其中x, y是左上角坐标不是中心点。很多人直接拿x, y当中心点算结果框整体偏移半个身位。正确做法是先算中心点x_center x width/2再归一化。另外 COCO 的category_id不一定从 0 开始连续YOLO 要求从 0 开始连续中间需要建一个映射表。YOLO 转 COCO 则相反要把归一化坐标乘回图像宽高并生成唯一的annotation id。这些细节在数据集自带的转换脚本里通常已经处理但如果你要自己改类别或增删数据最好把转换逻辑过一遍别直接套用。3. YOLO11 一键训练脚本拆解从 data.yaml 到训练启动数据集配了 YOLO11 一键训练脚本但“一键”不等于“无脑”。脚本背后涉及环境、配置、参数三块任何一块不对训练要么起不来要么指标异常。3.1 环境准备与依赖版本锁定YOLO11 基于 Ultralytics 框架环境要求不算苛刻但版本错位是翻车重灾区。常见做法是建一个干净虚拟环境按下面步骤走conda create -n fish_yolo python3.10 -y conda activate fish_yolo pip install ultralytics8.3.0 # 版本号以脚本实际依赖为准 pip install opencv-python pillow matplotlibPython 选 3.10 是因为 Ultralytics 对 3.11 的某些依赖兼容性还不稳定3.8 又偏旧。ultralytics版本必须和脚本里from ultralytics import YOLO的 API 匹配8.3.x 对应 YOLO11装成 8.0.x 会找不到yolo11n.pt。CUDA 版本根据显卡驱动来30 系卡建议 CUDA 11.8 以上否则训练时可能报no kernel image。装完跑一句yolo checks验证环境输出里能看到 GPU 是否可用。3.2 data.yaml 的路径与类别配置data.yaml是训练脚本和数据集之间的桥梁写错路径是最高频的启动失败原因。典型结构如下path: ./datasets/fish # 数据集根目录 train: images/train # 训练集图像相对路径 val: images/val # 验证集图像相对路径 test: images/test # 测试集可选 names: 0: fish 1: shrimp # 按实际类别增删path建议用相对路径方便整个项目迁移。train和val指向的是图像文件夹YOLO 会自动去找同级的labels文件夹里同名.txt。如果图像和标签不在同级目录需要在data.yaml里额外指定labels路径。names的键必须从 0 连续不能跳号否则训练时类别索引对不上模型会把虾预测成鱼。常见做法是先把data.yaml写好后用yolo train dataxxx.yaml跑一个 epoch看输出里nc类别数是否和预期一致。3.3 训练参数怎么调batch、imgsz、epochs 的取舍一键脚本通常给了一套默认参数但默认值不一定适合你的显卡和数据。下面是一段典型的训练启动代码from ultralytics import YOLO model YOLO(yolo11n.pt) # 加载预训练权重n 表示 nano 版 model.train( datadata.yaml, epochs100, # 水下数据少100 轮起步 imgsz640, # 输入分辨率小目标多可提到 1280 batch16, # 根据显存调8G 显存建议 8 或 16 device0, # 0 表示第一块 GPUCPU 填 cpu workers4, # 数据加载线程Windows 下建议 0 patience20, # 20 轮无提升则早停 lr00.01, # 初始学习率 augmentTrue # 开启内置增强 )epochs设 100 是因为 1000 张图属于小数据集太少欠拟合太多过拟合。imgsz默认 640但水下鱼群目标往往偏小提到 1280 能明显提升小目标召回代价是显存翻倍、速度减半。batch是显存杀手8G 卡跑 640 分辨率用 16 勉强跑 1280 就得降到 4 或 8。workers在 Windows 上设大于 0 有时会卡死这是血泪经验Linux 下可以放心用 4 或 8。patience设 20 是防止在某个局部最优反复震荡早停后拿best.pt就行。提示训练前先用yolo train datadata.yaml epochs1跑通流程确认没有路径和显存报错再开完整训练省得跑到一半崩了重来。4. 训练过程排查损失不降、显存溢出、指标异常的常见坑训练跑起来只是开始真正耗时间的是排查各种异常。下面几条是水下目标检测里高频出现的问题每条按现象、原因、解决来写。4.1 损失从第一轮就不降现象box_loss和cls_loss在头几个 epoch 几乎水平甚至上升。原因通常是学习率过大或标签格式错误。先检查data.yaml的names和标签文件里的类别索引是否一致索引对不上时模型学的是错误映射损失自然不降。再检查lr01000 张图的小数据集用 0.01 偏大可以降到 0.001 试试。如果标签里有大量空.txt无目标也会导致损失异常用脚本统计一下空标签比例超过 10% 就要考虑清理。4.2 显存溢出CUDA out of memory现象训练启动几秒后报RuntimeError: CUDA out of memory。原因无非三个batch太大、imgsz太高、模型太大。解决顺序是先降batch到 4 或 2再降imgsz到 416最后换yolo11s以下的小模型。如果降完还溢出检查是不是workers开太多导致数据加载占用显存设成 0 或 2。另外训练前用nvidia-smi看有没有其他进程占着显存僵尸进程不杀掉怎么调都白搭。4.3 验证集 mAP 波动大或为 0现象训练损失正常下降但验证集mAP50忽高忽低或者一直是 0。原因可能是验证集太小或分布和训练集差异大。1000 张图按 8:1:1 划分验证集只有 100 张指标波动是正常的可以看mAP50-95的平滑曲线。如果一直是 0检查验证集的标签路径是否写对YOLO 找不到标签时会静默跳过导致评估无效。还有一种情况是类别不平衡某类鱼只有几张图模型直接放弃该类需要做过采样或合并稀有类。4.4 训练中途 BN 层崩溃现象训练到几十轮突然报ValueError: Expected more than 1 value per channel指向 BatchNorm。原因是某个 batch 里只有一张图或某个通道全零BN 无法计算方差。水下图像如果有一批全黑或全蓝的废图就容易触发。解决方法是清洗数据集把标准差过低的图像剔除或者把batch调大保证每个 batch 至少 2 张有效图。如果还不行在模型配置里把 BN 的momentum调小增加稳定性。4.5 混淆矩阵总合不唯一现象训练结束看混淆矩阵发现行和列的总数对不上或者某些类别只出现在行不在列。这是 YOLO 评估时的常见现象原因是预测框和真实框的匹配用了 IoU 阈值低于阈值的预测不计入矩阵导致总数不守恒。不用慌看对角线上的值就行对角线越高说明分类越准。如果某个类别的对角线全是 0说明该类完全没学出来回去检查该类样本数量和标注质量。5. 进阶技巧用预训练权重和冻结层在小数据集上榨出更高 mAP1000 张图在目标检测里算小数据从头训练很难收敛到理想指标。我一般会走两条路一是用 COCO 预训练权重做迁移二是冻结主干前几层只训练检测头。下面这段代码演示冻结策略from ultralytics import YOLO model YOLO(yolo11n.pt) # 冻结前 10 层只训练后面的检测头 for i, (name, param) in enumerate(model.model.named_parameters()): if i 10: param.requires_grad False model.train( datadata.yaml, epochs150, imgsz960, batch8, freeze10, # 与上面手动冻结对应YOLO 内置参数 lr00.001, cos_lrTrue # 余弦退火后期学习率更平滑 )freeze10表示冻结前 10 层这些层学的是通用边缘和纹理特征水下场景和自然场景有差异但底层特征仍然可复用。cos_lrTrue让学习率按余弦曲线下降比阶梯下降更平滑小数据集上通常能多涨 1~2 个点 mAP。imgsz提到 960 是折中方案比 640 看得清小目标又比 1280 省显存。训练完用model.val()在测试集上跑一遍看mAP50和mAP50-95两个指标前者宽松后者严格工程落地更关注后者。还有一个技巧是测试时增强TTA在推理阶段对同一张图做翻转、缩放再合并预测框。YOLO11 里直接model.predict(source, augmentTrue)就能开。TTA 能涨点但推理速度降 2~3 倍适合离线评估不适合实时检测。从那以后我每次拿到新数据集都强制先跑一遍基线再开冻结和 TTA 对比确认涨点来自策略而不是随机波动。希望帮到你。本文还有配套的精品资源点击获取