简介:本资源为面向YOLO目标检测学习者的卫星遥感舰船检测数据集,适用于遥感图像识别、海上目标监测等场景,可帮助初学者与进阶开发者快速开展模型训练与验证。压缩包共2000个文件,约418.47MB,以1986个xml标注文件为主,另含少量html教程、txt说明与py脚本,标签覆盖voc、coco和yolo三种格式,分别存放于不同文件夹,可直接接入YOLO系列检测框架。资源附赠环境搭建、训练案例教程及数据集划分脚本,支持按需生成训练集、验证集与测试集,并输出ImageSets下的划分文件。已有650人学习下载,读者可借此获得真实场景的高质量标注数据、多格式标签转换参考以及完整的训练与划分流程,便于对照案例修改并训练自己的数据集,减少数据准备与格式适配的重复工作。
1. 从一份 5000 张的卫星遥感舰船数据集说起
卫星遥感舰船检测这件事,难点从来不在模型结构,而在数据。海面背景单一、目标尺度极小、港口密集停靠、云雾遮挡、尾迹干扰,这些场景决定了你拿 COCO 的预训练权重直接推理,召回率会难看到怀疑人生。一份 5000 张规模、同时给出 VOC、COCO、YOLO 三种标签格式并附带划分脚本和训练教程的数据集,价值就在于把最耗时的标注和对齐环节省掉,让你把精力放在训练策略和部署上。
这份数据集适合三类人:一是做遥感方向课程设计或毕设的学生,需要一份能跑通全流程的现成数据;二是想把 YOLO 落到实际业务里的工程师,需要验证小目标检测的调参边界;三是做边缘部署的开发者,想拿舰船这类高对比度目标先跑通链路。下面按「格式怎么选、脚本怎么跑、模型怎么训、坑在哪」的顺序讲清楚,每一步都给可复现的命令和参数。
2. VOC、COCO、YOLO 三种标签格式的差异与转换逻辑
2.1 三种格式的坐标表示与目录结构
同一批图片,三种格式描述的是同一件事,但坐标基准和文件组织完全不同。VOC 用左上角和右下角的绝对像素坐标,一张图一个 XML;COCO 用一个 JSON 汇总全部标注,坐标是[x, y, width, height]的绝对像素;YOLO 则是每张图一个 txt,每行class cx cy w h,全部归一化到 0 到 1 之间。
| 格式 | 坐标类型 | 文件组织 | 类别字段 | 典型用途 |
|---|---|---|---|---|
| VOC | 绝对像素 xmin/ymin/xmax/ymax | 每图一个 XML | name 字符串 | 传统检测框架、标注工具默认导出 |
| COCO | 绝对像素 x/y/w/h | 单个 annotations.json | category_id 整数 | 多任务、分割、评估指标统一 |
| YOLO | 归一化 cx/cy/w/h | 每图一个 txt | class_id 整数 | YOLO 系列直接训练 |
选哪个取决于你的训练框架。用 Ultralytics 系列就直接吃 YOLO 格式,用 MMDetection 或 Detectron2 就走 COCO,用老一代框架或需要和标注工具对接就留 VOC。数据集同时给三种,本质是让你不用自己写转换。
2.2 用 Python 在三种格式之间互转
转换的核心是坐标基准的换算。下面这段把 VOC 的 XML 批量转成 YOLO 的 txt,注意归一化时用的是图片真实宽高,不是标注里的size字段,因为部分标注工具的size会写错。
import os import xml.etree.ElementTree as ET from PIL import Image CLASSES = ["ship"] # 类别顺序必须和训练时的 data.yaml 一致 def voc_to_yolo(xml_dir, img_dir, out_dir): os.makedirs(out_dir, exist_ok=True) for xml_file in os.listdir(xml_dir): if not xml_file.endswith(".xml"): continue tree = ET.parse(os.path.join(xml_dir, xml_file)) root = tree.getroot() img_name = root.find("filename").text # 用真实图片尺寸,避免 size 字段不准 with Image.open(os.path.join(img_dir, img_name)) as im: w, h = im.size lines = [] for obj in root.iter("object"): cls = obj.find("name").text if cls not in CLASSES: continue cls_id = CLASSES.index(cls) 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) # 转成中心点 + 宽高,再归一化 cx = (xmin + xmax) / 2.0 / w cy = (ymin + ymax) / 2.0 / h bw = (xmax - xmin) / w bh = (ymax - ymin) / h lines.append(f"{cls_id} {cx:.6f} {cy:.6f} {bw:.6f} {bh:.6f}") with open(os.path.join(out_dir, xml_file.replace(".xml", ".txt")), "w") as f: f.write("\n".join(lines))逻辑说明:先读 XML 拿到绝对坐标,再用PIL打开原图取真实宽高做归一化,最后按 YOLO 的class cx cy w h顺序写出。参数上,CLASSES的顺序决定了class_id,一旦训练中途改动这个列表,之前训的权重就废了,所以定下来就别动。cx保留 6 位小数是 YOLO 官方推荐的精度,太少会丢小目标的位置信息。
反过来,YOLO 转 COCO 时要注意category_id从 1 开始而不是 0,这是 COCO 的约定,写成 0 会让评估脚本报错。转换脚本里还要补images、annotations、categories三个顶层字段,缺一个pycocotools就加载失败。
2.3 划分脚本怎么用才不出错
数据集自带的划分脚本通常做三件事:按比例切 train/val/test、保证同一场景的图片不被切散、生成对应的 txt 清单。跑之前先确认两件事:图片和标签是否同名同目录,以及类别是否只有一类。
# 常见调用方式,具体参数以脚本 --help 为准 python split_dataset.py \ --images ./images \ --labels ./labels \ --train-ratio 0.8 \ --val-ratio 0.1 \ --test-ratio 0.1 \ --seed 42 \ --output ./dataset参数说明:--seed固定随机种子,保证每次划分结果一致,方便复现;三个比例加起来必须等于 1,否则脚本一般会直接报错;--output下会生成images/train、labels/train这样的镜像结构。这里最容易踩的坑是划分后标签和图片路径对不上,训练时表现为「找到 0 张图片」,解决方法是划分完立刻用一条命令核对数量。
# 核对图片和标签数量是否一致 find ./dataset/images/train -type f | wc -l find ./dataset/labels/train -type f | wc -l两个数字必须相等。如果标签多出来,说明有孤立 txt;如果图片多出来,说明有图没标,训练时这些图会被当成纯背景,反而拉低召回。
3. 用 YOLO 训练舰船检测模型的完整流程
3.1 环境配置与 data.yaml 写法
环境这块,Anaconda 建一个独立环境最省事,Python 版本选 3.9 到 3.11 之间,太新或太旧都可能碰到依赖编译问题。装 Ultralytics 一条命令就够,GPU 用户记得先确认 CUDA 和 PyTorch 版本匹配。
conda create -n ship python=3.10 -y conda activate ship pip install ultralytics # 验证 GPU 是否可用 python -c "import torch; print(torch.cuda.is_available())"data.yaml是训练的入口配置,路径写错是最常见的失败原因。相对路径是相对于data.yaml所在目录解析的,不是相对于你执行命令的目录,这点和很多人的直觉相反。
path: ./dataset # 数据集根目录 train: images/train # 相对 path 的路径 val: images/val test: images/test nc: 1 # 类别数,舰船只有一类就写 1 names: ["ship"] # 顺序必须和标签里的 class_id 对应nc和names长度必须一致,names的顺序必须和生成标签时的CLASSES完全对应。改错这两处,模型会学出一个永远预测错类别的结果,而且 loss 看起来还在正常下降,非常隐蔽。
3.2 训练命令与关键参数怎么设
遥感舰船属于典型小目标场景,直接套默认参数效果一般。下面这条命令是我在 5000 张规模上比较稳的一组配置。
yolo detect train \ model=yolov8s.pt \ data=./data.yaml \ epochs=150 \ imgsz=1024 \ batch=8 \ lr0=0.01 \ lrf=0.01 \ mosaic=1.0 \ scale=0.5 \ patience=30 \ device=0 \ project=./runs \ name=ship_v1参数说明:imgsz=1024是关键,舰船在遥感图里往往只有十几个像素,用默认的 640 会把目标缩到几乎消失,放大输入尺寸是最直接的提升手段,代价是显存和训练时间;batch=8配合 1024 输入,8G 显存基本能跑,显存不够就降到 4 并开amp=True;mosaic=1.0做四图拼接增强,对小目标密集场景帮助明显;patience=30表示 30 轮没提升就早停,避免过拟合;lrf=0.01是最终学习率相对初始值的比例,配合余弦退火收尾更平滑。
如果显存实在紧张,可以退一步用imgsz=768,但别低于 640,否则小目标召回会掉得很难看。训练过程中重点盯mAP50-95而不是mAP50,前者对定位精度更敏感,舰船检测里框得准比框得全更重要。
3.3 训练日志里该看什么、不该看什么
训练启动后,runs/ship_v1/下会生成results.csv、weights/、若干可视化图。results.csv里每列对应一个指标,用 pandas 扫一眼趋势比盯着终端刷屏高效。
import pandas as pd df = pd.read_csv("runs/ship_v1/results.csv") df.columns = df.columns.str.strip() # 列名常带空格,先清理 print(df[["epoch", "train/box_loss", "metrics/mAP50-95"]].tail(10))逻辑说明:train/box_loss持续下降但metrics/mAP50-95停滞,说明模型在过拟合训练集,该加增强或减轮数;两者一起震荡,多半是学习率偏大,把lr0降到 0.005 试试。不要只看 loss 下降就以为训练成功,验证集指标才是判断依据。
提示:训练中途不要随意改
data.yaml的类别顺序或数量,已经训了一半的权重和新的类别定义不兼容,只能从头再来。
4. 推理、评估与置信度门限的调优
4.1 用训练好的权重跑推理
训练完拿best.pt做推理,命令行和 Python 两种方式都要会,前者适合批量跑,后者适合嵌进业务代码。
yolo detect predict \ model=runs/ship_v1/weights/best.pt \ source=./dataset/images/test \ imgsz=1024 \ conf=0.25 \ iou=0.5 \ save=True \ save_txt=True参数说明:conf=0.25是置信度门限,低于它的框直接丢弃;iou=0.5是 NMS 的重叠阈值,港口密集停靠场景可以适当调高到 0.6,避免相邻船只被误合并;save_txt=True会把预测结果按 YOLO 格式存下来,方便和真值做对比分析。
4.2 置信度门限与 NMS 阈值怎么联合调
这两个参数不是独立的。门限调低召回上去了但误检变多,NMS 阈值调低又会把密集目标里的真框压掉。遥感舰船场景里,海面杂波和云边缘是主要误检来源,港口密集停靠是主要漏检来源,两者要用不同策略。
| 场景 | conf 建议 | iou 建议 | 原因 |
|---|---|---|---|
| 开阔海面单船 | 0.35 到 0.45 | 0.5 | 背景干净,提高门限压误检 |
| 港口密集停靠 | 0.2 到 0.25 | 0.6 到 0.7 | 降低门限保召回,放宽 NMS 防合并 |
| 云雾遮挡 | 0.15 到 0.2 | 0.5 | 目标特征弱,门限必须压低 |
调参时不要凭感觉,用验证集跑一组网格,把conf从 0.1 到 0.5 按 0.05 步进,记录每个点的精确率和召回率,画一条 PR 曲线,选 F1 最高的那个点作为业务门限。这一步花十分钟,比上线后反复改代码划算得多。
4.3 用验证集指标判断模型是否可用
yolo detect val会输出每个类别的 P、R、mAP50、mAP50-95。舰船检测里,如果 mAP50 高但 mAP50-95 低,说明框得大致对但不够准,多半是标注框本身有偏差或者输入尺寸不够;如果两者都低,先回去查标签格式和类别对应,八成是数据问题而不是模型问题。
yolo detect val \ model=runs/ship_v1/weights/best.pt \ data=./data.yaml \ imgsz=1024 \ conf=0.001 \ iou=0.6验证时conf设成 0.001 是为了让评估脚本拿到全部预测框再统一算 AP,这是标准做法,不要用推理时的业务门限去评估,否则指标会虚高。
5. 小目标漏检与边缘部署的实战技巧
小目标漏检是遥感舰船检测最顽固的问题,除了放大imgsz,还有几个成本更低的技巧。一是切片推理,把大图切成带重叠的子图分别检测再合并,代价是推理时间成倍增加,适合离线批处理;二是调整 anchor 或改用无锚框结构,让模型对小尺度更敏感;三是训练时开copy_paste增强,把稀有尺度目标复制粘贴到不同背景,缓解尺度不均衡。
边缘部署时,模型体积和推理延迟是硬约束。常见做法是先把best.pt导出成 ONNX 或 TensorRT,再在目标设备上跑。
# 导出 ONNX,动态 batch 方便批量推理 yolo export model=runs/ship_v1/weights/best.pt format=onnx imgsz=1024 dynamic=True simplify=True # 导出 TensorRT,半精度,适合 NVIDIA 边缘设备 yolo export model=runs/ship_v1/weights/best.pt format=engine imgsz=1024 half=True device=0参数说明:dynamic=True让导出的 ONNX 支持可变 batch,部署时不用固定输入数量;half=True用 FP16 推理,速度提升明显,精度损失在舰船这类高对比度目标上通常可以接受;simplify=True会做图优化,去掉冗余算子,部分推理引擎对未简化的图支持不好。
部署后误检率高,先别急着换模型,按这个顺序排查:输入预处理是否和训练时一致,尤其是归一化和通道顺序;后处理的conf和iou是否沿用了训练时的默认值而不是业务调优值;图像缩放是否用了和训练相同的插值方式。这三处对不上,模型再好也会表现失常。最后,把线上误检的图定期回收,人工筛一遍补进训练集,迭代两三轮,误检率通常能降一个台阶。
本文还有配套的精品资源,点击获取