遥感卫星图像目标检测:从XML标注到YOLOv5训练实战

📅 发布时间:2026/9/16 2:30:37
遥感卫星图像目标检测:从XML标注到YOLOv5训练实战
简介遥感卫星图像目标检测数据集面向计算机视觉与遥感应用开发者包含5000张遥感图像及一一对应的XML标注文件为训练目标检测模型提供高质量标注数据适用于建筑物、车辆、植被等多类目标识别场景。压缩包共2000个文件全部为XML标注文件压缩后约302.92MB每个XML对应一张卫星图像可用于R-CNN、YOLO、Faster R-CNN等主流检测模型的训练。XML标注采用Pascal VOC结构记录文件名、图像尺寸、目标类别及边界框坐标xmin、ymin、xmax、ymax便于解析转换为TFRecord或PyTorch数据加载格式。已有524人学习下载适合具备一定深度学习基础、希望强化遥感图像检测实战能力的开发者和研究者。通过研读典型标注样例可快速理解遥感影像数据的组织方式减少数据清洗与格式转换的时间成本加速检测模型的迭代与优化。1. 遥感卫星图像的目标检测为什么这份5000张XML标注数据集值得拆解在常规目标检测中模型见惯了街头摄影与生活场景一到遥感卫星图像上往往表现大跌眼镜目标尺寸从几十像素到几个像素方向任意背景纹理复杂同一栋建筑在俯视图里可能只剩一个房顶轮廓。这份遥感卫星图像数据集恰恰是专门为这类俯视场景准备的。它包含5000张图像和对应的5000个XML标注文件标注字段沿用VOC风格覆盖了建筑物、车辆、植被等多类目标格式足够干净四类信息文件名、尺寸、类别、边界框一应俱全。这类数据集的核心价值不在数量而在标注与图像之间的一致性和可解析性。对做目标检测算法研究或工程落地的人来说拿到手之后首先需要确认的是XML结构是否规整、类别分布是否均衡、边界框是否有越界或全图标注而这套数据集的XML结构给出了清晰的扩展空间。后面我会从XML解析、格式转换、模型训练到小目标优化一步步把这条链路走通。无论你是准备用YOLO系列快速验证还是要在Faster R-CNN上做精细调参这套数据都能作为标准锚点。2. 从XML标注到训练样本解析VOC格式并构建标准化数据集2.1 XML标注结构里的关键字段和边界框含义拿到这5000个XML文件第一步不是急着扔给模型而是先读透结构。VOC格式的XML标注通常包含annotation根节点内部有folder、filename、size和多个object子节点。size中的width与height必须和对应图像的实际像素一致否则后续做归一化边界框时会整体偏移。每个object里的name是类别标签bndbox下的xmin, ymin, xmax, ymax表示左上角和右下角的绝对像素坐标。注意这里的坐标原点是图像的左上角x轴向右y轴向下与常见图像处理库一致。对遥感卫星图像来说truncated和difficult字段往往被忽略但difficult字段语义很重要。困难样本如果直接参与训练会引入高噪声梯度如果数量不大更稳妥的做法是先统计difficult1的样本数再决定是否从训练集中剔除。我通常会在解析阶段把这两个字段一并读出而不是直接丢弃方便后续做消融实验或分析标注质量。一个容易被忽略的问题是同一张图像中可能出现多个object节点。遥感俯视图里密集分布的建筑和小型车辆会让一张图带几十个目标解析时不能只读第一个object必须循环读取否则训练数据会严重丢失。比如一个码头场景可能同时有船舶和集装箱多个目标写在同一个XML文件里是常态。2.2 用Python解析XML并生成COCO或YOLO格式开源目标检测框架如Ultralytics YOLO、MMDetection通常不直接接受XML需要先转成对应的标签格式。以YOLO为例需要为每个图像生成一个同名txt文件每行写class_id x_center y_center width height其中四个值均为归一化到0~1的浮点数。转换时还要注意YOLO要求边界框坐标使用中心点加宽高的形式而不是VOC的左上右下。下面这段解析脚本覆盖了从XML到YOLO txt的完整转换同时设计了简单的越界检查与类别映射import xml.etree.ElementTree as ET import os def voc_to_yolo(xml_path, out_dir, class_names): tree ET.parse(xml_path) root tree.getroot() # 图像尺寸 size root.find(size) img_w int(size.find(width).text) img_h int(size.find(height).text) lines [] for obj in root.iter(object): name obj.find(name).text if name not in class_names: print(funknown class {name} in {xml_path}) continue cls_id class_names.index(name) box obj.find(bndbox) xmin float(box.find(xmin).text) ymin float(box.find(ymin).text) xmax float(box.find(xmax).text) ymax float(box.find(ymax).text) # 越界保护 xmin max(0, min(img_w, xmin)) xmax max(0, min(img_w, xmax)) ymin max(0, min(img_h, ymin)) ymax max(0, min(img_h, ymax)) # 宽度和高度可能为0的情况 if xmax xmin or ymax ymin: continue x_center (xmin xmax) / 2 / img_w y_center (ymin ymax) / 2 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}) xml_name os.path.basename(xml_path).replace(.xml, .txt) with open(os.path.join(out_dir, xml_name), w) as f: f.write(\n.join(lines))这段逻辑需要配合class_names列表使用。img_w / img_h决定归一化基准任何一张图只要是宽高比不一致都要优先从XML的size读取而不是从固定配置里取。越界保护用的是min/max夹取避免标注误差导致归一化值大于1或小于0我在实际转换中也见过y轴方向写反的问题所以建议每个维度都输出日志抽样打印前几个转换结果。2.2.1 数据集统计与类别均衡检查转换完成后不能直接扔进训练脚本先做一次统计学检查。遥感卫星数据集的类别分布往往极不均衡例如背景中成片出现的植被会占据大量标注框而船只、飞机这类目标可能只占极少比例。下面代码统计每个类别出现的边界框数量并生成尺寸直方图python -c import os, glob from collections import Counter label_dir labels/train cls_counter Counter() box_counter Counter() for txt in glob.glob(os.path.join(label_dir, *.txt)): with open(txt) as f: for line in f: parts line.strip().split() if len(parts) 5: cls int(parts[0]) w float(parts[3]) h float(parts[4]) box_counter[cls] 1 # 归一化宽高小于0.05视为小目标 if w 0.05 or h 0.05: cls_counter[cls] 1 print(class box count:, box_counter) print(small box count:, cls_counter) 这里我用归一化宽高小于0.05作为一个粗粒度的小目标阈值。如果发现某个类别的框数量不足100后续训练时就要考虑对这类目标做过采样或者调整损失函数的类别权重。另一个常见检查项是图像分辨率和目标绝对尺寸的关系卫星图像本身可能是512×512或更大但目标区域可能只占几十像素。这个信息直接决定你是否需要做切图处理。3. 遥感小目标场景下的模型选型与训练配置3.1 Faster R-CNN与YOLO在遥感小目标上的差异目标检测算法选型时遥感卫星图像和自然图像有一个显著区分目标绝对尺寸小、密度高。Faster R-CNN这类两阶段检测器依靠区域提议网络和RoI Pooling对中低分辨率目标有天然的定位优势但推理速度慢且候选框数量多了以后训练显存压力大。YOLO系列作为单阶段检测器在保持较高帧率的同时对小型目标的召回率往往弱于两阶段方法但通过调整锚框尺寸、输入分辨率和特征融合结构依然可以在遥感数据上获得可用精度。实际项目里我习惯先用YOLOv5做快速基线。它的模型配置文件和训练流程简单适合验证数据质量和标注一致性。如果发现小目标mAP明显偏低再切换到Faster R-CNN或Cascade R-CNN做精细调优。需要说明的是YOLOv5的默认锚框是针对COCO数据集设计的边长从几像素到几百像素不等遥感图像中常见的几十像素目标需要重新聚类锚框否则训练前期收敛会很慢。3.2 基于YOLOv5的训练流程和参数设置YOLOv5训练时要求数据按图像和标签一一对应文件夹结构通常是images/和labels/分别存放图像和txt标签。对于这套XML标注数据先完成第2章的转换然后按8:1:1划分训练、验证、测试集一个简洁的划分策略是直接按文件名哈希位做分层抽样。下面是一个dataset.yaml的示例train: datasets/remote/train/images val: datasets/remote/val/images test: datasets/remote/test/images nc: 4 names: [building, vehicle, ship, vegetation]这里nc代表类别数量names里的顺序必须和第二章转换脚本中class_names的顺序完全一致。常见错误是类别顺序不一致导致边界框类别对应错误训练时损失值会跳跃性异常。检查方式很简单随机选一张验证集图片查看它对应的txt文件再人工比对原图中的目标。启动训练的命令如下python train.py --data remote.yaml --weights yolov5s.pt --img 640 --batch 16 --epochs 100 --hyp hyp.remote.yaml关键参数说明--img控制训练输入尺寸。遥感目标小如果原始图像很大建议先用640或960而不是直接压到320否则目标尺寸会被进一步压缩。--batch需根据GPU显存调整16是个常见起点如果BatchNorm不稳定可以降低到8。--hyp指向超参数文件。遥感场景下我通常把hsv_h、hsv_s等颜色增强幅度降低因为卫星图像色调相对固定过度颜色扰动反而会让域偏移问题放大。3.2.1 迁移学习与骨干网络选择直接随机初始化训练在大数据集上可行但5000张图的量级更适合加载预训练权重。weights参数指定预训练模型比如yolov5s.pt。迁移学习的原理是让网络复用自然图像上学习到的边缘、纹理特征对遥感目标同样有效。唯一的风险是域差异过大时前几层的低层特征还有用高层语义需要更多epoch来适应。因此我在训练时会将freeze参数设为0或只冻结前10层让骨干网络也能随遥感数据更新。如果追求更高精度把yolov5s.pt换成yolov5m.pt或yolov5l.pt能显著增强对大场景下小目标的特征表达能力但显存占用和训练时间会同步上升。5000张图像用单张A100跑100个epochyolov5s大概需要2小时yolov5l可能需要6小时以上。3.2.2 锚框重聚类的必要性遥感图像中目标尺寸分布可能与COCO差异很大。YOLOv5的autoanchor功能可以在训练前自动重新聚类标注框。执行以下命令先检查当前数据集的锚框适应度python train.py --data remote.yaml --weights yolov5s.pt --img 640 --noautoanchor去掉--noautoanchor让算法在训练开始时执行k-means聚类输出新锚框并更新模型配置。观察终端打印的Anchors行如果cls和box的Gain有明显下降说明默认锚框不匹配。执行聚类后小目标对应的锚框会变得更密集比如从原来的20像素级别降到8像素级别这正是遥感小目标检测的关键调整项。4. 提升遥感目标检测精度的关键切图、增强与损失函数4.1 大图切分与小目标策略遥感卫星图像经常是几千乘几千像素的大图直接缩放到模型输入尺寸会丢失大量小目标细节。常见做法是先切成重叠切片再训练。切片尺寸一般取模型输入尺寸的1.5~2倍比如输入640时切640×640或960×960重叠率设置在128~256像素之间避免目标被截断。切图时需要同步修改标签坐标下面是一个高效的sliding window切分思路。def crop_image(img, boxes, crop_size640, overlap128): h, w img.shape[:2] crops [] new_boxes [] step crop_size - overlap for y in range(0, h, step): for x in range(0, w, step): y2 min(y crop_size, h) x2 min(x crop_size, w) crop img[y:y2, x:x2] adjusted [] for box in boxes: xmin, ymin, xmax, ymax box if xmin x2 and xmax x and ymin y2 and ymax y: nxmin max(xmin - x, 0) nymin max(ymin - y, 0) nxmax min(xmax - x, crop_size) nymax min(ymax - y, crop_size) if nxmax nxmin and nymax nymin: adjusted.append([nxmin, nymin, nxmax, nymax]) if len(adjusted) 0: crops.append(crop) new_boxes.append(adjusted) return crops, new_boxes这个切分函数的关键在于坐标偏移与越界处理。x和y是切图左上角在原图中的坐标边界框对齐时要减去这个偏移当目标横跨两个切片时会被复制到两个切片中而每个切片只保留落在自己区域内的部分。这样一来目标虽然被截断但至少不会大量丢失。训练阶段再配合随机裁剪能进一步增强模型对部分遮挡目标的鲁棒性。切片数量越多总训练样本量越大但内存和磁盘占用也线性增长需要权衡。4.2 数据增强与损失函数的实际调参遥感图像与自然图像的另一差别是旋转敏感度。卫星俯视图中的建筑和车辆通常没有固定朝向旋转增强能大幅提升模型的方向泛化能力。YOLOv5的超参数文件中已有degrees控制旋转角度遥感场景建议设置为0.5约180度范围内的随机旋转同时配合flipud0.5。但要注意degrees过大会引入大量边界框被旋转到图像外的样本反而增加无效学习。另一个有效增强是mosaic和copy_paste前者将多张图拼成一张后者将不同图上的目标复制粘贴到背景区域非常适合处理稀疏目标。如果训练时发现小目标类别召回率低除了增强还可以调整损失函数。Faster R-CNN中的rpn_cls_loss和rpn_bbox_loss权重YOLOv5中的box_loss_gain和cls_loss_gain都可以调节。常见做法是把box_loss_gain调高到0.08~0.1让模型更加关注边界框回归精度。对于类别极度不平衡的情况可以在损失函数里给高频类别更低的权重实现focal loss效果。YOLOv5的超参数文件中的cls_pw就是类别权重默认1.0当某一类目标框数量是另一类的10倍时我会把该类的cls_pw设为0.8。小目标检测评价参数不止mAP需要同时关注AP_small、AP_medium和AP_large。在验证阶段如果AP_small显著低于AP_medium就要回头确认切片尺寸和锚框是否匹配如果AP_small和AP_large都低则可能是标注噪声或类别混淆问题需要可视化坏例。5. 验证标注质量的一个实用技巧可视化XML边界框并统计分布无论模型训练效果如何标注文件本身的质量决定数据链路的可信度。这里分享一个花不了多长时间但能发现很多问题的技巧将XML中的边界框画回原图按类别用不同颜色区分输出成拼图。这个过程能直观暴露三类问题边界框是否偏离目标真实位置、类别标签是否错位、同一目标的框是否重叠或框住背景。下面脚本基于OpenCV实现import cv2 import xml.etree.ElementTree as ET def draw_xml(image_path, xml_path, color_map): img cv2.imread(image_path) tree ET.parse(xml_path) root tree.getroot() for obj in root.iter(object): name obj.find(name).text box obj.find(bndbox) xmin int(box.find(xmin).text) ymin int(box.find(ymin).text) xmax int(box.find(xmax).text) ymax int(box.find(ymax).text) color color_map.get(name, (0, 255, 0)) cv2.rectangle(img, (xmin, ymin), (xmax, ymax), color, 2) cv2.putText(img, name, (xmin, max(ymin - 5, 0)), cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 2) return img运行后将多张图纵向拼接或保存到独立目录。接着做边界框尺寸统计按类别输出最小、最大、平均宽高。我发现遥感数据集中常有xmin和xmax顺序颠倒或者标注框包含了大片背景这些靠数值检查很难发现可视化一眼就能看出来。统计代码可以用Pandas直接读txt也可以复用第2章的脚本这里不重复。一个更高级的技巧是把标注框投影到类别频率图上计算每个类别的bbox面积占图像面积的比例做成箱线图。若某类目标框的平均面积占比不足0.01那么模型很难稳定检测必须依赖高分辨率输入和多尺度特征。此时通常采用的手段是把该类目标单独裁剪为小图数据集先做一次二次分类或小图检测再融合回整体检测结果。这套级联优化思路在红外小目标检测和卫星图像船舰检测中都很常见。验证完成后建议把所有图像的边界框坐标按类别保存为一个parquet文件并在训练前固定一个随机种子做数据集划分。这样每次模型实验的评估结果都可复现也方便后续尝试多模态目标检测或Transformer检测头时直接对比同一份训练样本下的性能差异。本文还有配套的精品资源点击获取