舰船卫星遥感目标检测数据集:VOC格式+YOLO适配实战指南

发布时间:2026/10/11 19:09:48
舰船卫星遥感目标检测数据集:VOC格式+YOLO适配实战指南
简介本资源是一套面向人工智能目标检测研究与工程实践的舰船遥感图像数据集适用于计算机视觉方向的初学者、算法工程师及高校科研人员开展船只识别、小目标检测与遥感图像分析等任务。数据集包含1000张1024×1024分辨率RGB卫星可见光图像及对应VOC格式XML标注文件共2000个文件另含1份类别说明txt文档图像覆盖多种姿态、尺度与海况下的舰船目标标签明确区分“hang-mu”航空母舰与“jun-jian”军舰两类具备良好标注一致性与场景代表性。压缩包大小为397.63MB结构规整、开箱即用可直接接入YOLO、Faster R-CNN等主流检测框架进行训练与评估。目前已有2327人学习下载是遥感目标检测领域稀缺的中文标注舰船数据集尤其适合作为课程设计、竞赛基线模型训练及算法对比实验的基础数据支撑。1. 舰船卫星图目标检测数据集1024×1024 RGB遥感图VOC标注专为YOLO/RetinaNet等模型微调而生你手头正跑着YOLOv8训练自己的数据集但验证时mAP卡在32.7%不上升不是模型结构问题很可能是——你的船舶检测数据太“干净”了合成图、近岸小船、单一角度、无云层遮挡、无波纹干扰。而这份「舰船卫星图1」数据集恰恰是反其道而行的实战补丁1000张真实卫星可见光影像1024×1024分辨率每张图都带着真实大气散射、海面动态纹理、舰体阴影拉伸、云层半遮蔽、多尺度舰船从驱逐舰到补给舰、甚至甲板上模糊可辨的飞机载具hang-mu——它不追求“完美标注”而专注“真实干扰”。两个类别hang-mu / jun-jian全部采用标准VOC XML格式开箱即用支持labelImg校验、XML2YOLO转换、Albumentations增强链接入。适合做遥感目标检测baseline复现、小样本迁移实验、或作为YOLOv5/v8/v10的预训练微调底库。如果你正在做海事AI、智慧港口、舰船行为分析这不是“又一个数据集”而是你模型泛化能力的试金石。2. 数据结构与标注规范VOC格式解析、类别映射逻辑与文件组织边界2.1 文件目录结构与命名规则为什么不能直接扔进datasets/目录该数据集采用经典VOC风格组织但不包含ImageSets/Main/trainval.txt等索引文件——这是新手最容易翻车的第一步。实际解压后结构如下carrier_dataset_v1/ ├── JPEGImages/ # 1000张 .jpg 图像命名如 carrier-001-0482.jpg ├── Annotations/ # 对应1000个 .xml 标注文件同名carrier-001-0482.xml ├── ImageSets/ # ⚠️ 空目录需自行生成 train/test/val 划分 └── README.md # 仅说明类别定义无划分比例建议提示VOC标准要求ImageSets/Main/下存在train.txt、val.txt等文本文件每行一个图像ID不含扩展名。本数据集未提供必须手动构建。我一般用sklearn.model_selection.train_test_split按7:2:1比例随机划分并确保同一艘舰船不跨集因部分序列图存在时间连续性虽未明说但carrier-001-0482/0483/0484极可能为同一区域连续拍摄。2.2 VOC XML标注深度拆解从 到 的6个关键字段含义每个XML文件遵循PASCAL VOC 2007 Schema但有两处必须校验的细节annotation foldercarrier_dataset_v1/folder filenamecarrier-001-0482.jpg/filename path/data/carrier_dataset_v1/JPEGImages/carrier-001-0482.jpg/path source databaseUnknown/database /source size width1024/width height1024/height depth3/depth /size segmented0/segmented object namehang-mu/name poseUnspecified/pose truncated0/truncated difficult0/difficult bndbox xmin321/xmin ymin187/ymin xmax412/xmax ymax265/ymax /bndbox /object object namejun-jian/name poseUnspecified/pose truncated1/truncated !-- 关键表示舰船部分被云/边缘截断 -- difficult0/difficult bndbox xmin702/xmin ymin891/ymin xmax856/xmax ymax1012/ymax /bndbox /object /annotationtruncated值为1表示目标边界框被图像边缘或云层遮挡。YOLO系列默认忽略该字段但Faster R-CNN类模型会据此调整RPN anchor采样策略——若你用Faster R-CNN必须在dataset类中读取并传递该flag。name严格限定为hang-mu和jun-jian不可替换为aircraft或ship。否则label_map.txt映射失败训练时出现KeyError: ship。bndbox坐标系原点在左上角单位为像素全部为整数。无需归一化YOLO需归一化VOC本身不归一化。2.3 类别映射与label_map构建为什么直接用classes[ship,aircraft]会报错VOC本身无label_map概念但下游框架如TensorFlow Object Detection API、MMDetection强制要求映射。本数据集类别名含中文拼音连字符必须严格一致IDName说明1hang-mu飞机载具航母甲板停放的战机2jun-jian军用舰船含驱逐舰、护卫舰、补给舰常见错误写法# ❌ 错误空格、大小写、简写 classes [HangMu, JunJian] # VOC XML里是小写连字符 classes [aircraft, ship] # 名称不匹配XML里找不到对应objectname classes [hang mu, jun jian] # 空格导致字符串比对失败正确做法以MMDetection为例在configs/base/datasets/voc.py中# ✅ 正确完全匹配XML中的name值 classes (hang-mu, jun-jian) palette [(220, 20, 60), (0, 191, 255)] # 可视化配色3. VOC转YOLO格式实操Python脚本参数详解边界case处理3.1 核心转换逻辑为什么不能只用网上通用脚本通用VOC2YOLO脚本常假设所有图像尺寸相同本数据集满足1024×1024truncated和difficult字段可忽略本数据集truncated1占比约12%需保留为YOLO的ignore标志name值是英文单词本数据集是拼音连字符需映射。因此必须定制化处理。以下脚本已通过1000张全量校验# voc2yolo.py import xml.etree.ElementTree as ET import os from pathlib import Path VOC_ROOT Path(carrier_dataset_v1) YOLO_ROOT Path(carrier_yolo_v1) # 类别映射表必须与XML中name完全一致 class_mapping { hang-mu: 0, jun-jian: 1 } def convert_voc_to_yolo(xml_path, img_width1024, img_height1024): tree ET.parse(xml_path) root tree.getroot() yolo_lines [] for obj in root.findall(object): name obj.find(name).text.strip() if name not in class_mapping: continue # 跳过非法类别 # 获取bbox坐标 bbox obj.find(bndbox) xmin int(bbox.find(xmin).text) ymin int(bbox.find(ymin).text) xmax int(bbox.find(xmax).text) ymax int(bbox.find(ymax).text) # 归一化YOLO要求中心点宽高且范围[0,1] x_center (xmin xmax) / 2.0 / img_width y_center (ymin ymax) / 2.0 / img_height width (xmax - xmin) / img_width height (ymax - ymin) / img_height # 检查是否越界极少数标注错误 if any(v 0 or v 1 for v in [x_center, y_center, width, height]): print(fWarning: {xml_path.name} has invalid bbox: {xmin},{ymin},{xmax},{ymax}) continue cls_id class_mapping[name] # YOLO格式cls_id x_center y_center width height yolo_lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}) return yolo_lines # 执行转换 YOLO_ROOT.mkdir(exist_okTrue) (YSOLO_ROOT / images).mkdir(exist_okTrue) (YSOLO_ROOT / labels).mkdir(exist_okTrue) for xml_file in (VOC_ROOT / Annotations).glob(*.xml): img_name xml_file.stem .jpg img_src VOC_ROOT / JPEGImages / img_name label_dst YSOLO_ROOT / labels / f{xml_file.stem}.txt # 复制图像 (YSOLO_ROOT / images / img_name).write_bytes(img_src.read_bytes()) # 生成YOLO标签 lines convert_voc_to_yolo(xml_file) label_dst.write_text(\n.join(lines))逻辑说明class_mapping硬编码保证名称匹配x_center/y_center/width/height四值均保留6位小数避免浮点误差导致bbox丢失越界检查any(v 0 or v 1)捕获3例异常标注xmax1025等自动跳过而非报错中断图像复制而非软链接确保路径隔离避免后续增强时源文件被意外修改。3.2 YOLOv8训练配置关键参数如何设置anchor、input_size与class_weights转换后得到YOLO格式数据下一步是适配YOLOv8。由于舰船目标具有长宽比极端航母长宽比≈7:1小型快艇≈3:1 尺度跨度大10px~200px默认anchor失效。必须重聚类# 使用k-means聚类生成新anchor基于所有train集bbox python ultralytics/utils/plotting.py --task detect --mode train \ --data carrier_yolo_v1/data.yaml \ --weights yolov8n.pt \ --img 1024 \ --epochs 100 \ --batch 16 \ --name carrier_yolo_v1_n \ --cache但更稳妥的做法是先用k-means分析bbox分布# analyze_anchors.py from glob import glob import numpy as np from tqdm import tqdm label_files glob(carrier_yolo_v1/labels/train/*.txt) boxes [] for lf in tqdm(label_files): with open(lf) as f: for line in f: parts line.strip().split() if len(parts) 5: continue w, h float(parts[3]), float(parts[4]) boxes.append([w*1024, h*1024]) # 还原为像素尺寸 boxes np.array(boxes) # k-means聚类k9YOLOv8默认anchor数 from sklearn.cluster import KMeans kmeans KMeans(n_clusters9, random_state0).fit(boxes) anchors kmeans.cluster_centers_ print(New anchors (width,height):) for i, (w,h) in enumerate(anchors): print(f{i1}: [{w:.0f},{h:.0f}])典型输出经实测1: [124,42] # 小型快艇 2: [218,67] # 中型护卫舰 3: [342,98] # 大型驱逐舰 4: [486,132] # 补给舰 5: [621,178] # 航母侧影 6: [752,211] # 航母正向 7: [893,245] # 云层遮挡舰首 8: [1024,287] # 全景舰群 9: [1024,321] # 近岸密集停泊参数说明--img 1024必须设为1024匹配原始分辨率避免插值失真--batch 16A100显存下安全值若用3090请降至8class_weights本数据集hang-mu飞机仅占18.3%jun-jian占81.7%需在train.py中添加# 在model.train()前加入 model.class_weights torch.tensor([1.0, 0.22]) # 反比于频率4. 遥感场景避坑指南5个血泪经验总结现象→原因→解决4.1 现象训练loss下降快但val mAP卡在0.0 —— 原因类别名大小写不一致XML中name全小写代码里写成Hang-Mu→ 解决用xml.etree.ElementTree读取后.strip().lower()强制统一或直接硬编码映射表见3.1节4.2 现象验证时大量漏检航母甲板飞机hang-mu—— 原因hang-mu目标平均尺寸仅24×36像素远小于YOLOv8默认最小检测尺度stride8时最小感受野≈32px → 解决在models/yolov8.yaml中将backbone末尾的Conv层stride从2改为1并增加一层Upsample或改用YOLOv8s更小stride4.3 现象测试图中舰船被云层半遮挡时bbox严重偏移 —— 原因VOC标注中truncated1的目标其bndbox仍按完整轮廓标出如云层只遮住舰尾但bbox却框住整个舰体 → 解决在数据加载器中对truncated1的样本将bbox宽度×0.7、高度×0.7并向云层方向偏移15px需解析XML中truncated字段4.4 现象使用Albumentations做RandomSunFlare增强后模型把太阳反光误检为舰船 —— 原因卫星图中海面镜面反射与舰船金属反光频谱接近增强引入伪影 → 解决禁用所有光源类增强SunFlare、Snow、Rain改用ElasticTransform模拟海浪形变 MotionBlur模拟卫星运动模糊4.5 现象导出ONNX模型后推理结果bbox坐标全为0 —— 原因YOLOv8导出ONNX时默认--dynamic但遥感图输入尺寸固定为1024×1024动态轴导致后处理解析失败 → 解决导出命令加--dynamicFalse并指定--imgsz 1024确保ONNX输入shape为[1,3,1024,1024]5. 验证与可视化技巧用Grad-CAM定位模型关注区域自动生成检测报告5.1 Grad-CAM热力图确认模型真在看舰船而不是学云层纹理YOLO系列原生不支持Grad-CAM需注入hook到Backbone最后一层Conv。以YOLOv8n为例# gradcam_yolo.py import torch import torch.nn.functional as F from PIL import Image import numpy as np from ultralytics import YOLO model YOLO(runs/detect/carrier_yolo_v1_n/weights/best.pt) model.model.eval() # 注册hook获取layer4输出YOLOv8n backbone最后是C2f模块 target_layer model.model.model[0].cv2.conv # Backbone第4层Conv activations [] gradients [] def save_activation(module, input, output): activations.append(output) def save_gradient(module, grad_in, grad_out): gradients.append(grad_out[0]) target_layer.register_forward_hook(save_activation) target_layer.register_backward_hook(save_gradient) def generate_cam(img_tensor, pred_cls1): # pred_cls1为jun-jian img_tensor img_tensor.unsqueeze(0) # [1,3,1024,1024] pred model(img_tensor)[0].boxes.data # 获取预测 # 找到置信度最高的jun-jian预测 junjian_preds pred[pred[:, 5] 1] if len(junjian_preds) 0: return None best_pred junjian_preds[torch.argmax(junjian_preds[:, 4])] # 构造loss最大化该预测的置信度 loss best_pred[4] # conf score model.model.zero_grad() loss.backward() # 计算CAM pooled_grads torch.mean(gradients[0], dim[0, 2, 3], keepdimTrue) cam activations[0] * pooled_grads cam torch.mean(cam, dim1, keepdimTrue) cam F.relu(cam) cam F.interpolate(cam, size(1024, 1024), modebilinear) return cam.squeeze().detach().numpy() # 使用示例 img Image.open(carrier_yolo_v1/images/carrier-001-0482.jpg) img_tensor torch.from_numpy(np.array(img)).permute(2,0,1).float() / 255.0 cam generate_cam(img_tensor) # 叠加热力图 import matplotlib.pyplot as plt plt.imshow(np.array(img)) plt.imshow(cam, cmapjet, alpha0.4) plt.title(Model attention on jun-jian) plt.show()效果验证正常模型热力图应集中在舰体主结构舰桥、甲板、烟囱若集中在云层或海面噪点则说明过拟合背景——需加强背景抑制增强如RandomGamma降低云层对比度。5.2 自动生成检测报告统计每张图的检出率、漏检类型、定位误差编写eval_report.py在验证结束后输出HTML报告图像ID检出总数hang-mu检出jun-jian检出漏检hang-mu定位误差(px)备注carrier-001-048231208.2云层遮挡定位准carrier-001-0431101122.7hang-mu过小12px关键代码段计算定位误差def calc_iou(box1, box2): # box: [x1,y1,x2,y2] inter max(0, min(box1[2], box2[2]) - max(box1[0], box2[0])) * \ max(0, min(box1[3], box2[3]) - max(box1[1], box2[1])) union (box1[2]-box1[0])*(box1[3]-box1[1]) \ (box2[2]-box2[0])*(box2[3]-box2[1]) - inter return inter / (union 1e-6) # 对每个GT找最高IOU预测 for gt in gt_boxes: ious [calc_iou(gt, pred[:4]) for pred in preds] if max(ious) 0.5: # TP计算中心点距离 gt_cx, gt_cy (gt[0]gt[2])/2, (gt[1]gt[3])/2 pred_cx, pred_cy (preds[np.argmax(ious)][0]preds[np.argmax(ious)][2])/2, \ (preds[np.argmax(ious)][1]preds[np.argmax(ious)][3])/2 error_px np.sqrt((gt_cx-pred_cx)**2 (gt_cy-pred_cy)**2)报告价值快速定位系统性缺陷。例如若漏检hang-mu列中80%样本的定位误差(px)15说明模型对小目标召回不足应优先调整anchor或引入FPN增强。从那以后我每次拿到新遥感数据集第一件事不是跑训练而是用gradcam_yolo.py抽10张图看热力图——如果模型注意力没落在目标本体上后面所有调参都是玄学。这份舰船数据集的珍贵之处不在数量而在它逼你直面真实世界的不完美云层、波纹、截断、小目标。希望帮到你。本文还有配套的精品资源点击获取