简介面向海洋目标检测需求的 YOLO 数据集及其配套训练资料包适合需要真实场景图片训练 YOLO 系列模型的开发者、研究人员或课程学员。数据集包含 1000 张高质量海洋场景图片采用 LabelImg 标注提供 VOCxml、COCOjson、YOLOtxt三种格式标签分别存放于不同文件夹可直接用于模型训练。压缩包共 2000 个文件除 1000 个 xml 和 990 个 txt 标签外还含 6 个说明教程html、3 个数据集划分脚本py和 1 个配置文件yaml整体大小约 23.38MB便于快速下载。附赠 YOLO 环境搭建与训练教程区分 Windows/Linux 版本以及数据集划分脚本可自行划分训练集、验证集与测试集并支持从环境配置到训练验证的完整流程。该资源已有 413 人浏览学习配套教程与脚本能有效降低上手门槛帮助用户快速将标注数据转化为可用检测模型。1. 海洋目标检测数据集的第一个坑格式做海洋目标检测的人都有过这种经历网上找来的数据集要么是遥感影像裁出来的要么是水下机器人拍的模糊帧真正贴近岸基监控、船载摄像头视角的高质量数据少得可怜。更麻烦的是标注格式五花八门——有人给VOC的XML有人给COCO的JSON还有人只给YOLO的txt。而YOLO系列从v5到v8官方训练接口虽然统一了但数据预处理仍然绕不开“把标注转成自己需要的格式”这一步。这套海洋目标检测数据集的价值在于它把1000张真实场景图片同时做成VOC、COCO、YOLO三份标签还附带划分脚本和训练教程拿到手不用再写格式转换的重复代码直接进训练流程。适合正在做船舶、浮标、鱼类等海面目标检测的工程师也适合刚接触YOLO、需要一套完整数据链路练手的学生。2. VOC、COCO、YOLO三种标签的共存逻辑2.1 数据集目录结构与存放约定解压后的大致目录会是这样实际以压缩包内为准dataset/ ├── images/ ├── labels_voc/ # 存放xml文件 ├── labels_coco/ # 存放json文件 ├── labels_yolo/ # 存放txt文件 └── scripts/ # 划分脚本和教程html图片统一放在images下三种标签按类型分目录。这样做的好处是训练时目录隔离互不干扰。如果你想把三种格式合并到一套目录里后面会提到怎么用脚本做交叉验证。2.2 VOC的XML标注坐标是绝对的VOC格式用XML描述每个目标的类别和边界框。打开一个xml文件核心节点长这样annotation folderimages/folder filename0001.jpg/filename size width1920/width height1080/height depth3/depth /size object nameship/name bndbox xmin320/xmin ymin240/ymin xmax780/xmax ymax690/ymax /bndbox /object /annotationxmin, ymin, xmax, ymax是像素坐标系下的绝对坐标左上角为原点。注意VOC允许同一张图有多个object节点每个节点对应一个目标。这套数据集的标注框用labelimg产生框贴合目标边缘质量比较稳定。2.3 COCO的JSON把标注折叠成字典COCO格式把整张图片的标注信息集中在一个JSON文件的annotations数组里。每个标注元素包含image_id、category_id、bboxx, y, width, height和segmentation可以是多边形或多段线。这套数据集的目标是检测任务segmentation通常给的是矩形四角坐标或多边形近似。{ images: [{id: 1, file_name: 0001.jpg, width: 1920, height: 1080}], annotations: [ {id: 1, image_id: 1, category_id: 0, bbox: [320, 240, 460, 450]} ], categories: [{id: 0, name: ship}] }COCO的bbox是[x, y, width, height]和VOC的[xmin, ymin, xmax, ymax]不是同一个东西。如果自己写转换脚本别漏了width xmax - xmin这一步。2.4 YOLO的txt归一化坐标和类别索引YOLO格式每行一个目标格式为class_id x_center y_center width height所有坐标值都除以图片宽高归一化到0~1之间。类别索引从0开始比如0代表ship1代表buoy。一个典型的txt文件0 0.423 0.456 0.218 0.377 1 0.812 0.678 0.105 0.089这套数据集里三个文件夹的标签文件与images下的图片文件名一一对应除了后缀名不同。文件名的对应关系是训练时最容易出错的地方——如果图片叫0001.jpgYOLO的标签必须叫0001.txt否则训练直接跳过该图片。2.5 三种格式的换算关系从VOC到YOLO的转换公式如下假设图片宽为W、高为Hx_center (xmin xmax) / 2 / W y_center (ymin ymax) / 2 / H box_width (xmax - xmin) / W box_height (ymax - ymin) / H反过来从YOLO转VOC则是xmin int((x_center - width / 2) * W) ymin int((y_center - height / 2) * H) xmax int((x_center width / 2) * W) ymax int((y_center height / 2) * H)肉眼检查标签是否正确时可以把这些坐标画回图片上。下面这段脚本用OpenCV读取图片和YOLO标签画出边界框import cv2 img cv2.imread(images/0001.jpg) h, w img.shape[:2] with open(labels_yolo/0001.txt) as f: for line in f: cls, xc, yc, bw, bh map(float, line.split()) x1 int((xc - bw / 2) * w) y1 int((yc - bh / 2) * h) x2 int((xc bw / 2) * w) y2 int((yc bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(img, str(int(cls)), (x1, max(0, y1 - 5)), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) cv2.imwrite(check_0001.jpg, img)这里用w和h把归一化坐标还原成像素坐标注意类别索引被直接当成字符串显示。如果你想把类别名也显示出来需要先读取数据集的类别列表文件一般叫classes.txt或写在训练配置里。3. 划分脚本从手工拖拽到一行命令3.1 为什么要自己划分训练集、验证集、测试集很多开源数据集会打包好固定的train/val/test划分但实际项目里你需要根据拍摄时间、场景分布、目标密度来决定划分比例。比如极端天气的图片应该均匀分配到三个集合里而不是都堆到训练集。这套资源附带了三个Python脚本分别实现“图片标签整体划分写入新文件夹”和“生成ImageSets下的txt索引”。先用普通划分脚本处理再用它生成YOLO训练所需的列表文件。3.2 按比例把图片和标签拷贝到新目录核心逻辑是读取所有图片文件名随机打乱按比例切分成三份然后分别把图片和对应的标签文件复制到目标目录。参考实现如下import os import random import shutil source_images images source_labels labels_yolo target_root split_dataset train_ratio, val_ratio, test_ratio 0.7, 0.2, 0.1 assert train_ratio val_ratio test_ratio 1.0 names [f[:-4] for f in os.listdir(source_images) if f.endswith(.jpg)] random.shuffle(names) n_train int(len(names) * train_ratio) n_val int(len(names) * val_ratio) splits { train: names[:n_train], val: names[n_train:n_train n_val], test: names[n_train n_val:], } for split, file_stems in splits.items(): img_dir os.path.join(target_root, images, split) lbl_dir os.path.join(target_root, labels, split) os.makedirs(img_dir, exist_okTrue) os.makedirs(lbl_dir, exist_okTrue) for stem in file_stems: shutil.copy(os.path.join(source_images, stem .jpg), img_dir) shutil.copy(os.path.join(source_labels, stem .txt), lbl_dir)random.shuffle做一次全局打乱保证每个集合里的场景分布大体一致。如果你希望按时间或场景分组就不能这么写得先给图片打上分组标签再按组划分。3.3 生成VOC风格的ImageSets索引VOC训练时代需要在ImageSets/Main下生成train.txt、val.txt、test.txt每行放图片的相对路径无扩展名。这个脚本对后续用YOLOv5或YOLOv8的官方代码也有效因为很多教程会要求你提供一个train.txt和val.txt列表。import os def write_list(file_path, stems): with open(file_path, w) as f: for stem in stems: f.write(images/ stem \n) splits {train: n_train_names, val: n_val_names, test: n_test_names} os.makedirs(ImageSets/Main, exist_okTrue) for split, names in splits.items(): write_list(fImageSets/Main/{split}.txt, names)这个列表文件里默认写的是images/前缀训练时会拼上你的数据集根目录。如果你把图片放在子目录里记得调整这里的前缀。3.4 划分后必须做的完整性校验划分脚本跑完先别急着训练。检查三件事第一train/val/test里的图片数量和标签数量是否一一对应第二标签文件里的类别索引是否都在配置的类别范围内第三有没有某些类别的目标数量太少导致某个集合里完全没出现过该类。写一个几分钟内能跑完的校验脚本import os def validate(labels_dir, num_classes): class_count [0] * num_classes for f in os.listdir(labels_dir): if not f.endswith(.txt): continue with open(os.path.join(labels_dir, f)) as fp: for line in fp: cls int(line.split()[0]) if cls num_classes: print(f越界类别: {f} - {cls}) class_count[cls] 1 print(各类别数量:, class_count) validate(split_dataset/labels/train, 4)如果你发现val里某个类别的目标数为0最好把该类的部分图片重新划分进去否则验证集的mAP会虚高或失真。YOLO训练时验证集的作用是反馈模型在未见数据上的表现类别缺失会让这个反馈失去意义。4. 从零跑通YOLO训练环境、配置、命令4.1 Windows和Linux环境搭建的差别这套资源附带了两个平台的教程Linux版的YOLO环境搭建和Windows版的训练教程。实际部署时Windows最常见的坑是CUDA和PyTorch版本不匹配。我的建议是直接装Anaconda用虚拟环境隔离依赖。下面是Linux下的典型安装流程。conda create -n yolo python3.9 -y conda activate yolo pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 pip install ultralyticsWindows上如果安装失败多半是CUDA版本的问题。先运行nvidia-smi查看驱动支持的CUDA版本再选择对应的PyTorch轮子。不要盲目装最新版YOLOv8的代码对PyTorch版本不敏感但显卡驱动太旧会导致CUDA error: no kernel image is available。4.2 修改数据配置文件以YOLOv8为例训练自己的数据集需要新建一个YAML文件指向图片目录和类别名称# marine.yaml path: /path/to/split_dataset train: images/train val: images/val test: images/test nc: 4 names: [ship, buoy, fish, debris]path是数据集根目录train、val和test是相对路径。注意YOLOv8不再需要单独的train.txt文件它会根据这个YAML自动遍历目录下的图片。这套资源附带的数据集有1000张图数量不多如果你的目标类别超过10类建议先用预训练权重做迁移学习避免从零训练导致过拟合。4.3 启动训练与关键参数调整基础训练命令yolo detect train datamarine.yaml modelyolov8s.pt epochs100 imgsz640 batch16参数含义modelyolov8s.pt表示加载COCO预训练权重epochs100轮次imgsz640输入分辨率batch16批次大小。如果显存不够把batch降到8或4同时调整workers参数控制数据加载线程数。训练过程中重点看两个指标box_loss的下降趋势和mAP50-95的上升曲线。如果val的loss在某个epoch后开始上升而train的loss还在下降那就是过拟合的信号此时应该增加数据增强或减少训练轮次。4.4 训练集、验证集划分不均怎么办这套数据集的划分脚本默认按随机比例分但如果你发现某一类目标在训练集里特别多验证集里几乎没有建议用分层划分。基本思路是先按图片里包含的目标类别给图片分类再在每一类内部做随机切分。这样能保证每个集合的类别分布接近整体分布。from collections import defaultdict def read_classes(label_path): classes set() with open(label_path) as f: for line in f: classes.add(int(line.split()[0])) return classes class_to_images defaultdict(list) for f in os.listdir(labels_yolo): if f.endswith(.txt): classes read_classes(os.path.join(labels_yolo, f)) for c in classes: class_to_images[c].append(f[:-4]) # 在每个类别内部按比例划分再合并去重这样做会提高数据处理的复杂度但训练出来的模型更难出现“某类别在验证集上全错”的尴尬情况。对于海洋目标检测这类长尾分布明显的任务分层划分往往比随机划分效果更好。5. 让训练结果更稳的三个小技巧5.1 用labelimg复查标签既然数据集的标签是labelimg标注的那复查时也用labelimg最顺手。打开labelimg后把默认标签目录切换成labels_yolo图片目录指向images然后用快捷键“W”画框检查重点看两类错误一是边框是不是完全盖住目标尤其船舶的船头部分经常被漏标二是类别有没有混标比如浮标和渔船在远距离小目标情况下容易被标窜。发现错误标签后直接修改xml或txt再同步更新另外两种格式。这里建议在脚本里用voc2coco.py和voc2yolo.py这类工具做批量转换别手动改三个文件。5.2 数据增强的取舍YOLO内置的增强参数很多但海洋场景有自己的特点。海面反光、雾气、波浪纹路都会干扰检测训练时开启mosaic1.0和mixup0.2能增强模型对遮挡和背景混乱的鲁棒性。但注意mosaic增强在训练后期建议衰减到接近0否则模型在真实单图上的表现可能变差。model.train( datamarine.yaml, epochs100, patience20, augmentTrue, mosaic0.5, mixup0.2, hsv_h0.015, hsv_s0.7, hsv_v0.4 )hsv_h, hsv_s, hsv_v是颜色抖动参数海洋图片的颜色变化集中在蓝色系把饱和度抖动调高一点能让模型更好地适应不同深度的海水颜色。但不要把hsv_h调太大否则天空和海水会变成奇怪的紫色反而误导模型。5.3 推理时的置信度阈值和NMS参数训练完成后用yolo detect predict做推理建议先跑一批验证集图片画出来看看。如果漏检多把置信度从默认的0.25降到0.1如果误检多升到0.4。NMS的IoU阈值默认是0.45可以按密集程度调整船舶靠岸时互相遮挡严重把IoU阈值调到0.3能抑制重复框但也会把挨得近的船误合并。我的习惯是用max_det300限制每张图的最大检测数避免在拥挤海面上一口气输出几百个框。yolo detect predict modelruns/detect/train5/weights/best.pt sourcetest_images/ conf0.15 iou0.4 save_txtTrueconf0.15和iou0.4是一组比较均衡的参数适合大部分户外海洋监控场景。如果你检测的是水面小目标比如几公里外的浮标建议把输入分辨率imgsz从640提高到1280同时把conf再降一点。这会增加推理显存占用但小目标的召回率会有明显提升。最后把三种标签格式的转换脚本、划分脚本和训练参数组合起来才能让这套海洋检测数据集真正为你自己的项目服务。本文还有配套的精品资源点击获取