YOLOv5遥感图像目标检测:从切片训练到推理部署全流程解析
发布时间:2026/10/1 17:28:29 作者:尧图编辑部 阅读量:1,286

简介YOLOv5算法在遥感图像目标识别中的应用项目资源包面向遥感、计算机视觉方向的高校学生、科研人员及企业开发者适用于毕业设计、课程项目、作业演示或高分竞赛展示。资源以YOLOv5为核心提供从数据准备、模型训练到推理识别的完整闭环可帮助读者快速掌握目标检测在卫星图像中的落地方法。内含完整Python源码、YAML模型配置、预训练权重.pt、训练过程可视化图片png/jpg与日志文件并附带dockerfile、shell脚本、IPython notebook及Markdown说明便于快速部署、复现实验和二次开发。压缩包共156个文件大小约242.81MB代码经导师审核与答辩验证95分所有程序均测试稳定可直接运行。目前已有42人学习下载适合初学者循序渐进学习也可在原有框架上扩展优化应用于遥感影像飞机、船只、建筑物等目标识别任务。1. 把遥感图交给YOLOv5之前先弄明白这个资源包到底在解决什么拿到一批遥感影像想识别机场里的飞机、港口边的船舶、油库里的油罐第一反应是跑YOLOv5第二反应是拿COCO预训练权重直接推理然后翻车。遥感图是俯视视角目标只占几十像素甚至十几个像素COCO权重的anchor和后处理参数全是为自然场景调的。这个资源包的价值不在训练代码本身——训练代码是YOLOv5现成的——而在于把“环境配置、遥感图像标注、小目标切片、超参数调整、推理后处理、大图拼接”这条链路整理成可以照着复现的项目文件让从业者少走弯路。适合手里有遥感数据集、想用YOLOv5出结果的研究生、工程师和GIS从业者。很多人以为资源包是封装好的黑匣子装上一键出图实际不是。它是把训练到推理这段链路里所有会踩坑的环节拆成项目和参数方案主线仍然是YOLOv5源码本身。2. 把YOLOv5跑在遥感图上从conda环境配置到标注格式转换2.1 conda yolov5环境配置先定CUDA版本再装依赖配置环境是遥感项目资源包的第一步也是翻车率最高的环节。问题通常不出在YOLOv5本身而出在PyTorch版本和CUDA驱动不匹配。我一般建议用conda新建独立环境不要直接装在base里因为遥感项目经常还要开GDAL、rasterio、saga这类地理空间库依赖互相打架很常见。常见做法是先创建python 3.9环境再安装匹配CUDA的PyTorch最后下载YOLOv5源码并安装依赖命令序列如下。conda create -n yolov5 python3.9 -y conda activate yolov5 pip install torch2.0.1 torchvision0.15.2 --index-url https://download.pytorch.org/whl/cu118 git clone https://github.com/ultralytics/yolov5.git cd yolov5 pip install -r requirements.txt第一行创建环境python版本锁在3.9这个版本和当前主流PyTorch编译产物兼容度最好。第三行指定了CUDA 11.8对应的PyTorch轮子包如果你的显卡驱动是CUDA 12.x可以把cu118改成cu121如果是老卡比如GTX 10系需要用cu117或者更低的轮子。先用nvidia-smi看驱动支持的CUDA最高版本再决定安装哪个轮子。安装完PyTorch后可以用python -c import torch; print(torch.cuda.is_available())验证GPU是否可用输出True再进下一步。git clone拉下来的是YOLOv5源码主分支特征包含8000多行Python和少量C算子。后面所有训练和推理命令都在这个目录下执行所以conda yolov5环境配置其实是这套流程里最不需要动脑但最不能跳过的步骤。资源包里的环境配置部分一般就是把这四行命令写好附带requirements.txt里每个包的版本说明避免新版包接口变化导致代码跑不通。2.2 遥感图像标注从VOC XML转成YOLO格式的归一化坐标遥感图像标注工具现在很成熟LabelMe、X-AnyLabeling、CVAT都支持遥感影像标注导出的格式通常是VOC XML或者COCO JSON。YOLOv5不直接吃这两种格式它要求每张图片对应一个同名txt文件每行内容是“类别编号 归一化中心x 归一化中心y 归一化宽度 归一化高度”。VOC格式转YOLO格式是资源包里必备的脚本核心逻辑是解析XML里的bndbox再把像素坐标归一化到0到1之间。import xml.etree.ElementTree as ET from pathlib import Path class_names [airplane, ship, oil_tank] cat_id {name: i for i, name in enumerate(class_names)} def voc2yolo(xml_path: str, img_w: int, img_h: int) - list: tree ET.parse(xml_path) root tree.getroot() lines [] for obj in root.iter(object): name obj.findtext(name) if name not in cat_id: continue box obj.find(bndbox) x1 float(box.findtext(xmin)) y1 float(box.findtext(ymin)) x2 float(box.findtext(xmax)) y2 float(box.findtext(ymax)) cx (x1 x2) / 2 / img_w cy (y1 y2) / 2 / img_h w (x2 - x1) / img_w h (y2 - y1) / img_h lines.append(f{cat_id[name]} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}) return lines这段脚本的关键点有两个。第一是类别编号从0开始顺序必须和后面data.yaml里的names列表一致写错一个顺序整个训练就废了。第二是归一化分母用的是图片实际宽高不是标注文件里的相对坐标。踩坑最多的地方是图片被重采样过但XML没同步更新。有些遥感数据源的原始分辨率是0.5米处理时被重采样成1米像素宽高变了XML里的bndbox坐标还是旧的。转换后的txt文件坐标就会整体偏移训练出的模型框错位。所以转换后一定要做验证随机抽几张图用Python把txt坐标画回图上肉眼确认框和物体对齐再开始训练。资源包里的通用做法是把转换和验证画图写成同一个脚本转换完自动输出一张带框效果图这一步省不得。2.3 小目标识别大图切片与重叠滑窗遥感图像幅面大常见的场景是单张5120×5120甚至更大。如果整张缩放到640×640一个原本只有20×20像素的飞机缩完后只剩2.5×2.5像素模型根本不可能学出特征。所以第一步是做切片把大图切成模型能处理的尺寸。这一步是资源包的核心价值所在也是遥感图像目标检测区别于普通目标检测的关键操作。常用做法是滑窗切块切片过程中同步处理标注框坐标。下面是一个带重叠率的切片示意脚本。import cv2 import numpy as np def slide_crop(img, boxes, tile640, overlap0.2): h, w img.shape[:2] step int(tile * (1 - overlap)) tiles [] for y in range(0, h - tile 1, step): for x in range(0, w - tile 1, step): crop img[y:y tile, x:x tile] new_boxes [] for cls, cx, cy, bw, bh in boxes: abs_x1 (cx - bw / 2) * w abs_y1 (cy - bh / 2) * h abs_x2 (cx bw / 2) * w abs_y2 (cy bh / 2) * h x1 max(0.0, abs_x1 - x) y1 max(0.0, abs_y1 - y) x2 min(tile, abs_x2 - x) y2 min(tile, abs_y2 - y) if x2 - x1 8 or y2 - y1 8: continue new_boxes.append((cls, (x1 x2) / 2 / tile, (y1 y2) / 2 / tile, (x2 - x1) / tile, (y2 - y1) / tile)) tiles.append((crop, new_boxes)) return tiles这个脚本的关键是切片步长step tile × (1 - overlap)。overlap取0.2即20%重叠。重叠的目的不是增强而是保证跨切片边界的目标至少在一个切片里是完整的。如果目标被切成两半两个切片里各剩一半且残留面积不足8像素就会被过滤掉这个目标就白白从训练数据里消失了。overlap取值需要参考目标最大尺寸我一般会设成目标最大尺寸除以切片尺寸再留一点余量通常0.1到0.2之间。切片尺寸也有讲究常用的是640或1280。用1280可以保留更多上下文但对显存要求翻倍用640则小目标仍然偏小。我的做法是先用标注数据统计目标框的像素尺寸分布如果大部分目标在20到50像素之间用640切片合适如果在50像素以上可以试试1280但训练batch要相应降低。资源包一般会提供一个统计分析脚本输出目标尺寸直方图这个图直接决定你后面的切片参数。3. 用YOLOv5训练自己的遥感数据集权重选择与超参数调整3.1 迁移学习COCO预训练权重是半成品记得做冻结和微调遥感数据集的规模通常不大一两千张标注图就算不错从头训练模型几乎不可能收敛。主流做法是加载YOLOv5在COCO上预训练好的权重在这个基础上微调。但要注意COCO预训练权重对遥感场景只是半成品它提供的是低中层的视觉特征比如边缘、角点、纹理这些在遥感图上同样适用但高层的语义特征和anch0r先验统计完全不匹配必须通过训练覆盖掉。常用启动命令是python train.py --data data.yaml --weights yolov5s.pt --img 1280 --batch 8 --epochs 150 --cache --freeze 10--weights参数指定COCO预训练权重yolov5s.pt选s是因为遥感小目标识别模型容错率有限太大反而容易过拟合数据量超过5000张可以换yolov5m.pt但训练时间也上去了。--freeze 10表示冻结前10层参数只训练骨干以外的部分。冻结的目的不是加速是防止小数据集在训练初期破坏预训练特征。遥感图像和自然图像差异大冻结层数不宜过多10层以内比较稳妥。迁移学习的另一个常见问题是把全图resize到固定尺寸。--img 1280会让YOLOv5自适应调整网络结构输入分辨率越大小目标的像素占比越高。但这也会放大显存占用batch 8在12G显存上基本是上限。如果显存只有8G把batch降到4或者使用--rect模式减少空白填充效果比降低分辨率更划算。资源包里通常会把多组显存对应的训练参数写成表格照着填就不会OOM。3.2 yolov5超参数遥感场景先调这五个训练自己数据集时data.yaml要自己写。路径建议用绝对路径YOLOv5对相对路径的解析在换机器后经常出问题。train: /data/rsc/train/images val: /data/rsc/val/images nc: 3 names: [airplane, ship, oil_tank]train和val指向图片目录YOLOv5会按同名规则自动找标签文件。nc是类别数names和VOC转换脚本里的class_names必须完全一致。 这一部分写好后还有一个hyp超参数文件需要动默认的hyp.scratch-low.yaml是COCO调出来的参数直接套遥感场景会有三个明显问题。第一是颜色增强。默认hsv_h、hsv_s、hsv_v都有非零值会随机改变色调饱和度和明度这对自然图像很合适但遥感图像的色调具有物理意义例如植被的绿、水体的蓝黑随意改变色调会让模型学到错误的颜色关联。我一般会把hsv_h、hsv_s、hsv_v全部设成0只保留随机翻转和缩放。第二是fliplr默认0.5的概率左右翻转。这对飞机这类有方向性的目标很致命停机坪上飞机头朝左翻转后朝右类别没变但几何语义完全变味模型被迫学习矛盾的形态。遥感图像检测通常把fliplr设成0或很小。第三是mosaic增强。YOLOv5默认训练时会做mosaic把4张图拼在一起。这个增强对普通检测很有用但遥感大图切块后mosaic会让边界处的目标进一步挤压变形。如果目标本身已经很小mosaic反而压掉了有效像素。我的做法是先把训练跑50轮看loss曲线如果mAP起步很低且波动大就把mosaic设成0.5或0。下面是微调后的hyp片段lr0: 0.01 hsv_h: 0.0 hsv_s: 0.0 hsv_v: 0.0 fliplr: 0.0 mosaic: 0.5lr0默认0.01对迁移学习偏激进这是经验值。如果训练时loss在前10轮就快速下降然后震荡说明lr0偏大可以降到0.001重跑。YOLOv5有autoanchor机制训练开始时会自动重新聚类anchor并在日志里打印“autoanchor: 修改建议”。如果默认anchor和遥感目标的尺寸分布差异大autoanchor会给出新的anchor。这条日志值得重视因为它直接影响小目标识别的上限。3.3 训练命令与日志判读哪些指标变化说明模型在真正学习数据准备完、超参调好后正式训练命令和检测命令长这样python train.py --data data.yaml --weights yolov5s.pt --img 1280 --batch 8 --epochs 300 --patience 100 --cache --hyp data/hyps/hyp.remote.yaml--patience 100的意思是验证集mAP连续100轮不提升就早停这个保护机制能省下大量无效训练时间。--hyp指向修改后的超参文件。训练开始后会输出一个进度表包含box_loss、cls_loss、dfl_loss三项loss以及P、R、mAP50、mAP50-95四个评价指标。读日志的要点是看趋势而不是绝对值。box_loss持续下降说明回归框在学习cls_loss下降说明分类在学习mAP50快速上升通常出现在前50轮mAP50-95比mAP50爬得慢因为它对框的精度更敏感。如果mAP50在上升但mAP50-95几乎不动说明框定位不准常见原因是anchor尺度过大小目标被当成背景。训练结束后YOLOv5会在runs/train/exp目录下生成results.png里面有每个epoch的曲线这是排查训练过程最直接的图。超参数的调优在资源包里往往被描述成玄学实际上遥感场景就那几个变量。数据量少、目标小、背景复杂这三个条件决定了要优先调的是img尺寸、anchor、mosaic。其他超参数比如momentum、weight_decay保持默认即可改动它们通常不会带来肉眼可见的收益反而增加排查难度。4. 遥感场景的推理与后处理从切块预测到坐标还原4.1 直接跑detect.py会翻车遥感大图为什么不能整体resize训练完成后很多人直接把大图丢给detect.py这是资源包用户最常见的误用。detect.py内部默认会做letterbox把任意尺寸的输入resize到640×640这个操作会把遥感大图里的小目标压成亚像素几乎全部漏检。正确做法是在推理阶段同样采用滑窗切块把检测结果坐标还原到原图后再统一做后处理。下面用伪代码说明推理流程的核心逻辑all_dets [] for x, y, crop in slide_crop(img, tile640, overlap0.2): dets model(crop, conf0.1, iou0.3) # 每个窗口独立检测 for det in dets: det.x1 x det.y1 y det.x2 x det.y2 y all_dets.append(det) final nms(all_dets, iou_thres0.3)每个滑窗预测出的框要加回窗口左上角坐标还原到原图坐标系。这里有个容易被忽略的环节先拼后做NMS而不是每个窗口先各自NMS再拼。因为同一个目标如果被两个相邻窗口各检测到一半先各自NMS会把这两个半框都保留拼图后出现重复框只有把所有窗口的检测结果汇总到一个列表里再做全局NMS才能去重。资源包里一般把这段逻辑封装成inference.py同时输出带框大图和不带框的干净图。NMS之后的二次过滤也很有必要。遥感图中大量目标本身就很模糊比如小型船舶在低分辨率下就是一个亮斑模型输出置信度多在0.2到0.5之间默认的conf-thres 0.25会漏掉一大批。推理阶段把conf-thres放到0.1宁可多出几个假阳性框也不要漏检假阳性可以通过后面按类别统计或人工审核过滤。下面是YOLOv5 detect.py推理时常用的参数组合和说明。参数推荐值说明conf-thres0.1遥感小目标置信度普遍偏低0.1能减少漏检iou-thres0.3密集目标区域更保守0.3防止邻近目标被合并img1280推理尺寸保持训练尺寸不降分辨率augment启用TTA增强小目标检出速度会明显变慢agnostic-nms启用不同类别不互相抑制适合场景内多类目标堆叠4.2 NMS的局限性密集目标场景下需要调整IoU阈值机场停机坪和港口码头是遥感目标识别里最典型的密集场景飞机和集装箱排列紧密目标之间几乎没有空隙。此时默认的iou-thres 0.5会把相邻目标的框合并成一个表现为输出框只有一个且框住两个目标。对策是调低iou-thres到0.3或0.2让两个高重叠的框各自保留。代价是同一个目标可能出现重复框后续再加一层模式分类帮助不大直接按置信度取top1即可。agnostic-nms这个参数也很关键。默认YOLOv5的NMS是按类别分别做的不同类别之间不会互相抑制。遥感场景里油罐和飞机外形差异大按类别抑制没大问题但如果两个不同类别在空间上高度重合比如“油箱”和“卡车货箱”agnostic-nms能让低置信度的框让路。4.3 坐标还原与地理编码从像素坐标映射到经纬度遥感图像最终要落到GIS平台里使用光有像素坐标不够。如果输入图像是GeoTIFF可以使用rasterio读取地理变换矩阵把像素坐标映射到投影坐标。import rasterio with rasterio.open(raster.tif) as src: transform src.transform px, py 1024, 768 x transform.c px * transform.a y transform.f py * transform.etransform是影像左上角地理坐标和像元分辨率的仿射变换参数。x和y就是该像素对应的地图坐标。要转经纬度再用pyproj做一次坐标系转换。资源包里如果附带地理编码工具通常就是用这两行代码做的。如果输入是普通TIFF或JPG没有地理元数据就只能输出像素坐标后续靠GIS平台通过控制点配准。这一点在资源包的README里应当写明因为不少用户试图从普通JPG里直接拿到经纬度这是不可能的。5. 遥感目标识别踩坑记录四个高频问题与排查路径5.1 训练loss先降后升mAP在最后几轮跳崖现象训练前期loss正常下降到第100轮左右loss反升验证集mAP突然掉到接近0。这看起来像过拟合但实际原因是数据泄漏。遥感数据集通常由若干张大图切片而来如果切片时随机打乱同一张大图的不同切片可能同时出现在训练集和验证集模型在训练时已经见过几乎相同的背景纹理验证时遇到同源图像表现虚高等到模型真正泛化到独立场景时就崩了。解决用大图分块而不是切片分集。先按原始影像编号分组把整张大图的所有切片全部放进训练集或全部放进验证集。这样验证集才真正代表“没见过的场景”。如果数据源只有一两张覆盖同一区域的大图切片后无论如何分集都会泄漏这时只能增加不同季节、不同角度的数据而不是调整参数。5.2 切块边界切断目标推理时框消失现象检测结果里位于两片相邻切片交界处的目标经常漏检明显低于图像中央区域的目标检出率。原因是滑窗切块时目标被窗口边界切成两半单侧残片面积过小被脚本的8像素阈值过滤掉或者因为残留像素过少置信度低于阈值。重叠率设太小是根因。解决把overlap从0.2提高到0.3或者让overlap不小于目标最大尺寸。具体做法是先统计标注数据里最大目标的长边像素值然后overlap取max(0.2, max_target_size / tile_size)。同时切片脚本里过滤目标的最小面积阈值不要写死按目标尺寸分布动态调整。推理阶段同样要使用和训练一致的切片参数否则边界效应会重新出现。5.3 训练完框错位明显验证集mAP却很高现象模型在验证集上mAP50达到0.85但把输出框画回原图很多框的中心点偏移了半个目标宽度框和目标肉眼可见不对齐。原因是VOC转YOLO脚本里写死了图像宽度和高度或者图片在预处理时被重采样过而XML没有同步更新。YOLO的归一化坐标一旦分母错所有框都会系统性偏移。解决在转换脚本里直接从图像文件读取宽高不要用配置文件里的固定值。转换完成后做一次叠加验证把txt坐标按原图宽高换算回像素值用cv2.rectangle画框保存逐一对照标注物体是否对齐。这一步在每批数据转换后都要做不需要全部检查随机抽20张图基本就能发现问题。5.4 mAP50可以但mAP50-95极低小目标是重灾区现象训练完mAP50有0.8以上mAP50-95只有0.2左右。这说明框的位置不够准尤其是小目标。YOLOv5评价指标里mAP50只看框和真值的IoU是否超过0.5mAP50-95会从0.5一直算到0.95要求框和真值高度重合。小目标本身只有十几个像素框偏3个像素IoU就掉一大截。解决先看autoanchor日志确认YOLOv5给出的建议anchor里有没有小尺寸锚框没有就说明默认anchor对小目标不友好可以改用kmeans对训练集的真实框重新聚类。再看训练时的img尺寸640对小目标来说仍偏小尝试提到1280。最后检查标注框是否贴边很多遥感标注工具自动外扩了背景框本身覆盖了目标的1.2倍这会让模型学到的框整体偏大IoU上限被标注质量锁死。排查顺序应该是标注质量先行然后anchor最后才是超参数。6. 验证自己的训练结果交叉验证、对比实验与SAHI推理增强技巧训练完模型第一件事不是马上部署而是做一次独立的验证。我习惯的做法是将数据按大图而不是按切片划分拆成三折分别训练三个模型把三个模型在各自验证集上的mAP取平均。这个数字比单次训练的结果可信得多能过滤掉数据集本身分布不均带来的幻觉。做完交叉验证再和基线对比用同一个数据集跑YOLOv5s、YOLOv5m和YOLOv8n看遥感小目标场景下谁的实际收益高而不是看谁的论文指标好看。推理层面的增强有一个性价比很高的技巧启用SAHI代替手写滑窗。SAHI是一个专门做航空影像目标检测的库和YOLOv5做了适配安装后可以直接调用其切片推理接口。python scripts/sahi_detect.py --source big_image.tif --model-weights runs/train/exp/weights/best.pt --slice-size 640 --overlap 0.2SAHI会自动完成切片、预测、拼回和全图尺度NMS减少自己写切窗逻辑的排错时间。但要注意slice-size和overlap必须和训练时保持一致否则检测结果会因切片尺寸不一致而出现目标尺度失真。推理增强还有一个选项是开启TTA即推理时对输入做翻转和多尺度增强再叠加结果通常能带来2到3个mAP50的提升代价是推理时间成倍增加实时性要求不高的场景可以承受。我现在拿到一个新遥感数据集会先花一个小时把大图的标注框画出来看一眼统计目标尺寸分布再决定切片尺寸、overlap和anchor配置。这一步省掉的话后面整轮训练跑完才发现小目标全漏检返工成本高得多。希望帮到你。本文还有配套的精品资源点击获取