简介这份PPT是商汤科技SenseRemote人工智能遥感解译技术介绍资料共24页面向遥感、GIS及计算机视觉方向的学习者与技术从业者帮助理解深度学习在遥感图像分析中的落地路径。内容围绕海量数据、超级计算与学习算法三大要素展开讲解商汤自建Parrots深度学习平台的设计动因对比开源平台在分布式训练、超深网络与算法迭代上的局限并说明遥感多波段、高光谱、大幅面数据为何难以直接套用VGG、ResNet等常规网络。资源还涵盖数据普适模型、道路河流与云雪舰船等场景专用模型、模型压缩与融合传统解译思路的改进方法并给出云雪水体提取、路网提取、飞机关键点检测、舰船检测、变化检测、土地分类与建筑物提取等实测案例及处理耗时。压缩包内为1个pptx文件约21.19MB已有472人学习适合用于技术调研、方案汇报与遥感智能化应用选型参考。1. 遥感解译从人工判读到模型推理差的是什么一景两米分辨率的多光谱影像人工判读加手工勾绘耕地、建筑、水体图斑按有经验的技术员估算完整出图要两到三天。换成训练好的语义分割模型做初步提取同样的影像从读入到输出掩膜往往只要几十分钟剩下的时间用来做后处理和人工修正。人工智能遥感解译要压缩的就是这段人力密集的工时把重复判读交给算力把判断力留给复核环节。这个主题落到工程上要回答四件事遥感解译分哪几类任务、每类配什么模型影像和标签怎么组织才能喂进神经网络训练一个分割模型的关键参数怎么设推理精度掉下来时先查哪里。只会在PPT上画流程框图是不够的真正卡住项目的是数据切片、标签对齐和显存这几个环节。适合的读者是已经会一点Python和PyTorch、准备把深度学习用到遥感业务里的工程师也适合需要判断方案可行性的技术负责人。后面每一节都会给出能直接跑的命令和参数不停留在名词解释。2. 遥感解译的四类任务与人工智能模型选型2.1 分类、检测、语义分割、变化检测的任务边界遥感解译的需求落到代码层面基本拆成四类任务。图像级分类给整景影像打标签例如判断某区域是建成区还是农田目标检测在影像上框出飞机、油罐、车辆的位置语义分割逐像素标注类别输出建筑、水体、植被的掩膜变化检测比较两个时相的影像输出发生变化的区域。选哪一类不看技术新不新看业务要什么输出。需要把提取结果矢量化成图斑就选语义分割需要计数和定位就选目标检测。项目里常见的一个误判是上来就做分割标注成本被低估其实很多场景先用检测做粗筛再用分割做精修更划算。四类任务的对照关系如下表。任务类型输出形式标签成本典型场景图像分类整景标签低地块类型筛查目标检测边界框中飞机、油罐、车辆计数语义分割像素掩膜高建筑物提取、水体范围变化检测变化掩膜高违建监测、地表覆盖变化变化检测和前三种的区别在于输入是双时相网络结构上要么做双分支编码器后融合要么直接拼接通道后面会提到参数怎么配。2.2 骨干网络与解码头怎么组合语义分割模型分两部分看骨干网络提特征解码头把特征还原到原图分辨率。骨干常见的有ResNet、EfficientNet和Swin Transformer解码头常见的有U-Net的跳跃连接、DeepLab系列的ASPP、SegFormer的轻量MLP解码。遥感影像和自然图像有两个明显差异。一是波段数不止三通道常带近红外甚至红边波段二是目标尺度差异大同一景里既有几十平的独立建筑也有连片的耕地。前者要求骨干的第一层卷积把in_channels改成实际波段数后者要求解码阶段保留足够的高分辨率特征U-Net这类带跳跃连接的结构在这点上比纯Transformer解码更稳。我一般会这样起步数据量在几千张切片以内用ResNet34或EfficientNet-B0做骨干的U-Net训练快、显存占用低数据量上万且算力充足再换Swin-Base加UperNet或者直接用SegFormer的轻量配置。这条路线也是在人工智能入门阶段最容易复现的路径社区实现多出问题好查。2.3 显存、参数量与推理速度的取舍选型时要同时看三个数字不是越大的模型越好下面是常见配置在512×512输入下的参考区间。模型配置参数量级单卡显存batch4适用阶段U-Net ResNet34约24M6~8GB快速验证、中小数据集U-Net EfficientNet-B4约19M8~10GB精度优先、算力中等DeepLabV3 ResNet50约39M10~12GB多尺度目标并存SegFormer-B2约27M8~10GB大场景、长尾类别Swin-Base UperNet约60M14GB以上数据量充足时刷精度显存不够时优先降batch_size并配合梯度累积而不是直接缩小输入尺寸遥感小目标对分辨率非常敏感切到256×256之后很多独立建筑会退化成几个像素召回率明显下滑。推理速度方面同样的骨干换成TensorRT或ONNX Runtime通常能带来一到两倍加速这部分放到最后一章讲。3. 遥感影像切片与标签对齐的工程化处理3.1 用rasterio检查影像元数据动模型之前先确认数据本身没问题。波段顺序、坐标系、无效值这些信息决定了后面切片和标签对齐怎么做。import rasterio # 打开一景多波段影像先确认波段数、坐标系和数据类型 with rasterio.open(GF2_20230512.tif) as src: print(波段数:, src.count) print(坐标系:, src.crs) print(尺寸:, src.width, src.height) print(数据类型:, src.dtypes) print(仿射变换:, src.transform) # 检查无效值填充方式很多产品用0或-9999 print(Nodata:, src.nodata)代码里src.count直接决定模型输入通道数crs和transform决定影像和标签能不能对齐nodata决定预处理时哪些像素要屏蔽。如果影像本身带云或者条带缺失这些区域在标签里应该单独标一类或者直接剔除不然模型会把噪声当成地物学。提示同一批数据里波段顺序可能不一致有的产品是BGR有的是RGB加近红外。切片之前统一波段顺序否则模型学到的是错乱的通道组合。3.2 滑动窗口切片的实现与重叠策略整景影像动辄几千乘几千像素不可能整幅送进网络标准做法是滑动窗口切片。下面是一个不依赖额外库的实现。import numpy as np import rasterio def slide_window(img, size512, stride384): 按滑动窗口切patchstridesize时相邻patch有重叠缓解边缘拼接痕迹 h, w img.shape[:2] coords [] for y in range(0, h - size 1, stride): for x in range(0, w - size 1, stride): coords.append((y, x)) # 补上右边界和下边界避免边缘像素被丢弃 for y in range(0, h - size 1, stride): if (w - size) % stride ! 0: coords.append((y, w - size)) return coords with rasterio.open(GF2_20230512.tif) as src: img src.read() # 形状 (bands, H, W) img np.transpose(img, (1, 2, 0)) # 转成 (H, W, bands) coords slide_window(img, size512, stride384) print(切片数量:, len(coords))参数上size和骨干网络的下采样倍数对齐用U-Net的话512或1024都可以stride小于size时产生重叠区推理阶段可以在重叠区做加权平均减少拼接处的接缝。不设重叠省显存但拼接痕迹在目视检查时会很明显。3.3 标签栅格对齐与类别编码标签通常来自人工矢量化后转成的单波段栅格类别值可能是离散的整数也可能带255这种无效值。训练之前要把无效值映射到ignore_index类别值重排成从0开始的连续整数不然损失函数计算会出错。import numpy as np # 原始类别值到训练标签的映射255和0视为忽略 value_map {1: 0, 2: 1, 3: 2, 4: 3, 5: 4, 255: 255} IGNORE_INDEX 255 def encode_label(mask): out np.full(mask.shape, IGNORE_INDEX, dtypenp.uint8) for raw, new in value_map.items(): out[mask raw] new return out这段代码的作用是把业务里的类别编码转换成损失函数能接受的连续标签IGNORE_INDEX 255会在交叉熵里被跳过不参与梯度计算。标签和影像必须用同一个transform裁切否则切片位置对不上模型会学出完全随机的对应关系。数据量不足时旋转90度、水平翻转、色彩抖动是性价比最高的增强组合几何变换记得同步作用到标签上。4. 训练一个遥感语义分割模型的关键参数4.1 PyTorch训练脚本骨架用segmentation_models_pytorch能把模型搭建压缩到几行注意力集中在数据管道和损失函数上。import torch import segmentation_models_pytorch as smp from torch.utils.data import DataLoader # 四通道输入RGB 近红外六类输出 model smp.Unet( encoder_nameresnet34, encoder_weightsimagenet, # 自然图像预训练权重小数据集上收敛更快 in_channels4, classes6, ).cuda() # Dice对类别不平衡更鲁棒交叉熵负责像素级监督 dice smp.losses.DiceLoss(modemulticlass, ignore_index255) ce torch.nn.CrossEntropyLoss(ignore_index255) criterion lambda pred, target: dice(pred, target) ce(pred, target) optimizer torch.optim.AdamW(model.parameters(), lr3e-4, weight_decay1e-4) scheduler torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max60) loader DataLoader(train_dataset, batch_size4, shuffleTrue, num_workers4, pin_memoryTrue)encoder_weightsimagenet这个参数在遥感项目里常被质疑自然图像和遥感图像分布差异大但实测在小数据集上仍然比随机初始化收敛快很多因为底层边缘和纹理特征是通用的。in_channels4时要确认预训练权重能不能扩展通道smp会自己处理如果手写模型需要复制第一层权重再平均到新增通道。4.2 学习率、批大小与损失函数的设置超参没有万能值但遥感分割有一套相对稳的起点下表是常用的区间。参数推荐区间调整方向初始学习率1e-4 ~ 3e-4震荡就降收敛慢就升batch size4 ~ 16受显存限制配合梯度累积权重衰减1e-4过拟合时适当加大训练轮数40 ~ 80看验证集IoU何时走平损失权重Dice 1.0 CE 1.0小类别召回低就加大Dice训练循环里有两个容易忽略的点。一是每轮之后打印各类别的IoU而不只是总loss总loss下降但小类别IoU不动的现象很常见这时候要做的是重采样或者调损失权重不是继续加轮数。二是保存验证集IoU最高的权重而不是最后一个epoch的权重遥感数据量有限过拟合来得比自然图像快。for epoch in range(60): model.train() for img, mask in loader: img, mask img.cuda(), mask.cuda() optimizer.zero_grad() pred model(img) loss criterion(pred, mask) loss.backward() optimizer.step() scheduler.step() # validate()内部计算逐类IoU并返回最优权重标记 miou validate(model, val_loader, num_classes6, ignore_index255) print(fepoch {epoch} mIoU {miou:.4f})4.3 用IoU和F1验证精度遥感项目汇报时最常被问的两个指标是IoU和F1前者衡量区域重叠后者在小目标上更敏感。用torchmetrics可以省掉手写混淆矩阵。from torchmetrics.classification import MulticlassJaccardIndex, MulticlassF1Score iou MulticlassJaccardIndex(num_classes6, ignore_index255).cuda() f1 MulticlassF1Score(num_classes6, ignore_index255).cuda() torch.no_grad() def validate(model, loader, num_classes6, ignore_index255): model.eval() for img, mask in loader: img, mask img.cuda(), mask.cuda() pred model(img).argmax(dim1) iou.update(pred, mask) f1.update(pred, mask) return iou.compute().item()评估时一定要过滤ignore_index对应的像素否则无效区域会拉低整体指标掩盖真实问题。分类别看结果如果水体IoU到0.9而建筑只有0.5问题多半出在建筑样本少或者边界标注不一致先查数据再调模型。5. 推理阶段精度掉点的排查与提升技巧训练集指标好看、上线效果差是遥感解译里最常见的落差。按顺序排查通常能定位到原因。第一站查数据一致性。推理影像的波段顺序、辐射定标、分辨率如果和训练集不一致模型输入分布就变了。做法是在推理前对影像做一次和训练时相同的归一化把统计量落到同一区间。下面这段代码把切片推理和重叠区加权拼接串起来。import numpy as np import torch torch.no_grad() def infer_full_image(model, img, size512, stride384, num_classes6): 整景推理重叠区按权重累加后再取argmax消除拼接痕迹 h, w, c img.shape prob np.zeros((num_classes, h, w), dtypenp.float32) weight np.zeros((h, w), dtypenp.float32) # 用汉宁窗做权重中心权重高、边缘权重低 win np.outer(np.hanning(size), np.hanning(size)).astype(np.float32) for y in range(0, h - size 1, stride): for x in range(0, w - size 1, stride): patch img[y:ysize, x:xsize] tensor torch.from_numpy(patch.transpose(2, 0, 1)).unsqueeze(0).cuda() out torch.softmax(model(tensor), dim1)[0].cpu().numpy() prob[:, y:ysize, x:xsize] out * win weight[y:ysize, x:xsize] win weight[weight 0] 1.0 return (prob / weight).argmax(axis0)第二站查后处理。原始掩膜往往有碎斑和毛刺直接矢量化会生成大量小多边形。常见的组合是先做形态学开运算去掉小连通域再设定最小图斑面积阈值工程上一般把小于6到10个像素的图斑过滤掉。这一步会牺牲一点点召回但输出的矢量图层干净很多。第三站看提升空间。如果排查完前三项指标仍不达标可以按成本从低到高尝试对预测置信度低的区域做一次人工标注用这批难例做微调把推理分辨率提高到训练分辨率的1.5到2倍做测试时增强换成带近红外和红边波段的输入组合植被和建筑在这几个波段上的可分性通常更好。硬件侧如果要求实时把模型导出成ONNX后用ONNX Runtime推理或者用TensorRT做FP16量化在精度损失可控的前提下把单景推理时间压下来。本文还有配套的精品资源点击获取