ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

YOLO卫星图像目标检测:从数据集标注到模型训练实战

YOLO卫星图像目标检测:从数据集标注到模型训练实战 简介面向YOLO目标检测的高分辨率卫星图像标注数据集VHR-10包含800张来自Google Earth和Vaihingen的遥感图像及对应标注文件覆盖飞机、轮船、储罐、棒球场、网球场、篮球场、地面跑道、港口、桥梁和车辆10个类别适合计算机、电子信息等专业学生完成课程设计、期末大作业或毕业设计。压缩包共2612个文件主要有650张jpg图像、650个xml标注文件及1307个txt文本标注信息可直接用于YOLO系列模型训练整体大小约61.15MB目录结构清晰便于按需调用。目前已有321人学习使用。借助该数据集可省去手动标注的繁琐过程直接开展遥感目标检测实验、算法对比与模型调优配套的缓存文件也有助于快速搭建训练流程是入门遥感图像目标检测的实用资源。1. 卫星图像目标检测绕不开的训练集与标注这道坎YOLO 在车辆、船舶、建筑物等卫星图像目标检测上的落地最难的不是模型结构而是你根本拿不到标好的数据。这就是为什么一份 800 张已标注卫星图像集会被当成硬通货它直接跳过了从 0 开始标框、写 XML、转 YOLO 格式的过程。拿到手的正确姿势是解压后先做三件事核对标签格式、检查类别分布、按同源规则切分数据集。这比先跑通 train.py 更重要。适合读这篇文章的人有三类用遥感图像做毕设或课题的学生、刚接到业务方“帮我识别图上有几栋楼”需求的算法工程师、以及想验证 YOLO 在小样本遥感场景下能不能用的 GIS 开发者。2. 拿到已标注数据集先核对 YOLO 标签格式与类别分布2.1 已标注文件应该长什么样YOLO 的 txt 格式标题说“已标注文件可以直接使用”但“可直接使用”在 YOLO 生态里有严格含义。YOLOv5/v8 要求每张图对应一个同名 txt 文件里面每一行标注一个目标类别序号、框中心点的 x 坐标、框中心点的 y 坐标、框宽、框高其中四个坐标值都是 0 到 1 之间的相对值即实际像素值除以图像宽高。解压 .rar 后先别急着训练随便打开一张 txt 看一眼# 某一张卫星图的标注文件内容示例 0 0.3315 0.2412 0.0601 0.0339 1 0.6710 0.5513 0.1018 0.0715 1 0.7844 0.6078 0.0966 0.0675这段表示假设 0 代表 car、1 代表 ship第一个框中心点落在图像横向 33.15%、纵向 24.12% 的位置宽和高分别占整图宽高的 6.01% 和 3.39%。注意无论原图多大标注和图像之间都没有像素级依赖所以任意缩放图像都不需要重新标注。这里最容易出问题的是三个点。一是把 VOC 的 xml 或 labelme 的 json 当成“YOLO 格式就能用”转换时把左上角右下角坐标算成了中心点结果训练出来框全部偏移二是类别序号没有和配置文件里的 names 列表对齐原先标好的类别全乱了三是 txt 文件里用了 tab 或者带了 BOM 头训练时解析失败但报错不明显。从数据标注工具导出的文件尤其容易出现这类问题建议把它当数据预处理的一部分来做不要直接丢给训练脚本。2.2 用脚本核查 800 张图的标注质量800 张图看起来量不大但靠人眼逐一抽查不可靠正确的是写一个 Python 小脚本做四件事统计每个类别的框数量、检查坐标越界、找出空标注文件、核对图像与标签文件名是否一一对应。# check_label.py from pathlib import Path img_dir Path(images) # 图像目录 label_dir Path(labels) # YOLO txt 标签目录 cls_count {} total_boxes 0 bad_files [] # 记录有问题的文件 # 第一步两张 .txt 缺失检查缺失 该图被当作背景处理 img_names {p.stem for p in img_dir.glob(*.png)} label_names {p.stem for p in label_dir.glob(*.txt)} missing_label img_names - label_names if missing_label: print(缺标签的图像:, list(missing_label)[:10]) for label_file in sorted(label_dir.glob(*.txt)): if label_file.stat().st_size 0: bad_files.append((label_file.name, empty)) continue for line in label_file.read_text().strip().splitlines(): parts line.split() if len(parts) ! 5: bad_files.append((label_file.name, format)) break cls, x_c, y_c, w, h [float(v) for v in parts] if not (0 x_c 1 and 0 y_c 1 and 0 w 1 and 0 h 1): bad_files.append((label_file.name, out of range)) break cls_count[int(cls)] cls_count.get(int(cls), 0) 1 total_boxes 1 print(总框数:, total_boxes) print(每个类别的框数:, cls_count) print(问题文件:, bad_files[:10])脚本核心是逐行读 txt拆成五个浮点数再判断是否都在 0 到 1 之间。中心点必须落在图内宽高理论上也不超过 1。越界不一定导致训练崩溃很多训练流程会忽略越界框或裁剪它但漏检率和指标可靠性会受影响。统计类别分布的用处是如果某个类别只有五六十个框而其他类别有两三千个那这个类很可能在训练后根本学不出来要么补样本要么在训练时单独配类别权重。2.3 训练集/验证集划分与同源泄漏800 张图按经验建议切成 7:2:1即 560 张训练、160 张验证、80 张测试。但在卫星图场景有一个隐蔽的坑如果这 800 张瓦片是从同一景原始影像切出来的那随机划分会和常规自然图像截然不同。划分方式做法对遥感场景的影响不分组随机划分整批 images 按比例乱序分给 train/val同一景影像的相邻瓦片可能同时出现在训练集和验证集验证指标虚高因为模型记住了同一区域的地物纹理按原始影像分组统计每张瓦片来源同一来源的瓦片整体放入同一分桶验证集和训练集地理不重叠指标更接近新区域泛化的真实水平如果压缩包里带有来源信息比如文件名前缀相同就按前缀分组再切分。没有的话用一个简单的启发式对文件名做哈希后取模分桶。这也能解释为什么你拿同一个数据集训练别人说 mAP 有 0.8你复现只有 0.65——很可能就是切分方式不同导致的评估偏差。另外再强调一次始终保证验证集里没有伪造的“训练见过”的框否则生产环境回退到新区域时指标会暴跌。3. 用 YOLOv8 在本地训练卫星目标检测模型3.1 写 dataset.yaml 时容易错的三处训练之前先建数据配置文件。路径写绝对路径还是相对路径取决于你的工作目录但建议第一次跑全部用绝对路径把无关变量排除掉# dataset.yaml path: /home/user/remote_sense # 数据集的根目录 train: images/train # 训练图片目录 val: images/val # 验证图片目录 test: images/test # 测试图片目录 nc: 2 # 类别数量 names: [car, ship] # 类别名列表三个常见错误。第一path 写成相对路径但训练时换过当前工作目录导致找不到图YOLO 会直接报 FileNotFoundError第二train 和 val 写的是图片文件夹路径而不是 txt 文件——YOLOv8 的 dataset.yaml 字段接受绝对路径但要注意目录结尾不要带/否则部分版本的路径拼接会重复出双斜杠第三names 列表顺序必须和标签 txt 里的数字序号一致这一点最隐蔽很多人在实验中途去调整了标签序号结果训练出来的类别语义整体错乱一个全天排错的时间就浪费在这里。3.2 训练命令与参数表对于 800 张这种规模的数据我不会从随机初始化开始训练而是用官方预训练权重微调。下面这个命令是 5GB 显存以上的机器都能跑的配置yolo detect train \ datadataset.yaml \ modelyolov8s.pt \ epochs150 \ imgsz1280 \ batch16 \ patience25 \ device0 \ workers8modelyolov8s.pt加载 COCO 预训练权重。卫星图像里的目标和 COCO 天然不同但低层特征边缘、纹理、重复结构是通用的预训练带来明显的收敛加速。imgsz1280 而不是默认的 640。卫星图像上的目标普遍偏小如果你在 640 下检测车辆、小船舶目标可能只有几个像素模型很难学到有效特征。显存不够就退到 960 或 640同时调小 batch。patience25验证集指标连续 25 轮不升就早停。卫星数据集小过拟合来得快早停务必开启。device0 表示用第一块 GPU没有 GPU 就改成 devicecpu但 imgsz1280 下 CPU 训练不现实建议先用小模型跑 640 版本验证流程通畅再上 GPU。提示imgsz1280 的显存占用大约是 640 的三倍以上。遇到 OOM 先减小 batch不要直接降图像尺寸除非你确定目标在 640 下仍然大于 5 像素。训练时还可以关注另一组超参数它们对小样本遥感场景影响非常直接参数取值建议说明lr00.005 或 0.01数据量小lr0 调低一点能防止预训练权重被破坏mosaic1.0 或 0.5对尺度跨度大的遥感目标有助益但会破坏地理连续纹理可以对比后取舍scale0.5图像缩放增强范围卫星目标密集时适当调大hsv_h / hsv_s默认卫星影像色彩相对均匀增强不必开太猛3.3 训练过程看什么loss 曲线与过拟合YOLOv8 训练时终端会实时输出 box_loss、cls_loss、dfl_loss 以及 precision、recall。对小数据集重点看 train 和 val 的 box_loss 曲线train 一直降而 val 在某个 epoch 后回升就是过拟合val 指标上升太慢八成是 imgsz 太小或标注本身有噪声。训练结束会在 weights 目录下产生 best.pt 和 last.pt 两个文件best 按验证集指标自动挑选。生产上建议先拿 best.pt 做推理若 best 与 last 的指标差距很大说明训练波动明显可以适当调大 lr0 或改用带 momentum 的优化器再跑一轮。4. 预测验证从 best.pt 到整景卫星图的输出4.1 用 val 和 predict 验证模型效果训练完之后不要直接在整张大图上跑推理先用 val 看一遍指标yolo detect val modelruns/detect/train/weights/best.pt datadataset.yaml输出会给出 mAP50、mAP50-95、precision、recall。卫星图像目标小、目标密度高mAP50-95 偏低是正常的更应该参考 mAP50 和 recall。recall 低说明漏检多先做两件事把推理 conf 阈值调低训练时提高 imgsz。precision 和 recall 都低就不是阈值问题了回头查标注质量空 txt 和类别不平衡是最常见原因。验证输出里的 confusion_matrix.png 也要看它能直观告诉你哪些类别互相混淆比如小型车辆和大型车辆在低分辨率下经常被混成一个类。推理时除了单张图 predict也能对目录批量推理yolo detect predict modelruns/detect/train/weights/best.pt \ sourcetest_images/ \ imgsz1280 \ conf0.25 \ iou0.45 \ saveTrue \ save_txtTruesave_txtTrue 会把坐标以 YOLO 格式写进 txt省去自己输出的步骤。注意预测输出的 txt 坐标是相对当前推理图像的宽高的如果最后要换算成原始瓦片的绝对像素需要乘回推理图尺寸。4.2 遥感小目标的锚框与推理尺寸陷阱YOLOv8 是 anchor-free 的严格说没有固定锚框但特征金字塔的浅层、中层、深层分别负责不同尺度。卫星影像上一个 30m 的船舶在 0.5m 分辨率下是 60 像素在 10m 分辨率下只有 3 像素这就是为什么同一个模型换个分辨率后阈值哪怕不变漏检情况也完全不同。常见做法是对原始大幅卫星图切瓦片比如 10000×10000 的原图切成 1280×1280 的瓦片相邻瓦片重叠 64 像素再逐片推理。切瓦片时标签坐标要同步平移# 假设切图窗口的起始像素是 (x0, y0)新瓦片宽高是 w, h # 原标注框中心点像素坐标是 (cx_pix, cy_pix) new_cx (cx_pix - x0) / w new_cy (cy_pix - y0) / h new_w bbox_w_pix / w new_h bbox_h_pix / h核心是减掉偏移再做归一化。切图时目标在边界被一劈两半的情况很常见经验做法是框与瓦片相交面积占原框面积的比例大于 0.3 就保留该框否则丢弃。这是遥感数据扩充和推理里最常踩的坑很多人忽略它模型会把两截车辆学成错误类别。另外如果你要检测的船舶或建筑物方向性很强、需要旋转矩形框水平框方案的 YOLO 不够用常见做法是转 DOTA 数据集格式后使用 mmrotate 训练。YOLO 系的水平框和 DOTA 的旋转框是两套坐标体系不要混着用。4.3 后处理conf/iou 阈值与瓦片拼接去重切瓦片推理的另一个问题是同一目标会被相邻瓦片重复检出拼接前要做跨瓦片去重。YOLO 自带的 NMS 只是在单张瓦片内做跨图不会去重。常见做法是把所有瓦片的预测框先还原为原图坐标再跑一次全局 NMS 或 WBF加权框融合。WBF 对置信度中等但多个视角重复检出的目标往往效果好于简单 NMS因为它融合的是几何位置证据而不是直接丢弃低置信度框。读回 save_txt 输出的文件后用约 30 行的非极大值抑制代码就能完成拼接去重先试 NMS效果不够再看 WBF。这套流程对无人机正射影像同样成立只要把瓦片来源从卫星图换成正射图即可。5. 已标注数据不够时的保精度技巧5.1 K 折交叉验证评估这 800 张图样本少时单次 7:2:1 的评估方差大更好的做法是 K 折交叉验证。对 K4 或 K5 拆每折训练一次并记录指标最后取均值得到的结果能真实反映模型在数据层面的可复现性。折间必须按 2.3 节提到的同源规则切分否则指标虚高没有参考价值。具体操作上可以用结果最好的那一折权重作为最终模型其他折的指标只用来估计稳定性。如果训练环境是 CPUK 折的时间成本会成倍增加建议先单次训练验证流程K 折留到有 GPU 时再跑。5.2 用伪标签自动扩充卫星图样本如果手头还有一批没有标注的同分布卫星图一个提精度的手段是伪标签用训练好的 best.pt 对未标注图做推理把置信度超过阈值的框写成 YOLO 格式的 txt与真实标注混合后增量训练。操作上就是把第 4.1 节 predict 命令的 save_txt 输出改名复制到待扩充数据集的 labels 目录里命令行不需要额外改动。这里有两个约束伪标签只做训练集绝对不要混进验证集或测试集伪标签的框需要经过人工抽查或按类别统计过滤后再用否则错框会被模型当正确答案吸收。卫星图像上我会先从 0.75、0.8、0.85 三个置信度档位各做一次增量训练对比选验证集指标最高的那档作为最终数据配方这比盲目压低阈值收进来的大量错框更可靠。本文还有配套的精品资源点击获取
返回列表