YOLOV5水下目标检测数据集:5类别海鲜识别与训练实战指南

📅 发布时间:2026/10/11 20:21:35
YOLOV5水下目标检测数据集:5类别海鲜识别与训练实战指南
简介面向水下目标检测模型训练需求这份数据集聚成了1920×1080高分辨率的海鲜动植物图像覆盖海参、海胆、扇贝、海星、海草5个类别。高分辨率有助于保留水下小目标细节提升模型对模糊目标的辨识能力。数据已按YOLOV5标准目录组织含明确的训练集、验证集与测试集划分训练与验证图片均配套txt标注测试集独立用于最终评估同时提供类别字典文件可直接导入YOLOV5项目使用省去格式转换与手工标注环节。压缩包共2000个文件以txt标注/字典文件为主另附一个可直接运行的Python可视化脚本能随机读取图片绘制边界框便于快速核查标注质量数据目录按训练、验证、测试分文件夹存放命名规范便于快速接入训练流程。压缩包整体约469.75MB解压后数据约800MB属于中等规模数据集。目前已有597人学习下载适合水下目标检测方向的研究者、学生与算法工程师作为模型训练、算法验证或课程设计的现成数据基础。1. 先说这份数据集到底解决什么问题第一次把水下拍摄的图片喂给 YOLOV5 训练时很多人会发现模型在 COCO 上表现不错一换到水下场景就开始疯狂漏检海参认成海胆螃蟹的螯足被切断章鱼在深色背景下直接消失。这不是模型的问题是数据的问题——水下图像的光谱衰减、悬浮颗粒散射和低对比度让通用数据集训练出来的权重几乎不可用。这份「目标检测数据集(YOLOV5目录格式)大分辨率水下海鲜动植物目标检测数据集5类别」把从采集到标注再到训练目录格式的一条链路都做好了适合两类人一类是做水下机器人、渔业监测、海洋牧场巡检的工程师另一类是刚接触目标检测、手头没有合适数据、想拿一份现成数据把 YOLOV5 训练流程完整跑通的同学。2. 大分辨率和水下场景这份数据的两个核心前提2.1 为什么通用数据集在海鲜目标上不灵自然图像数据集比如 COCO、ImageNet 的子集里海鲜和水下环境的样本占比极低。更重要的是水下图像存在物理层面的特殊性红光在 5 米深度几乎衰减殆尽所以水下图像整体偏蓝绿悬浮颗粒造成对比度下降人工光源会导致中心亮、边缘暗的亮度不均。用通用预训练权重做微调时模型学到的纹理和颜色特征在水下场景是错位的。最典型的表现是海参在 COCO 预训练模型眼里更像「背景噪声」因为它的纹理和颜色在陆地物体里没有对应物。这里还有一层常常被忽略的问题——类别间的易混性。5 个类别常见的是海参、海胆、扇贝、海星、螃蟹具体以你拿到的数据标注为准在形态上高度相似海参和海胆都是椭圆的深色团块扇贝和海星都存在放射状纹理螃蟹在不同生长阶段颜色差异极大。如果训练集里每个类别的样本数不均衡模型大概率会把少数类直接吞掉。2.2 大分辨率到底意味着什么标题里「大分辨率」三个字不是营销话术。水下目标检测有两个天然痛点一是目标在画面中占比偏小比如远处海底的海参可能只有 40×30 像素二是细节纹理对判别很关键海参的刺、海胆的棘、扇贝的放射肋。低分辨率图像一旦缩放到 640×640 输入尺寸这些判别信息基本就丢了。大分辨率常见是 1920×1080 甚至 4000×3000给了两个选择空间第一可以用滑窗切图的方式把大图切成多个 640×640 的 patch 分别检测再合并结果第二可以在训练时让 YOLOV5 用更大的输入尺寸比如 1280×1280。前者适合推理阶段后者适合训练阶段。常见做法是训练时把大图等比缩放到合适尺寸并配合 mosaic 增强推理时对大图做切分两侧兼顾。注意大分辨率并不意味着直接原图进网络。YOLOV5 默认输入是 640×640你把 4000×3000 的图原样喂进去显存瞬间爆掉而且大量信息被 resize 压缩反而比小图更差。2.3 5 类别的数据集结构设计5 类目标的数据集在设计上有它的巧妙之处类少但每个类内部差异大。螃蟹有青蟹、梭子蟹、帝王蟹等不同形态海参有刺参、黑参等同一物种在不同水质、不同光照下的外观也会有巨大差异。这意味着数据集的「多样性」远比「数量」更重要——1000 张覆盖不同水域、不同光照、不同季节的图比 3000 张同一个水池拍的图有用得多。拿到数据后第一步应该做类别分布统计不是数文件夹里的文件个数而是数每张图里每个类别的目标框数量。目标检测的数据均衡要看「框数」而非「图数」一张图里有 50 个海胆和 50 张每张只有 1 个扇贝的图对 loss 的贡献方式完全不同。如果框数差距超过 3 倍后面训练时就需要调 loss 权重或做复制粘贴增强。3. YOLOV5 目录格式从目录树到标签文件的完整拆解3.1 标准目录树长什么样这份数据集的目录格式是 YOLOV5 的标准组织方式。你拿到手的时候应该是这样的结构dataset/ ├── images/ │ ├── train/ │ │ ├── img_0001.jpg │ │ ├── img_0002.jpg │ │ └── ... │ └── val/ │ ├── img_0101.jpg │ └── ... ├── labels/ │ ├── train/ │ │ ├── img_0001.txt │ │ ├── img_0002.txt │ │ └── ... │ └── val/ │ ├── img_0101.txt │ └── ... ├── data.yaml └── README.md这个结构是 YOLOV5 官方约定images和labels必须同名同路径对应YOLOV5 在训练时会通过替换后缀的方式自动找到标签文件。data.yaml是数据集的配置文件YOLOV5 启动训练时通过--data参数指定。有的数据集会把训练集和验证集合并放在images下再通过脚本按比例划分。这份数据既然已经分好了 train/val你就不需要再做划分直接改data.yaml里的路径就能训练。如果后续想加测试集按同样的目录结构放一份images/test和labels/test即可。3.2 data.yaml 的核心配置data.yaml是 YOLOV5 的数据入口内容类似这样# data.yaml path: /absolute/path/to/dataset # 数据集根目录 train: images/train # 训练图片路径相对于 path val: images/val # 验证图片路径 # test: images/test # 测试集可选 names: 0: sea_cucumber # 海参 1: sea_urchin # 海胆 2: scallop # 扇贝 3: starfish # 海星 4: crab # 螃蟹这里的路径坑很多。如果你用的是 Windowspath字段要写绝对路径而且反斜杠要转义或用正斜杠。如果你在本地跑通后要迁到服务器path必须重新改。names的索引顺序必须和标签文件里第一个数字对应否则模型会学到完全错位的映射关系。3.3 标签文件的格式与内容每张图片对应一个同名.txt文件每行代表一个目标框格式是class_id x_center y_center width height注意x_center y_center width height全部是归一化坐标即相对于图片宽高的比例值取值范围在 01 之间。举个例子一张 1920×1080 的图里某个扇贝的像素坐标是 x960, y540, w300, h200那标签行就是2 0.5 0.5 0.15625 0.185185其中0.15625 300/19200.185185 200/1080。很多新手第一次写标签时容易把像素坐标直接写进去YOLOV5 训练时 loss 会异常大并且完全无法收敛。我拿到数据后的第一件事是写一个脚本做完整性校验不是拿眼看而是跑一遍# check_labels.py import os from pathlib import Path def check_labels(img_dir, lbl_dir, num_classes5): img_paths list(Path(img_dir).glob(*.jpg)) errors [] for img_path in img_paths: lbl_path Path(lbl_dir) / (img_path.stem .txt) if not lbl_path.exists(): errors.append(f缺少标签: {lbl_path}) continue for line in lbl_path.read_text().strip().splitlines(): parts line.split() if len(parts) ! 5: errors.append(f格式错误: {lbl_path} - {line}) continue cls int(parts[0]) x, y, w, h map(float, parts[1:]) if cls num_classes: errors.append(f类别越界: {lbl_path} - {line}) if w 0 or h 0 or x 0 or y 0 or x 1 or y 1: errors.append(f坐标越界: {lbl_path} - {line}) if errors: print(f发现 {len(errors)} 个问题:) for e in errors[:20]: print(e) else: print(f校验通过: {len(img_paths)} 张图, 标签全部合法) # 使用示例 check_labels(dataset/images/train, dataset/labels/train, num_classes5)这段脚本做三件事检查同名标签是否存在、检查每行是否恰好 5 个字段、检查类别索引是否在合法范围内、检查坐标是否在 01 区间。这套校验跑通了训练时基本不会再遇到「标签解析失败」这类幺蛾子。很多所谓的数据集下载下来标签不是多了空行就是少了空格轻则警告重则直接中断校验脚本能帮你把这些坑挡在训练之前。3.4 类别分布统计脚本标签校验通过之后建议顺手统计类别分布。这一步决定了你要不要做类别重加权或用其他手段处理不均衡。# class_distribution.py from pathlib import Path from collections import Counter def count_boxes(lbl_dir): counter Counter() for lbl_path in Path(lbl_dir).glob(*.txt): for line in lbl_path.read_text().strip().splitlines(): cls int(line.split()[0]) counter[cls] 1 return counter train_cnt count_boxes(dataset/labels/train) val_cnt count_boxes(dataset/labels/val) class_names {0: sea_cucumber, 1: sea_urchin, 2: scallop, 3: starfish, 4: crab} print(训练集类别分布:) for cls in range(5): print(f {class_names[cls]}: {train_cnt.get(cls, 0)} 框) print(验证集类别分布:) for cls in range(5): print(f {class_names[cls]}: {val_cnt.get(cls, 0)} 框)如果发现某一类比另一类少一个数量级别急着改 loss先考虑是不是漏标了。水下数据集的标注难度极高海参贴在海胆旁边时经常被漏掉这种情况回看原图补标比任何算法层面的补救都更有效。4. 大分辨率图进 YOLO 训练前的预处理与检查4.1 读取图片时最容易翻车的三个点大分辨率水下图像在读取阶段有三个常见问题一是图片位深不是 8 位部分水下相机输出 16 位 TIFF 或 RAW直接读进 OpenCV 会得到全黑图或全白图二是 EXIF 旋转信息手机或部分运动相机拍的 JPG 带了旋转标记OpenCV 默认不处理导致图和标签错位三是色彩空间OpenCV 读进来是 BGRPyTorch 训练时要转 RGB这一步错了模型学到的颜色特征全是反的。建议在训练之前写一个批量检查脚本把每张图的尺寸、通道数、位深、文件大小打印出来快速定位异常图。下面的脚本可以在几分钟内扫描上万张图# inspect_images.py import cv2 from pathlib import Path def inspect_images(img_dir): img_paths list(Path(img_dir).glob(*.jpg)) issues [] for p in img_paths: img cv2.imread(str(p), cv2.IMREAD_UNCHANGED) if img is None: issues.append(f无法读取: {p}) continue h, w img.shape[:2] if len(img.shape) 2: issues.append(f灰度图: {p} ({w}x{h})) elif img.shape[2] 4: issues.append(f带透明通道: {p} ({w}x{h})) # 检查是否纯黑或纯白 if img.mean() 3 or img.mean() 252: issues.append(f疑似纯色图: {p} (mean{img.mean():.1f})) if issues: print(f发现 {len(issues)} 个问题:) for item in issues[:30]: print(item) else: print(f检查完成: {len(img_paths)} 张图全部正常) inspect_images(dataset/images/train)4.2 训练输入尺寸的选择逻辑大分辨率图进入 YOLOV5 时有两条路线一条是直接缩放到 640×640 或 1280×1280另一条是保持长宽比做 letterbox。YOLOV5 默认用的是 letterbox也就是等比缩放后填充灰边。填充的灰边在训练时是有效信息吗不是但 YOLOV5 的 loss 计算不会因为灰边而产生梯度所以影响不大。这里有一个参数层面的权衡--img设得越大小目标保留的像素越多但显存占用和训练时间也随之上升。对这份数据集来说如果目标在原始大图里普遍较小比如小于 64×64建议用 1280 而不是 640如果目标本身比较大占图面积超过 5%640 就够用。判断方法很简单随机挑几张图数一数里面最小目标的像素尺寸。4.3 用官方训练命令直接开始目录结构没有问题、图片检查通过后训练命令本身并不复杂python train.py \ --data dataset/data.yaml \ --weights yolov5s.pt \ --img 1280 \ --batch-size 16 \ --epochs 200 \ --cache ram \ --device 0这条命令里几个参数值得说明。--weights yolov5s.pt是官方 COCO 预训练权重用它做初始化比随机初始化收敛快得多因为 COCO 里已经有通用特征。--cache ram是把图片一次性加载进内存大幅减少训练时读盘的 I/O 开销。如果显存不够把--batch-size调到 8 或 4不要直接改小--img因为大分辨率是这个数据集的灵魂。注意--img 1280会让训练速度下降明显如果你的 GPU 显存小于 8G建议先用 640 跑通全流程确认模型能收敛再上 1280。第一次跑训练的核心目标是验证数据链路不是追求精度。4.4 超参数对这份数据集的特殊影响YOLOV5 自带的hyp.scratch-low.yaml是通用配置但水下场景有两个超参数需要单独关注。第一个是hsv_h、hsv_s、hsv_v三个颜色增强参数。水下图像颜色失真严重增强时如果随意加大饱和度扰动会进一步扭曲本来就稀缺的颜色信息。我一般会把hsv_s从默认的 0.7 降到 0.3hsv_v从 0.4 降到 0.2保留更多原始色彩分布。第二个是mosaic和mixup的启用程度。水下数据集一般规模不大mosaic能有效扩充样本多样性但要注意4 张图拼在一起后每个目标的像素面积变成原来的 1/4小目标进一步变小。如果数据集里小目标居多建议保持mosaic1.0但把mixup从默认调低到 0.1否则目标会被增强策略严重稀释训练出来的模型对小目标极不友好。5. 水下目标检测的 5 个常见坑与排查方法5.1 标签路径不匹配导致 val loss 为 0现象训练正常启动train loss正常下降但val loss一直是 0验证集的 mAP 全部为 0。原因YOLOV5 找不到验证集标签。data.yaml里val路径配置错误或验证集文件夹里图片和标签的命名不一致。解决先检查data.yaml里path和val的拼接是否正确。再看验证集每张图是否都有同名.txt标签。最直接的方法是单独指定验证集跑一次val.py观察控制台输出里有没有Scanning阶段报错。5.2 大图缩小后目标小到无法检测现象训练时 mAP 一直很低尤其小目标基本全部漏检查了标签也没发现问题。原因原图是 4000×3000目标在原始分辨率下是 100×100 像素缩放到 640×640 后变成 16×16 像素已经低于 YOLOV5 的检测下限大约 8×8 像素。这是分辨率缩放导致的信息丢失不是模型问题。解决把--img提到 1280 或 1536或者改用滑窗切图方案训练时把原图切成上下左右四个 patch每个 patch 作为独立训练样本。推理时同样方式切图检测结果再映射回原图坐标做合并。5.3 类别不平衡导致海参被学成海胆现象训练到后期海参的 recall 明显低于其他类有些海参直接被识别为海胆。查了训练集的类别分布发现海参框数只有海胆的三分之一。原因目标检测的 loss 是所有类别的加权平均占比大的类别主导梯度方向。模型倾向于把模棱两可的样本判给高频类。解决最干净的做法是把海参的漏检样本补标进训练集把两个类的框数拉平衡。补标之后如果仍然不均衡给低频类提高 loss 权重在class_weight里把海参的权重设为 23。另外可以考虑做针对性的复制粘贴增强把海参目标从背景干净的区域裁出来粘贴到海胆密集的区域人为制造难例。5.4 水下图像的亮度不均烧坏模型现象训练 loss 正常下降但推理时同一张图左半边能检出、右半边全漏检或者在暗光区域出现大量误检。原因水下人工光源造成中心亮、边缘暗模型学到了「亮度」这个伪特征把暗区域当作背景。这是水下场景的典型翻车点。解决在训练前对图像做自适应直方图均衡化CLAHE降低光照不均的干扰。在数据增强层面加一点亮度扰动但不要太大。推理时如果现场光照条件可控尽量用均匀光源比任何算法都有效。5.5 标签坐标是像素值导致 loss 异常大现象训练启动后box_loss高达 20 以上且下降极其缓慢mAP 变化不大。原因标签文件里的坐标没有归一化写的是像素值。YOLOV5 期望 01 的浮点数喂进去的坐标超过范围后IoU 计算全部失真。解决用第一节的校验脚本扫描所有标签找出坐标值大于 1 的行。然后写脚本把所有坐标除以对应的图片宽高重新生成标签文件。这个问题在手工标注然后转换格式的数据集里极其常见这份数据如果也是从其他格式转换来的值得警惕。6. 把这份数据用好的三个习惯验证划分、增强边界与迁移策略第一个习惯不要相信默认的 train/val 划分先看看 val 集的类别分布是否和 train 接近。如果 val 全是晴天拍摄、train 全是阴天拍摄模型在验证集上的表现就是虚假的。重新划分时按「视频片段」而不是按「单帧」来切同一个视频片段里的相邻帧高度相似如果一部分在 train、一部分在 val验证指标会虚高。常见做法是把同一个采集批次的数据整体放到 train 或 val而不是随机打散。第二个习惯增强策略要克制。水下数据的天然扰动光照、浑浊度、视角已经足够多不需要像通用目标检测那样做激进的增强。我一般保留 mosaic、随机翻转和轻微的颜色扰动关掉copy_paste或降到 0.1。另外水下图像不适合做垂直翻转——海底目标几乎不会以倒置视角出现垂直翻转只会让模型学到无效特征。第三个习惯用小模型把 pipeline 跑通再上大模型。先用yolov5s.pt跑 100 epoch观察 loss 曲线是否正常下降验证集 mAP 是否稳步上升。确认数据链路没问题后再换yolov5m.pt或yolov5l.pt。这种做法能帮你在 30 分钟内定位到数据集问题而不是花两个小时训练完一个 5 类别的模型之后才发现标签路径错了。注意验证集的作用是反映真实分布不是刷分。如果你发现 val mAP 高但实际场景表现差回到「用采集批次划分数据」这个原则审视你的划分逻辑。训练结束后保留最优权重和最后一轮权重两个文件最优权重用于部署最后一轮权重用于调试。YOLOV5 保存的best.pt和last.pt在训练几次中断后可能不够稳自己手动复制一份更可靠。到了部署阶段记得用--img相同尺寸导出 TorchScript 或 ONNX形状不对很容易在推理时出现reshape报错。这份数据本身是大分辨率水下场景推理阶段我建议优先做「先切块、后检测、再合并」而不是直接整图输入。前面提到过整图缩放到 640 对小目标不友好而切块方案在 1920×1080 的图上切成 2×2 的 patch每个 patch 约 960×540缩放到 640 时信息损失远小于整图缩放。切块方案需要多写一个坐标映射逻辑但这也是把大分辨率数据价值榨干的标准姿势。做数据集项目这一年下来我最大的教训是数据质量检查永远值得多花两小时而训练只在数据确认无误后才开始。很多次翻车不是因为模型不够好而是因为标签某一行多了个空格、某一张图损坏、某个类别索引错位。希望这份数据能帮你少走这些弯路。本文还有配套的精品资源点击获取