☰
遥感卫星图像YOLOV5数据集:飞机、油罐、船只检测实战指南
2026/9/28 2:25:15 网站建设 项目流程

简介:这份资源面向从事遥感图像目标检测的算法工程师、研究生与竞赛选手,提供一套按YOLOv5目录格式整理的三类别检测数据集,覆盖飞机、油罐、船只三类典型遥感目标,可直接投入训练与验证,省去格式转换与清洗成本。图像为800×600的RGB卫星影像,标注清晰,训练集含2398张图片及对应txt标签,验证集含1393张图片及对应txt标签,并附类别说明文件。资源包共约2000个文件,以1999个txt标注文件和1个Python可视化脚本为主,压缩包大小约237.68MB,解压后即可按标准目录结构使用。其中show.py可随机读取一张图片绘制边界框并保存到当前目录,无需修改即可运行,便于快速核验标注质量。目前已有215人学习下载,适合需要快速搭建遥感目标检测基线、验证模型效果或开展迁移学习实验的读者参考使用。

1. 遥感卫星图像下的飞机、油罐、船只检测:为什么这三类目标值得单独做一套 YOLOV5 数据集

拿到一批遥感卫星图像,想直接套开源预训练权重跑检测,结果大概率是:飞机漏检、油罐粘连、船只和浪花混在一起。原因不复杂——通用 COCO 权重里这三类的样本分布和遥感视角差异太大,俯视角度、目标尺度跨度、背景纹理全都对不上。这套面向 YOLOV5 目录格式的遥感卫星图像数据集,专门覆盖飞机、油罐、船只三个类别,解决的就是「通用模型在遥感场景下不好使」这个具体问题。

它适合谁?做遥感图像目标检测的算法工程师、需要快速验证检测方案可行性的研究者、以及想拿一个真实三类别场景练手 YOLOV5 训练部署全流程的开发者。三类别不算多,但恰好覆盖了遥感检测里三种典型难点:飞机是离散小目标、油罐是密集排列的圆形目标、船只是长条形且受水面纹理干扰。把这三类跑通,迁移到其他遥感目标上心里就有底了。下面从目录结构、标注规范、训练配置到避坑,一步步拆开讲。

2. YOLOV5 目录格式拆解:images、labels 与 data.yaml 到底怎么摆

2.1 标准目录树与三个必须对齐的地方

YOLOV5 对数据集的目录结构有固定约定,不按这个来,训练脚本第一步就报错。常见做法是根目录下分 images 和 labels 两个平行文件夹,各自再分 train、val,有时加 test。结构如下:

dataset/ ├── images/ │ ├── train/ │ │ ├── img_0001.jpg │ │ └── ... │ └── val/ │ ├── img_0101.jpg │ └── ... ├── labels/ │ ├── train/ │ │ ├── img_0001.txt │ │ └── ... │ └── val/ │ ├── img_0101.txt │ └── ... └── data.yaml

三个必须对齐的地方:第一,images 和 labels 下的子目录名必须完全一致(train 对 train,val 对 val);第二,每张图片和它的标注文件必须同名,只是扩展名不同(img_0001.jpg 对应 img_0001.txt);第三,labels 下不能有多余的非 .txt 文件,否则 YOLOV5 在缓存标签时会报解析错误。

遥感图像常见的坑是图片格式不统一。有的源数据是 .tif,有的是 .png,直接混着放,YOLOV5 的 dataloader 虽然能读,但不同位深的图像归一化后分布不一致,训练时 loss 会抖。我一般会先统一转成 8 位 JPEG 或 PNG,转换时注意别把 16 位遥感影像直接截断成 8 位,那样会丢大量暗部细节。

2.2 标注文件格式:归一化中心点坐标的五个字段

YOLOV5 的标签文件每行代表一个目标,格式是:

<class_id> <x_center> <y_center> <width> <height>

五个字段全部归一化到 0~1 之间。class_id 从 0 开始,这套数据集里约定 0=飞机、1=油罐、2=船只。x_center 和 y_center 是边界框中心点相对于图像宽高的比例,width 和 height 是框宽高相对于图像宽高的比例。

用 Python 做格式转换时,核心逻辑是这样:

# 将 VOC 格式 (xmin, ymin, xmax, ymax) 转为 YOLO 归一化格式 def voc_to_yolo(xmin, ymin, xmax, ymax, img_w, img_h): x_center = (xmin + xmax) / 2.0 / img_w y_center = (ymin + ymax) / 2.0 / img_h width = (xmax - xmin) / img_w height = (ymax - ymin) / img_h # 裁剪到 [0,1],防止标注越界导致训练报错 x_center = max(0.0, min(1.0, x_center)) y_center = max(0.0, min(1.0, y_center)) width = max(0.0, min(1.0, width)) height = max(0.0, min(1.0, height)) return x_center, y_center, width, height

这段代码的关键在最后四行裁剪。遥感图像标注时,目标有时会贴着图像边缘,标注框超出边界,归一化后出现负数或大于 1 的值。YOLOV5 在训练时遇到这种值不会报错,但会算出无效的 anchor 匹配,表现为 loss 突然变成 nan。加上裁剪是最省事的后悔药。

参数说明:img_w 和 img_h 是原始图像的宽高,不是缩放后的。如果先做了 resize 再转换,坐标要按缩放比例同步调整,否则框会整体偏移。我一般建议在原始分辨率下完成标注和格式转换,把 resize 留给 YOLOV5 的 dataloader 去做。

2.3 data.yaml 的五个字段与路径写法

data.yaml 是 YOLOV5 找到数据和类别的入口,内容不多但每个字段都不能错:

path: /home/user/dataset # 数据集根目录,绝对路径最稳 train: images/train # 相对 path 的训练图片目录 val: images/val # 相对 path 的验证图片目录 nc: 3 # 类别数 names: ['plane', 'oiltank', 'ship'] # 类别名,顺序对应 class_id

path 字段用绝对路径能避免很多「找不到文件」的玄学问题。train 和 val 写相对路径时,YOLOV5 会拼在 path 后面。nc 必须和 names 的长度一致,names 的顺序就是 class_id 的顺序,写反了模型会把飞机认成油罐。遥感数据集里油罐和船只的类间差异其实不小,但飞机和某些白色屋顶建筑容易混,names 命名时建议用语义明确的英文,别用缩写。

3. 从原始遥感影像到可训练数据集:切片、标注与划分的完整操作

3.1 大幅遥感影像切片:512 或 640 的窗口怎么选

遥感卫星图像单幅动辄几千甚至上万像素,直接送进 YOLOV5 会被缩放到 640,小目标直接缩没了。标准做法是先切片。窗口大小常见选 512×512 或 640×640,重叠率设 20%~30%。

import cv2 import os def slice_image(img_path, save_dir, slice_size=640, overlap=0.2): img = cv2.imread(img_path) h, w = img.shape[:2] stride = int(slice_size * (1 - overlap)) count = 0 for y in range(0, h, stride): for x in range(0, w, stride): # 边界处理:最后一块不足 slice_size 时回退对齐 x1 = min(x, w - slice_size) if w > slice_size else 0 y1 = min(y, h - slice_size) if h > slice_size else 0 x2 = x1 + slice_size y2 = y1 + slice_size patch = img[y1:y2, x1:x2] if patch.shape[0] < slice_size or patch.shape[1] < slice_size: continue name = os.path.splitext(os.path.basename(img_path))[0] cv2.imwrite(f"{save_dir}/{name}_{count}.jpg", patch) count += 1 return count

slice_size 选 640 的好处是和 YOLOV5 默认输入尺寸一致,切片后不用再缩放,小目标保留得最好。代价是切片数量多,训练慢。512 是折中,显存占用小,适合单卡 8G 的场景。overlap 设 0.2 意味着相邻切片有 128 像素重叠,目的是防止目标被切在边界上——一个飞机正好跨在两块切片中间,两块里各有一半,标注时两边都标不完整,训练时模型学到的是残缺目标。重叠切片能让完整目标至少出现在一块切片里。

注意:切片后要重新标注,不能把原图的标注直接按坐标裁过来。因为切片边界处的目标需要人工判断保留还是丢弃。我一般会写脚本把原图标注映射到切片上,然后人工过一遍边界目标,该删的删,该补的补。

3.2 三类别标注规范:飞机、油罐、船只的边界怎么定

标注工具用 labelImg 或 roLabelImg 都行,导出 YOLO 格式。三个类别的标注边界有各自容易翻车的地方。

飞机:标注框紧贴机身和机翼的最外沿,包括翼尖。遥感图像里飞机常停在停机坪,旁边有白色标线,标注时别把标线框进去。如果飞机是斜向停放,用水平矩形框,不要用旋转框——YOLOV5 原生不支持旋转框,用了反而增加处理成本。

油罐:油罐通常是圆形或椭圆形,从俯视角度看是圆。标注框用外接矩形,紧贴油罐边缘。密集排列的油罐之间间隙很小,标注时框与框可以重叠,但不要合并成一个框。我见过有人把一排油罐标成一个大框,训练出来的模型会把整排当一个目标,推理时 NMS 一压就全没了。

船只:船身细长,标注框沿船体长轴方向紧贴。水面有尾迹和浪花时,只框船体本身,不要把尾迹框进去。尾迹是水面纹理,不同光照下变化很大,框进去会让模型学到不稳定的特征。

标注完成后,用脚本检查一遍:有没有宽或高为 0 的框、有没有坐标超出 1 的框、有没有 class_id 超出 nc 的。这三个问题在训练时都会以 loss nan 或 mAP 为 0 的形式表现出来,提前查比训练时排查省事得多。

3.3 训练集验证集划分:8:2 还是 7:3,按场景分还是随机分

划分比例常见 8:2 或 7:3。这套三类别数据集如果总量在几千张切片级别,8:2 够用。关键不是比例,是划分方式。

随机划分有个隐患:同一幅原始大图切出来的切片,可能一部分进了训练集,一部分进了验证集。这些切片来自同一场景,光照、地物分布高度相似,验证集指标会虚高。正确做法是按原始图像划分——先把原始大图分成训练组和验证组,再各自切片。这样验证集里的场景和训练集不重叠,指标更真实。

如果原始图像数量少,做不到按图划分,至少按地理区域或拍摄时间划分。同一区域、同一时相的切片放同一边。遥感数据集的分布偏移比自然图像数据集严重得多,划分方式不对,验证集 mAP 能差 10 个点以上。

4. YOLOV5 训练配置:超参数怎么设、预训练权重怎么选、训练多久停

4.1 从 COCO 预训练权重起步,还是从零训

这套数据集三个类别,如果切片数量在 2000 张以下,强烈建议从 COCO 预训练权重起步。YOLOV5s 或 YOLOV5m 的 COCO 权重里已经有飞机和船只的相似特征,油罐虽然没有直接对应类别,但圆形目标的底层特征可以迁移。从零训在小数据集上几乎必然过拟合,验证集 loss 先降后升,mAP 卡在低位上不去。

# 从 COCO 预训练权重开始训练三类别遥感数据集 python train.py \ --weights yolov5s.pt \ --data dataset/data.yaml \ --epochs 100 \ --batch-size 16 \ --img-size 640 \ --cfg models/yolov5s.yaml \ --hyp data/hyps/hyp.scratch-low.yaml \ --name remote_sense_3cls

参数说明:--weights 指定预训练权重路径,yolov5s.pt 是轻量版,适合快速验证;如果显存够且追求精度,换 yolov5m.pt 或 yolov5l.pt。--img-size 设 640 和切片尺寸对齐。--batch-size 16 在单卡 8G 上跑 yolov5s 加 640 输入基本是上限,显存不够就降到 8,同时把 --accumulate 设成 2 来等效大 batch。--hyp 用 hyp.scratch-low.yaml,这是为小数据集设计的低增强配置,如果切片数量超过 5000,可以换 hyp.scratch.yaml 用标准增强。

4.2 学习率、锚框和增强参数的调整逻辑

YOLOV5 默认学习率 lr0=0.01,配合 SGD 优化器。遥感数据集如果切片数量少,lr0 降到 0.005 甚至 0.001,避免初期震荡太大。用 --hyp 自定义一个 yaml,改 lr0 和 lrf(最终学习率因子)。lrf 默认 0.01,意味着训练结束时学习率降到初始值的 1%,这个一般不用动。

锚框方面,YOLOV5 默认锚框是在 COCO 上聚类得到的,对遥感小目标偏大。如果飞机目标在切片里普遍小于 32×32 像素,建议用 k-means 在自己的标注框上重新聚类锚框。YOLOV5 仓库里有 utils/autoanchor.py,训练时加 --noautoanchor 关闭自动锚框,提前用脚本算好写进 cfg 文件。不重新聚类的话,小目标召回率会明显偏低。

增强参数里,mosaic 对遥感数据要慎用。mosaic 把四张图拼成一张,拼接边界会产生不自然的直线,遥感图像里这种直线会被模型当成道路或田埂特征学进去。如果验证集 mAP 上不去且训练 loss 正常,试试把 mosaic 关掉或把概率从 1.0 降到 0.5。翻转增强可以用,但上下翻转要谨慎——遥感图像里上下翻转后,某些地物的阴影方向会反,模型可能学到错误的阴影-目标关系。

4.3 训练多久停:看 mAP 还是看 loss

YOLOV5 默认 300 epoch,这套三类别数据集通常 100~150 epoch 就收敛了。判断收敛看验证集 mAP@0.5,连续 20 个 epoch 没有提升就可以停。别只看训练 loss,训练 loss 一直在降但验证 mAP 不涨,是过拟合的典型信号。

训练过程中重点盯三个指标:mAP@0.5、mAP@0.5:0.95、以及每个类别的 AP。三个类别里如果油罐的 AP 明显低于飞机和船只,回去检查油罐标注是不是有合并框或漏标。如果船只 AP 低,看验证集里是不是有很多水面反光被误检成船。这些排查比调超参有效得多。

训练完成后,用 val.py 在验证集上跑一遍,加 --save-txt 和 --save-conf 把预测结果存下来,挑几张误检和漏检的图看看,比看数字更能发现问题。

5. 避坑与排查:遥感三类别检测里最容易翻车的五个地方

5.1 训练 loss 变 nan:标注越界和空标签文件

现象:训练几个 epoch 后 loss 突然变成 nan,之后一直 nan。 原因:标签文件里有坐标超出 [0,1] 的值,或者某个标签文件是空的(0 字节)。YOLOV5 在计算损失时对空标签文件不会报错,但会参与缓存,导致后续 batch 的标签解析异常。 解决:训练前跑一遍检查脚本,遍历所有 labels 下的 .txt 文件,逐行解析五个字段,确认坐标在 [0,1] 内、class_id 在 [0, nc-1] 内、文件非空。发现越界就裁剪,发现空文件就删掉对应图片和标签。

5.2 验证集 mAP 虚高:切片泄漏

现象:验证集 mAP@0.5 到 0.95 很高,但拿新场景的遥感图推理,效果差很多。 原因:同一幅原始大图切出来的切片同时出现在训练集和验证集里,验证集和训练集高度相似,指标虚高。 解决:按原始图像划分训练集和验证集,先分图再切片。如果已经切好了,用文件名前缀追溯原始图,按原始图重新分组划分。

5.3 油罐漏检严重:锚框尺寸不匹配

现象:飞机和船只检测正常,油罐漏检多,尤其是小油罐。 原因:默认锚框偏大,小油罐在特征图上匹配不到合适的 anchor。 解决:用 k-means 在油罐标注框上重新聚类锚框,或者把输入尺寸从 640 提到 1024,让小油罐在特征图上有更多像素。两种方法可以叠加用。

5.4 船只和浪花混淆:负样本不足

现象:船只检测框旁边经常多出误检框,位置在水面反光或浪花处。 原因:训练集里水面背景样本不够,模型没学到「什么样的水面纹理不是船」。 解决:在训练集里加入一些不含船只的水面切片作为背景负样本,标签文件留空。YOLOV5 支持空标签文件作为负样本,但注意空文件不能是 0 字节,至少写一个换行符,否则会被当成损坏文件跳过。

5.5 推理时框重叠:NMS 阈值和类别顺序

现象:密集油罐区域推理时,多个油罐被合并成一个框,或者一个油罐出多个框。 原因:NMS 的 IoU 阈值默认 0.45,密集排列的油罐之间 IoU 容易超过这个值,被误压。另外如果 data.yaml 里 names 顺序和训练时不一致,类别预测会错位。 解决:推理时把 --conf-thres 从 0.25 提到 0.4,--iou-thres 从 0.45 提到 0.6,给密集目标更多保留空间。同时确认推理用的 data.yaml 和训练时完全一致,names 顺序不能变。

6. 进阶技巧:用 TTA 和分块推理把遥感小目标召回再提一截

训练收敛之后,如果还想在推理阶段再挤一点精度,有两个成本低、见效快的手段:TTA(测试时增强)和分块推理。

TTA 的做法是在推理时对同一张图做多种变换(水平翻转、多尺度缩放),分别预测后再把结果融合。YOLOV5 的 detect.py 自带 --augment 参数,开启后会自动做 TTA。代价是推理速度降到原来的 1/3 左右,适合离线批量处理场景,不适合实时。

# 开启 TTA 推理,提升小目标召回 python detect.py \ --weights runs/train/remote_sense_3cls/weights/best.pt \ --source test_images/ \ --img-size 640 \ --conf-thres 0.4 \ --iou-thres 0.6 \ --augment \ --save-txt

--augment 开启 TTA,--conf-thres 和 --iou-thres 按上一章的避坑建议调高。--save-txt 把预测结果存成 YOLO 格式,方便后续做后处理或和标注对比。

分块推理针对的是超大遥感图。如果测试图是几千像素的大图,直接缩放到 640 推理,小目标全丢。做法是把大图按 640 窗口切片,逐块推理,再把结果映射回原图坐标,最后做一次全局 NMS 去重。切片时重叠率设 0.3,比训练时的 0.2 稍大,确保边界目标至少在一块里完整出现。

# 分块推理后处理:把切片预测框映射回原图坐标 def map_boxes_to_original(boxes, offset_x, offset_y, slice_size): mapped = [] for box in boxes: x1, y1, x2, y2, conf, cls = box mapped.append([ x1 + offset_x, y1 + offset_y, x2 + offset_x, y2 + offset_y, conf, cls ]) return mapped

offset_x 和 offset_y 是当前切片左上角在原图中的坐标。映射完成后,所有切片的框汇总到一起,用 torchvision 的 nms 或自己写一个 IoU 去重,把跨切片重复检测的同一个目标合并。这一步的 IoU 阈值建议设 0.5,比单图 NMS 稍低,因为跨切片的框位置会有几个像素的偏差。

这两个技巧叠加使用,在遥感小目标上通常能把 mAP@0.5 再提 2~5 个点。代价是推理链路变长,工程复杂度上升。我的习惯是:如果验证集 mAP 已经满足业务要求,就不上 TTA 和分块,保持推理链路简单;如果差几个点死活上不去,再上这两个手段,同时把推理耗时纳入评估。遥感检测这行,精度和速度的取舍比自然图像场景更尖锐,早点想清楚业务能接受多慢的推理,比盲目堆技巧有用。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询