YOLO目标检测怎么用?卫星图识别车辆?
YOLO目标检测怎么用?卫星图识别车辆? 这是很多 GIS 同学和遥感应用工程师都会遇到的实际问题:手里有一张高分辨率卫星影像,想自动找出停车场、道路、厂区里的车辆,但不知道从数据切片、标注、训练到结果回写 GIS 应该怎么做。本文按一个可复现的工作流讲清楚:YOLO 适合解决什么问题,卫星图识别车辆需要注意哪些参数,以及怎样把检测框转换成 GIS 可用的矢量结果。

引言:YOLO目标检测适合卫星图识别车辆吗
YOLO 是一种常见的目标检测模型,全称可以理解为“一次前向推理就同时预测目标类别和位置”。在 GIS 和遥感场景里,它常用于识别车辆、船只、光伏板、建筑物、油罐等具有明确外形的小目标。
对于“卫星图识别车辆”这个任务,YOLO 的优势是推理速度快、部署方式成熟、结果容易转换为矩形框矢量数据。它不需要逐像素分割车辆边界,而是输出每辆车的外接框、类别和置信度,因此非常适合做车辆数量统计、停车场占用分析、道路拥堵初筛、园区车辆巡查等任务。
但要注意:YOLO 不是把整幅遥感影像直接丢进去就能识别。卫星影像通常很大,车辆在图上又很小,必须先处理分辨率、坐标系、切片、标注和后处理,否则很容易出现漏检、误检、坐标错位等问题。
背景:卫星图识别车辆为什么比普通照片检测更难
普通照片中的车辆往往占据几十到几百个像素,而卫星图里的车辆可能只有十几个像素宽。对于 YOLO目标检测 来说,小目标本来就是难点,遥感影像又额外增加了几个 GIS 特有问题。
- 影像尺寸很大:一景 GeoTIFF 可能是几万乘几万像素,不能直接作为模型输入。
- 目标尺度很小:如果空间分辨率不够,例如 1 米或更粗,普通小汽车可能只占几个像素,识别质量会明显下降。
- 视角是俯视:卫星图中的车辆形态与街景照片不同,不能直接依赖通用车辆模型。
- 背景复杂:停车线、屋顶设备、集装箱、阴影、道路标线都可能被误识别为车辆。
- 需要空间坐标:YOLO 输出的是像素坐标,GIS 分析需要投影坐标或经纬度坐标。
因此,卫星图识别车辆的关键不是“会不会调用 YOLO”,而是能不能把遥感影像处理流程和目标检测流程接起来。
原理:YOLO检测框如何变成GIS结果
YOLO目标检测 的输出通常包含四类信息:目标类别、置信度、检测框中心点坐标、检测框宽高。这里的坐标默认是图像像素坐标,不是地图坐标。
例如,模型在某个 640×640 的影像切片中检测到一辆车,输出框的位置可能是:
class: car
confidence: 0.86
x_center: 320
y_center: 270
width: 28
height: 14
在 GIS 中,我们真正需要的是这个车辆框在原始遥感影像中的位置,例如投影坐标 EPSG:3857、EPSG:32650,或者经纬度 EPSG:4326。转换时需要两层关系:
- 切片中的像素坐标转换为原始影像中的像素坐标。
- 原始影像像素坐标通过 GeoTIFF 的仿射变换转换为地图坐标。
如果使用的是带地理参考的 GeoTIFF,可以通过 GDAL、Rasterio 或 QGIS 读取影像的 transform 信息。它记录了左上角坐标、像元大小、旋转参数等内容。只要保留每个切片在原图中的偏移量,就能把 YOLO 的检测框回写成 GeoJSON、Shapefile 或 PostGIS 空间表。
简单说:YOLO 负责“找出车在图片里的框”,GIS 后处理负责“把这个框放回真实地图位置”。这一步是卫星图识别车辆项目能否落地的关键。
步骤:用YOLO进行卫星图识别车辆的完整流程
步骤1:准备合适的卫星影像
车辆识别对影像分辨率要求较高。通常情况下,小汽车识别建议使用亚米级影像,例如 0.3 米、0.5 米或类似精度的数据。如果影像分辨率太粗,车辆目标只有几个像素,即使模型结构再好,也很难稳定识别。
准备数据时建议检查以下内容:
- 影像是否为 GeoTIFF 或其他带地理参考的数据。
- 坐标系是否明确,可以在 QGIS 中查看图层属性。
- 影像是否存在明显云遮挡、阴影、严重压缩或拉伸变形。
- 车辆目标是否足够清晰,而不是只有模糊亮点。
- 是否需要裁剪研究区,减少无关区域参与训练和推理。
如果影像是普通 PNG、JPG,但另有 world file 或坐标文件,也可以使用;不过后处理时必须确保像素坐标能够准确转换到地图坐标。
步骤2:把大幅卫星影像切成小图
YOLO 模型通常使用固定尺寸输入,例如 640×640、1024×1024。遥感影像往往远大于这个尺寸,因此必须进行影像切片。切片时建议使用重叠窗口,因为车辆可能位于切片边缘,如果没有重叠,边缘目标容易被截断。
一个常见切片策略如下:
- 切片大小:640×640 或 1024×1024。
- 重叠比例:10% 到 25%。
- 保留每个切片的原图偏移量,例如 row_offset、col_offset。
- 跳过空白区域、纯水域、无车辆场景,减少无效训练样本。
下面是一个使用 Rasterio 读取 GeoTIFF 并切片的简化示例。实际项目中还需要增加边缘补齐、空白过滤和切片记录保存。
import rasterio
from rasterio.windows import Window
from pathlib import Path
import numpy as np
from PIL import Image
src_path = "satellite.tif"
out_dir = Path("tiles")
out_dir.mkdir(exist_ok=True)
tile_size = 640
overlap = 128
stride = tile_size - overlap
with rasterio.open(src_path) as src:
width = src.width
height = src.height
tile_index = 0
for row in range(0, height, stride):
for col in range(0, width, stride):
win_width = min(tile_size, width - col)
win_height = min(tile_size, height - row)
if win_width < 256 or win_height < 256:
continue
window = Window(col, row, win_width, win_height)
data = src.read([1, 2, 3], window=window)
img = np.transpose(data, (1, 2, 0))
img = np.clip(img, 0, 255).astype("uint8")
out_name = f"tile_{tile_index}_r{row}_c{col}.jpg"
Image.fromarray(img).save(out_dir / out_name, quality=95)
tile_index += 1
文件名中保留 r 和 c 偏移量,是为了后续把检测框从切片坐标还原到原图坐标。正式项目也可以把偏移量保存到 CSV、JSON 或数据库中。
步骤3:标注车辆样本
如果你使用的是遥感车辆公开数据集,可以先用公开数据训练或微调。但在实际 GIS 项目中,最好用目标区域或相似影像源做一部分本地标注。因为不同卫星、不同城市、不同季节、不同拍摄角度会显著影响模型效果。
常见标注工具包括 CVAT、LabelImg、Roboflow、Label Studio 等。标注时建议遵守统一规则:
- 只标注清晰可见的车辆,不要把模糊亮点全部标成车辆。
- 车辆被树冠或阴影遮挡超过一半时,可单独定义是否标注。
- 小汽车、货车、公交车是否分成不同类别,需要在项目开始前决定。
- 矩形框尽量贴合车辆主体,不要包含过多阴影。
- 训练集、验证集和测试集要按区域划分,避免同一区域相邻切片同时进入训练和测试。
对于第一次做卫星图识别车辆的读者,建议先只做一个类别:vehicle。等单类别效果稳定后,再考虑 car、truck、bus 等细分类别。
步骤4:整理YOLO数据集目录
YOLO 常见的数据集结构如下。不同版本工具细节略有差异,但核心思想都是:图片和标注文件一一对应,标注文件中保存归一化后的类别和检测框。
dataset/
images/
train/
val/
test/
labels/
train/
val/
test/
data.yaml
一个 YOLO 标注文件的每一行通常表示一个目标:
0 0.5125 0.4382 0.0312 0.0187
其中第一列是类别编号,后面四列分别是归一化后的框中心点 x、中心点 y、宽度和高度。所谓归一化,就是用图像宽高把像素值转换到 0 到 1 之间。
data.yaml 可以写成类似下面的形式:
path: dataset
train: images/train
val: images/val
test: images/test
names:
0: vehicle
步骤5:训练或微调YOLO模型
训练时建议从预训练权重开始,而不是完全从零训练。对于卫星图识别车辆,小目标较多,输入尺寸可以适当提高,例如使用 1024 输入进行实验,但要注意显存压力。
以下是一个典型训练命令示例,具体参数需要根据你使用的 YOLO 实现和硬件环境调整:
yolo detect train data=dataset/data.yaml model=yolo11n.pt imgsz=1024 epochs=100 batch=8
训练过程中重点观察以下指标:
- precision:检测出来的车辆中,有多少是真车辆。
- recall:真实车辆中,有多少被模型找到了。
- mAP:综合评估不同置信度阈值下的检测质量。
- 验证集可视化:不要只看指标,一定要打开预测图检查漏检和误检类型。
如果你的目标是车辆计数,recall 往往很重要;如果目标是提取高可信车辆点位,precision 可能更重要。不同业务目标对应不同阈值选择。
步骤6:对整幅卫星影像进行推理
训练完成后,需要对原始大幅影像重新切片,并对每个切片运行 YOLO目标检测。推理时必须使用与训练阶段相近的切片大小和影像风格,否则效果会不稳定。
yolo detect predict model=runs/detect/train/weights/best.pt source=tiles imgsz=1024 conf=0.25 save_txt=True save_conf=True
推理参数中,conf 是置信度阈值。阈值越低,检出的目标越多,但误检也会增加;阈值越高,结果更保守,但容易漏掉阴影中或边缘处的车辆。
对于切片有重叠的情况,同一辆车可能在相邻切片中被检测多次。因此推理之后还需要做去重处理,常见方法是 NMS,即非极大值抑制。简单理解就是:如果两个检测框重叠很高,并且属于同一类,就保留置信度更高的那个。
步骤7:把YOLO检测框转换为GeoJSON
YOLO 输出的 txt 文件仍然是切片内的归一化像素坐标。要生成 GIS 结果,需要依次完成以下转换:
- 读取切片宽高。
- 把归一化坐标转为切片像素坐标。
- 加上切片在原始影像中的 row、col 偏移量。
- 使用原始 GeoTIFF 的 transform 把像素坐标转换为地图坐标。
- 生成 Polygon 或 Point,并保存为 GeoJSON、Shapefile 或 GeoPackage。
下面示例展示了核心转换思路。实际使用时,你需要根据自己的切片命名规则、YOLO输出路径和类别表进行适配。
import rasterio
from rasterio.transform import xy
import geopandas as gpd
from shapely.geometry import Polygon
from pathlib import Path
src_tif = "satellite.tif"
label_dir = Path("runs/detect/predict/labels")
tile_size = 640
features = []
with rasterio.open(src_tif) as src:
transform = src.transform
crs = src.crs
for label_path in label_dir.glob("*.txt"):
name = label_path.stem
parts = name.split("_")
row_offset = int([p for p in parts if p.startswith("r")][0][1:])
col_offset = int([p for p in parts if p.startswith("c")][0][1:])
for line in label_path.read_text().strip().splitlines():
values = line.split()
cls_id = int(values[0])
x_center = float(values[1]) * tile_size
y_center = float(values[2]) * tile_size
box_w = float(values[3]) * tile_size
box_h = float(values[4]) * tile_size
conf = float(values[5]) if len(values) > 5 else None
x_min = col_offset + x_center - box_w / 2
y_min = row_offset + y_center - box_h / 2
x_max = col_offset + x_center + box_w / 2
y_max = row_offset + y_center + box_h / 2
p1 = xy(transform, y_min, x_min)
p2 = xy(transform, y_min, x_max)
p3 = xy(transform, y_max, x_max)
p4 = xy(transform, y_max, x_min)
geom = Polygon([p1, p2, p3, p4, p1])
features.append({
"class_id": cls_id,
"confidence": conf,
"geometry": geom
})
gdf = gpd.GeoDataFrame(features, crs=crs)
gdf.to_file("vehicle_detection.geojson", driver="GeoJSON")
生成 GeoJSON 后,可以直接拖入 QGIS 检查位置是否与原始影像对齐。如果检测框整体偏移,优先检查切片偏移量、坐标转换顺序、行列坐标是否写反。
步骤8:在QGIS中检查和修正结果
把 vehicle_detection.geojson 加载到 QGIS 后,建议进行以下检查:
- 检测框是否落在车辆上,而不是整体偏移半个切片或一个像元。
- 同一辆车是否存在多个重叠框。
- 误检是否集中在屋顶、集装箱、路面标线、树影等区域。
- 漏检是否集中在阴影区、车身颜色较暗区域、切片边缘区域。
- 坐标系是否与底图或原始影像一致。
如果要做车辆数量统计,可以把检测框转为中心点,然后按停车场范围、道路缓冲区或行政区面进行空间汇总。对于需要人工复核的项目,也可以在 QGIS 中按置信度设置样式,例如高置信度绿色、低置信度红色。
常见坑:YOLO卫星图车辆检测容易出错的地方
坑1:直接用通用车辆模型识别卫星图
很多通用车辆模型来自街景、行车记录仪或普通照片,这类模型看到的是侧视或斜视车辆。卫星图是俯视角,车辆外观差异很大。直接使用通用模型,通常会出现大量漏检。
解决方法是使用遥感车辆数据集进行训练,或者至少用自己的卫星图标注样本进行微调。
坑2:影像分辨率不够还强行识别车辆
如果车辆在影像中只有几个像素,YOLO 很难判断它到底是车辆、噪声还是路面标记。此时盲目增加训练轮数意义不大。
建议先在 QGIS 中量一下车辆像素大小。如果普通小汽车宽度不足 5 到 8 个像素,就要谨慎评估结果可靠性。
坑3:切片没有重叠导致边缘漏检
车辆刚好被切片边界切成两半时,模型可能识别不到,或者输出不完整检测框。使用 10% 到 25% 重叠切片可以明显减少这种问题,但也会带来重复检测,因此后处理要做去重。
坑4:只看训练指标,不看GIS叠加结果
模型指标高不代表 GIS 结果可用。车辆检测框如果坐标转换错了,mAP 再高也无法用于空间分析。每次推理后都应该把结果加载到 QGIS,与原始影像叠加检查。
坑5:把阴影、屋顶设备、集装箱误识别为车辆
卫星图中很多物体在俯视角下与车辆相似。误检通常与训练样本不均衡有关。可以增加负样本区域,例如屋顶、集装箱堆场、停车线密集区,并在验证集中专门检查这些场景。
方法比较:YOLO、传统遥感方法和深度学习分割怎么选
| 方法 | 适用场景 | 优点 | 局限 |
|---|---|---|---|
| YOLO目标检测 | 车辆、船只、光伏板等边界相对清晰的小目标 | 速度快,输出框简单,适合计数和点位提取 | 对小目标、遮挡和影像分辨率敏感 |
| 传统影像分类 | 地物类型分类,如水体、植被、建设用地 | 流程简单,可解释性较强 | 不适合精确识别单辆车辆 |
| 语义分割 | 道路、水体、建筑轮廓等连续区域 | 可得到像素级区域 | 车辆太小且实例密集时,单车分离不方便 |
| 实例分割 | 需要车辆精细轮廓或更高质量边界 | 比矩形框更精细 | 标注成本和计算成本更高 |
如果你的目标是“数车”和“定位车辆大致位置”,YOLO目标检测 通常是性价比较高的方案。如果需要精确车辆轮廓,才需要考虑实例分割。但对多数 GIS 应用来说,检测框或中心点已经足够用于空间统计。
检查清单:做卫星图识别车辆前后都要核对什么
数据准备检查
- 影像分辨率是否足以看清车辆。
- 影像是否有正确坐标系和地理参考。
- 训练区、验证区、测试区是否分开。
- 样本是否覆盖停车场、道路、厂区、阴影、树木遮挡等场景。
- 车辆类别规则是否明确,例如只识别 vehicle,还是区分 car、truck、bus。
模型训练检查
- 是否使用遥感场景相关的样本进行训练或微调。
- 输入尺寸是否适合小目标车辆。
- 是否查看过验证集预测图片,而不仅是看指标。
- 是否分别分析误检和漏检样本。
- 是否保存了训练配置、数据版本和模型权重。
GIS成果检查
- 检测框是否与原始影像准确叠加。
- 坐标系是否正确写入 GeoJSON、Shapefile 或 GeoPackage。
- 重叠切片带来的重复车辆是否已经去重。
- 低置信度结果是否单独标记,方便人工复核。
- 统计结果是否按业务区域重新汇总,而不是只统计原始检测框数量。
FAQ:YOLO目标检测和卫星图识别车辆常见问题
Q1:YOLO目标检测怎么用在GIS项目里?
核心流程是:先把带地理参考的遥感影像切片,再用 YOLO 对切片进行目标检测,最后把检测框从切片像素坐标转换回地图坐标。GIS 项目不能只停留在模型输出图片,还要生成 GeoJSON、Shapefile、GeoPackage 或 PostGIS 表,才能用于空间查询和统计。
Q2:卫星图识别车辆需要多高分辨率?
通常建议使用亚米级影像。分辨率越高,车辆在图像中占的像素越多,识别越稳定。如果车辆只占几个像素,模型很难可靠区分车辆和背景噪声。实际项目开始前,应先在 QGIS 中放大检查车辆是否清晰可辨。
Q3:可以不训练,直接用现成YOLO模型识别车辆吗?
可以尝试,但不建议直接用于正式成果。很多现成模型训练于普通照片,不适合俯视卫星图。更可靠的做法是使用遥感车辆样本进行微调,并用本地影像做验证。
Q4:YOLO识别结果为什么和QGIS底图对不上?
常见原因包括切片偏移量记录错误、行列坐标顺序写反、影像 transform 使用错误、输出文件缺少坐标系、切片时发生缩放但后处理没有同步处理。排查时应先用一个已知切片做单独测试,确认检测框能准确回到原图位置。
Q5:卫星图车辆检测结果可以直接用来统计车流量吗?
单景卫星影像只能反映拍摄时刻的车辆分布,不能直接代表连续车流量。如果要分析车流变化,需要多时相影像,或结合道路卡口、轨迹数据、视频数据等。YOLO目标检测 更适合做某一时刻的车辆计数、停车占用或空间分布分析。
Q6:检测框和车辆中心点哪个更适合GIS分析?
如果要做人工复核或空间叠加,检测框更直观;如果要做数量统计、热力图、网格汇总或空间连接,中心点更方便。实际项目中可以同时保留检测框面和中心点点图层。
结论:先把遥感流程做对,再谈YOLO模型效果
YOLO目标检测 可以很好地用于卫星图识别车辆,但它不是一个单独的模型命令,而是一套完整的 GIS 与深度学习结合流程。正确做法是:准备高分辨率影像,按重叠窗口切片,标注遥感车辆样本,训练或微调模型,对整幅影像推理,再把检测框转换为带坐标的 GIS 矢量成果。
如果你是第一次做这个任务,建议先选择一个小范围停车场或园区影像,跑通“切片—标注—训练—推理—GeoJSON回写—QGIS检查”的闭环。只要这个闭环稳定,后续扩大到城市道路、工业园区或多时相车辆监测,就会清楚很多。