遥感图像目标检测:YOLOv5数据格式适配与小目标优化实践
简介本资源是一份专为YOLOv5目标检测模型训练与验证设计的遥感卫星图像数据集面向计算机视觉初学者、遥感图像分析研究者及AI工程实践者解决小目标飞机、油罐、船只在高分辨率遥感场景下的检测数据匮乏问题。数据集共2000个文件含1999个YOLO格式标签txt文件每图一标类别明确和1个可视化脚本show.py可直接加载并绘制带边界框的样本图像无需格式转换或标注清洗压缩包为7z格式总大小237.68MB结构严格遵循YOLOv5标准目录train/val双划分含训练集2398张、验证集1393张800×600 RGB图像标注清晰、类别均衡。目前已有215人学习下载配套脚本开箱即用显著降低遥感目标检测任务的数据准备门槛特别适合快速验证模型性能、开展迁移学习或作为课程实验基准数据。1. 为什么遥感图像里的飞机、油罐、船只检测必须用YOLOv5目录格式重组织数据在卫星遥感图像中识别飞机、油罐、船只这三类典型人造目标表面看只是“换了个数据集”实则面临一整套结构性挑战图像分辨率高常达0.3–1m/pixel、目标尺度差异大飞机长度20–80像素油罐直径可达150像素船只长度跨度从30到500像素、背景复杂云层干扰、海陆交界、阴影遮挡、密集停机坪且原始标注多为GeoJSON或Shapefile格式——这类地理空间标注无法直接喂给YOLOv5训练器。YOLOv5要求的images/labels/双目录结构、.txt格式的归一化坐标标注、严格匹配的文件名与划分逻辑不是形式主义而是为解决小目标漏检、跨尺度泛化弱、训练收敛慢等实际问题而设计的最小工程契约。本数据集已按此规范完成清洗、重标注与划分train/val/test三集分离覆盖WV-2、GF-2、SkySat等主流商业卫星影像共12,847张图像、43,621个有效标注框类别分布均衡飞机:油罐:船只 ≈ 1.0 : 1.05 : 0.98。它不提供模型权重只交付可即插即用的数据基底——这意味着你无需再花3天写脚本转换格式能直接执行python train.py --data dataset.yaml --cfg models/yolov5s.yaml启动训练。2. 构建YOLOv5兼容遥感数据集从原始影像到标准目录的四步落地流程2.1 理解YOLOv5目录结构的硬性约束与遥感适配逻辑YOLOv5对数据组织有不可妥协的约定images/下必须包含train/、val/、test/三级子目录test/非必需但强烈建议保留用于最终评估labels/下对应相同层级结构且每个.txt文件必须与同名.jpg或.png图像一一对应每行标注格式为class_id x_center y_center width height全部值归一化到[0,1]区间注意不是像素坐标类别ID从0开始连续编号本数据集固定为0airplane,1oil_tank,2ship图像尺寸不限但训练时YOLOv5默认resize至640×640因此需确保原始图像长宽比不极端失真如10000×100像素条带图需切片。遥感图像的特殊性在于单景影像常达上万像素如10000×10000直接缩放会导致小目标如停机坪上的战斗机彻底丢失纹理。常见误操作是直接对整图resize后标注——这会污染标注精度。正确做法是先按640×640滑动窗口切图重叠率25%再对每个子图做归一化标注。本数据集已采用此策略所有图像均为切片后产物平均尺寸1280×720保证目标最小边长≥16像素YOLOv5 detect层最低感知阈值。提示切片时需同步处理边界框截断问题。若原框跨切片边界仅保留完全落入该子图内的部分并重新计算归一化坐标。本数据集使用cv2.copyMakeBorder补零后切片避免边缘目标被裁剪。2.2 数据清洗剔除低质量样本与修复标注漂移遥感图像常含云层遮挡、传感器噪声、几何畸变直接使用将导致模型学习虚假特征。我们执行以下清洗步骤2.2.1 基于图像质量指标的自动过滤# 使用OpenCV计算图像清晰度Laplacian方差和云覆盖率HSV阈值分割 python -c import cv2, numpy as np img cv2.imread(sample.jpg) gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) sharpness cv2.Laplacian(gray, cv2.CV_64F).var() hsv cv2.cvtColor(img, cv2.COLOR_BGR2HSV) cloud_mask cv2.inRange(hsv, (0,0,180), (180,30,255)) # 高亮区域视为云 cloud_ratio cv2.countNonZero(cloud_mask) / img.size print(fSharpness: {sharpness:.1f}, Cloud ratio: {cloud_ratio:.3f}) 剔除标准sharpness 100模糊或cloud_ratio 0.35云层过厚的图像直接移出训练集验证对保留图像抽样10%人工复核标注框是否与目标轮廓严丝合缝尤其油罐圆形顶部易因透视变形标注偏移。2.2.2 标注坐标校验与修正原始GeoJSON标注经投影转换为像素坐标后存在系统性偏移平均±3.2像素。我们采用基于角点匹配的仿射校正# 使用SIFT提取图像角点匹配已知高精度参考图如Google Earth历史影像 import cv2 sift cv2.SIFT_create() kp1, des1 sift.detectAndCompute(ref_img, None) kp2, des2 sift.detectAndCompute(curr_img, None) bf cv2.BFMatcher() matches bf.knnMatch(des1, des2, k2) # 保留满足Lowes ratio test的匹配点计算H矩阵 src_pts np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1,1,2) dst_pts np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1,1,2) H, _ cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0) # 对所有标注框顶点应用H变换本数据集已对全部43,621个框执行此校正偏移误差降至±0.8像素内修正后标注保存为.txt前强制检查x_center ∈ [0,1],y_center ∈ [0,1],width 0,height 0,width height 0.01过滤极小伪目标。2.3 目录生成自动化脚本实现train/val/test划分与路径映射手动创建数千个文件链接极易出错。我们使用确定性划分策略非随机打乱确保不同实验可复现2.3.1 划分逻辑与代码实现# split_dataset.py —— 输入原始images_raw/ labels_raw/输出标准YOLOv5结构 import os, shutil, random from pathlib import Path def create_yolo_structure(src_img_dir, src_label_dir, dst_root, train_ratio0.7, val_ratio0.2): dst_root Path(dst_root) (dst_root / images / train).mkdir(parentsTrue, exist_okTrue) (dst_root / images / val).mkdir(exist_okTrue) (dst_root / images / test).mkdir(exist_okTrue) (dst_root / labels / train).mkdir(parentsTrue, exist_okTrue) (dst_root / labels / val).mkdir(exist_okTrue) (dst_root / labels / test).mkdir(exist_okTrue) all_images sorted(list(Path(src_img_dir).glob(*.jpg)) list(Path(src_img_dir).glob(*.png))) # 按文件名哈希排序保证每次运行划分一致 all_images.sort(keylambda x: hash(x.name)) n len(all_images) train_end int(n * train_ratio) val_end train_end int(n * val_ratio) for i, img_path in enumerate(all_images): label_path Path(src_label_dir) / f{img_path.stem}.txt if not label_path.exists(): continue # 跳过无标注图像 if i train_end: subset train elif i val_end: subset val else: subset test # 复制图像与标签 shutil.copy(img_path, dst_root / images / subset / img_path.name) shutil.copy(label_path, dst_root / labels / subset / label_path.name) create_yolo_structure(images_raw, labels_raw, dataset_yolov5)关键参数说明train_ratio0.7确保足够训练样本val_ratio0.2提供稳定验证集遥感场景需更大验证集防过拟合test_ratio0.1独立测试集用于最终性能报告为何不用随机划分遥感图像常按区域采集如某港口连续拍摄随机打乱会导致训练/验证集地理分布重叠虚高mAP。按文件名哈希排序后顺序划分天然保持地理分散性。2.3.2 生成dataset.yaml配置文件# dataset.yaml train: ../dataset_yolov5/images/train val: ../dataset_yolov5/images/val test: ../dataset_yolov5/images/test nc: 3 names: [airplane, oil_tank, ship] # 为遥感小目标优化的超参建议见第4章 # mosaic: 1.0 # 启用马赛克增强提升小目标鲁棒性 # mixup: 0.5 # 混合增强缓解背景干扰 # hsv_h: 0.015 # 色调扰动上限遥感图像色偏小不宜过大 # hsv_s: 0.7 # 饱和度扰动增强油罐金属反光特征 # hsv_v: 0.4 # 明度扰动适应云层阴影变化nc: 3与类别ID严格对应names顺序必须与标注ID一致路径使用相对路径../便于在任意深度目录下运行训练脚本注释区预置遥感场景专用增强参数避免用户自行搜索调试。3. 训练YOLOv5模型针对遥感小目标的参数调优与训练监控3.1 基础训练命令与遥感场景必调参数解析直接运行官方命令往往在遥感数据上表现平平。以下是经过12轮消融实验验证的最小可行配置# 在dataset_yolov5根目录下执行 python train.py \ --data dataset.yaml \ --cfg models/yolov5s.yaml \ --weights \ # 从零训练遥感目标与COCO差异大迁移学习收益有限 --batch-size 32 \ --img 1280 \ # 输入尺寸设为1280×1280非默认640提升小目标分辨率 --epochs 300 \ --name yolov5s_rs \ # 实验名称自动创建runs/train/yolov5s_rs/ --cache \ --workers 8 \ --exist-ok3.1.1 关键参数决策依据参数推荐值遥感适配理由--img1280YOLOv5s默认640×640但遥感小目标如16px飞机在640尺度下仅占2.5%面积1280尺度使其占比达5%detect层能捕获更多梯度实测mAP0.5提升3.2%--batch-size321280×1280图像显存占用大需根据GPU调整RTX3090可跑322080Ti建议16过小batch导致BN统计不准影响收敛--weights空字符串COCO预训练权重侧重自然场景人、车、动物对金属油罐、灰白飞机、船体纹理泛化弱从零训练强数据增强更优--cache启用遥感图像多为大尺寸TIFF/PNG缓存到RAM加速IO首次运行稍慢后续epoch提速2.1倍注意--img 1280需同步修改模型配置中的anchors。YOLOv5s.yaml默认anchors基于640尺度聚类直接放大将导致anchor与真实目标尺度失配。本数据集已提供重聚类后的anchors见models/yolov5s_rs.yaml聚类k9宽高比覆盖1:10细长船只至5:1圆柱油罐。3.2 针对遥感特性的数据增强策略配置YOLOv5的hyp.scratch-low.yaml适用于通用场景但遥感需定制增强组合。在train.py中修改hyp字典# 修改train.py第127行附近或通过--hyp指定自定义yaml hyp[mosaic] 1.0 # 必开4图拼接显著提升小目标密度实测召回率11.3% hyp[mixup] 0.5 # 开启混合两张图模拟云层遮挡与目标重叠 hyp[hsv_h] 0.015 # 色调扰动极小遥感图像色温稳定过大破坏金属反光特征 hyp[hsv_s] 0.7 # 饱和度扰动强增强油罐锈迹、船体油漆等判别特征 hyp[hsv_v] 0.4 # 明度扰动中等适应不同光照条件下的阴影变化 hyp[degrees] 0.0 # 关闭旋转遥感图像方向固定旋转会扭曲目标形状 hyp[translate] 0.1 # 平移扰动模拟定位误差 hyp[scale] 0.5 # 缩放扰动模拟不同成像高度3.2.1 为什么禁用旋转增强遥感图像中飞机跑道方向、船只航向、油罐排列均具地理意义。degrees10会使飞机机翼旋转后与跑道不平行模型学到错误姿态关联。实测关闭旋转后飞机方向敏感度下降42%mAP0.5稳定在78.6%开启时为72.1%。3.2.2 mosaic增强的遥感适配技巧标准mosaic将4图拼成正方形但遥感图像常为宽幅如4000×800。我们修改datasets.py中LoadImagesAndLabels.__getitem__# 替换原mosaic逻辑优先选择同区域图像拼接如都来自港口A避免背景突变 if random.random() hyp[mosaic]: # 从同一地理分区文件名前缀中采样3张图而非全局随机 region_prefix img_path.stem.split(_)[0] # 如port_shanghai_001 regional_imgs [p for p in all_images if p.stem.startswith(region_prefix)] if len(regional_imgs) 3: mosaic_imgs random.sample(regional_imgs, 3) [img_path] else: mosaic_imgs random.sample(all_images, 4)此改动使mosaic后背景纹理一致如全为海水或全为机场水泥地减少模型混淆。3.3 训练过程监控与早停策略YOLOv5默认300 epoch可能过拟合。我们基于验证集loss plateau实施动态早停3.3.1 修改train.py添加早停逻辑# 在train.py末尾添加约第450行 best_fitness 0.0 patience 50 # 连续50 epoch无提升则停止 patience_counter 0 for epoch in range(start_epoch, epochs): # ... 训练循环 ... # 验证后 fitness results[2] * 0.5 results[3] * 0.5 # mAP0.5 mAP0.5:0.95加权 if fitness best_fitness: best_fitness fitness patience_counter 0 torch.save(model.state_dict(), weights/best.pt) else: patience_counter 1 if patience_counter patience: print(fEarly stopping at epoch {epoch} due to no improvement in {patience} epochs) breakfitness公式强调mAP0.5遥感任务更关注定位精度而非严格IoU0.5:0.95patience50经验证本数据集通常在210–260 epoch达到峰值过早停止损失精度过晚导致过拟合。3.3.2 关键指标解读表指标遥感场景健康值异常含义应对措施Box Loss0.03–0.080.15学习率过高或anchor不匹配 → 降低lr或重聚类anchorsObj Loss0.05–0.120.02检测头过于自信 → 增加obj_loss权重修改models/common.pyCls Loss0.02–0.060.10类别区分困难 → 检查油罐/船只标注混淆如将驳船标为油罐Precision0.82–0.890.75背景误检多 → 加强hsv_v增强或增加negative miningRecall0.78–0.850.70小目标漏检 → 提高--img尺寸或启用--multi-scale4. 验证与推理如何用训练好的模型在新遥感图像上可靠检测4.1 使用detect.py进行批量推理并生成GIS友好的结果YOLOv5默认detect.py输出图像和results.txt但遥感分析需坐标回溯到原始地理空间。我们扩展其功能# 推理命令指定原始大图路径自动切片合并 python detect.py \ --weights runs/train/yolov5s_rs/weights/best.pt \ --source /path/to/satellite_image.tif \ --img 1280 \ --conf 0.25 \ --iou 0.45 \ --save-txt \ --save-conf \ --project inference_results \ --name port_a \ --geo-tiff /path/to/satellite_image.tif # 新增参数传入原始GeoTIFF获取坐标系4.1.1--geo-tiff参数实现原理# 在detect.py中解析GDAL元数据 from osgeo import gdal ds gdal.Open(opt.geo_tiff) gt ds.GetGeoTransform() # (ulx, xres, xskew, uly, yskew, yres) # 将归一化坐标(x,y,w,h)转为地理坐标 x_geo gt[0] (x_center * img_width) * gt[1] (y_center * img_height) * gt[2] y_geo gt[3] (x_center * img_width) * gt[4] (y_center * img_height) * gt[5] # 输出GeoJSON格式结果 feature { type: Feature, geometry: { type: Polygon, coordinates: [[ [x_geo - w_geo/2, y_geo - h_geo/2], [x_geo w_geo/2, y_geo - h_geo/2], [x_geo w_geo/2, y_geo h_geo/2], [x_geo - w_geo/2, y_geo h_geo/2], [x_geo - w_geo/2, y_geo - h_geo/2] ]] }, properties: {class: class_name, confidence: conf} }输出inference_results/port_a/labels/*.json可直接加载到QGIS或ArcGISw_geo,h_geo由像素宽高×分辨率gt[1],gt[5]计算得出保证地理精度。4.2 评估指标计算超越mAP的遥感专用度量YOLOv5默认test.py只输出mAP但遥感任务需关注定位误差LE预测框中心与真实框中心的欧氏距离像素方向一致性DC飞机/船只航向角误差度漏检率MR真实目标未被检出的比例尤其密集停机坪场景。4.2.1 批量计算LE与MR的脚本# eval_le_mr.py import numpy as np from pathlib import Path def calculate_le_mr(pred_dir, true_dir, iou_thresh0.5): pred_files sorted(Path(pred_dir).glob(*.txt)) le_list, mr_count, total_true [], 0, 0 for pred_file in pred_files: true_file Path(true_dir) / f{pred_file.stem}.txt if not true_file.exists(): continue # 读取预测框归一化坐标 preds np.loadtxt(pred_file, delimiter , ndmin2) truths np.loadtxt(true_file, delimiter , ndmin2) # 转为像素坐标假设图像尺寸已知 img_w, img_h 1280, 1280 # 与--img一致 preds[:, 1:] * [img_w, img_h, img_w, img_h] # x,y,w,h - pixel truths[:, 1:] * [img_w, img_h, img_w, img_h] # 计算中心点 pred_centers preds[:, 1:3] preds[:, 3:5] / 2 true_centers truths[:, 1:3] truths[:, 3:5] / 2 # LE最近邻匹配 for t_c in true_centers: if len(pred_centers) 0: mr_count 1 continue dists np.linalg.norm(pred_centers - t_c, axis1) min_idx np.argmin(dists) if dists[min_idx] 15: # LE 15像素视为准确定位 le_list.append(dists[min_idx]) else: mr_count 1 total_true len(true_centers) le_mean np.mean(le_list) if le_list else float(inf) mr mr_count / total_true if total_true else 0 return le_mean, mr le, mr calculate_le_mr(inference_results/port_a/labels, dataset_yolov5/labels/val) print(fLocalization Error: {le:.2f}px, Miss Rate: {mr:.3f})LE 12px满足亚米级定位需求0.3m/pixel卫星MR 0.08密集场景如航母甲板可接受阈值本数据集最佳模型达成LE9.3px,MR0.062。4.3 模型轻量化部署将YOLOv5s转为ONNX并在边缘设备运行遥感分析常需在无人机或星载计算机实时处理。YOLOv5s转ONNX后可部署至Jetson AGX Orin# 导出ONNX--dynamic指定batch维度可变适配不同尺寸输入 python export.py \ --weights runs/train/yolov5s_rs/weights/best.pt \ --include onnx \ --dynamic \ --imgsz 1280 # 使用ONNX Runtime推理Python import onnxruntime as ort import numpy as np session ort.InferenceSession(yolov5s_rs.onnx) input_name session.get_inputs()[0].name output_name session.get_outputs()[0].name # 预处理BGR→RGB→归一化→NHWC→NCHW img cv2.imread(test.jpg)[:, :, ::-1] # BGR to RGB img cv2.resize(img, (1280, 1280)) img img.astype(np.float32) / 255.0 img np.transpose(img, (2, 0, 1)) # HWC→CHW img np.expand_dims(img, 0) # CHW→NCHW # 推理 preds session.run([output_name], {input_name: img})[0] # 后处理NMS使用torchvision.ops.nms...Orin实测性能1280×1280输入YOLOv5s ONNX模型达23 FPSTensorRT优化后可达41 FPS内存占用ONNX模型仅14.2MB远低于PyTorch模型42MB适合星载存储限制。本文还有配套的精品资源点击获取
上一篇/下一篇内容由系统自动关联
返回资讯列表 →