ARTICLE DETAIL

资讯详情

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

高分辨率遥感图像建筑物识别:语义分割到滑窗推理与GIS落图

高分辨率遥感图像建筑物识别:语义分割到滑窗推理与GIS落图 简介这是一份面向遥感图像处理、计算机视觉方向研究者与高年级学生的深度学习参考文献聚焦高分辨率遥感图像中的建筑物识别难题尤其针对现有方法识别结果过度分割、小目标识别效果不佳的痛点适合作为语义分割入门与进阶的参考资料。资源为单篇PDF论文共1个文件压缩包约2.62MB内容为《计算机工程与应用》期刊原文包含摘要、引言、方法设计、实验与结论等完整章节便于系统研读与引用。论文提出基于SegNet改进的AA-SegNet网络模型引入增强型空间金字塔池化模块与空间注意力融合模块以强化特征传播、抑制低级特征噪声并提升小目标学习能力基于高分二号遥感影像构建数据集开展实验总体识别准确率达96.61%在识别率、F1分数与训练时间上均优于SegNet、U-Net、DeepLab-V3。目前已有416人学习适合希望借鉴网络改进思路、复现对比实验或撰写相关论文的读者参考。1. 高分辨率遥感图像里的建筑物识别拼的不是模型大小拿到一景 0.3 米分辨率的航拍正射影像先别急着套 U-Net。真正卡住进度的往往是屋顶反光、树冠遮挡、阴影压边以及相邻楼栋之间那条只有两三个像素宽的缝。高分辨率遥感图像的建筑物识别本质是逐像素二分类每个像素回答“是否落在建筑物轮廓内”。它服务违建排查、国土变更调查、灾后损失评估、三维建模底面提取。适合已经跑通过语义分割 demo、想把这套深度学习流程搬到遥感数据上的工程师也适合手上有带标注正射影像、正在选主干网络的技术负责人。难点不在网络有多深而在数据管道、标签质量、推理拼接、边界规整这四件事。2. 建筑物识别任务的数据底座从高分辨率遥感影像到可训练标签2.1 分辨率、波段与瓦片尺寸的取舍高分辨率遥感图像通常指地面采样距离在 0.1 到 1 米之间的影像来源包括航拍正射、亚米级商业卫星和无人机拼接图。分辨率越高建筑物识别越像纹理识别屋顶的瓦片排列、通风口、水箱、空调外机都会变成干扰项。把 0.3 米影像降采样到 0.5 米再训练经常比硬上原始分辨率更容易收敛——边界模糊一点但类内差异也小了很多模型的泛化误差界反而好看。波段方面RGB 三通道是底线近红外对植被与建筑的可分性帮助很大能拿到四通道就别只用三通道。近红外在这里的用法是先算植被指数把树冠遮挡区域标成“不确定”避免模型把树冠下的建筑学成“不是建筑”这是新手最容易忽略的一步。瓦片尺寸的常见做法是 512×512 配 64 或 128 像素重叠。1024×1024 显存吃紧但上下文更完整256×256 训练快却容易把大楼切碎。经验值单栋建筑平均占地小于 256 像素时用 512 瓦片大厂房、连片城中村这种长条目标用 512 加 50% 重叠。场景建议 GSD瓦片重叠说明城市密集住宅0.30.5 m512128楼间距小重叠一次不够就加到两次工业园区大厂房0.5 m512256长条目标跨瓦片概率高城郊农村自建房0.81.0 m25664目标小瓦片太大反而稀释正样本2.2 从 Shapefile 或 GeoJSON 到二值掩膜标签转换最容易写出静默 bug。常见做法是先按瓦片范围裁矢量再用 rasterio 的 rasterize 烧录成与影像严格对齐的单通道 uint8 掩膜。关键点是 all_touched 的取值与像素中心点判定口径不一致会让边界整体偏移半像素训练时表现为预测轮廓系统性外扩。import rasterio from rasterio.features import rasterize import geopandas as gpd from shapely.geometry import box def vector_to_mask(tif_path, shp_path, out_path): with rasterio.open(tif_path) as src: # 掩膜必须复用影像本身的仿射变换和尺寸自己算迟早错位 transform, width, height, crs src.transform, src.width, src.height, src.crs bounds src.bounds gdf gpd.read_file(shp_path).to_crs(crs) # CRS 必须与影像统一 gdf gdf[gdf.intersects(box(*bounds))] # 只烧录与瓦片相交的几何 shapes ((geom, 1) for geom in gdf.geometry if geom.is_valid) mask rasterize( shapesshapes, out_shape(height, width), transformtransform, fill0, dtypeuint8, all_touchedFalse, # 仅像素中心落多边形内才置 1避免边界胖一圈 ) with rasterio.open(out_path, w, driverGTiff, heightheight, widthwidth, count1, dtypeuint8, crscrs, transformtransform, compresslzw) as dst: dst.write(mask, 1) vector_to_mask(tile_001.tif, buildings.shp, tile_001_mask.tif)逻辑说明rasterize 把矢量几何按地理坐标打点到栅格上fill0 保证背景为 0、建筑为 1。all_touchedFalse 是标准口径改成 True 会让每栋楼胖一圈边界 IoU 掉的往往就是这一圈。参数说明out_shape 取自影像而不是自己推算否则瓦片裁切范围一改就全错to_crs 漏掉的话掩膜会飞到另一个半球compresslzw 对二值图压缩比很高几万张瓦片的磁盘占用差别可观。2.3 正负样本分布与瓦片级过滤建筑物像素在整景里通常只占 5% 到 20%直接训练会让模型偏向全预测背景recall 虚高、precision 崩掉。常见做法分三层瓦片级过滤把建筑占比低于 5% 的瓦片丢弃或降采样损失函数层面的正样本加权放在第 3 章讲在线难例挖掘把每个 epoch 里 loss 最高的若干瓦片固定重采样。瓦片级过滤最省事代价是丢失纯背景样本模型在空旷区域的误检会略升。实践中保留 10% 左右的低占比瓦片能让模型记住“空地长什么样”误检率下降比多训十个 epoch 有效。提示转换完成后随机抽 20 张瓦片做目视叠加掩膜半透明压在影像上边界偏移一眼能看出来比盯着 loss 曲线猜快得多。3. 面向建筑物识别的主干网络与损失函数选型3.1 编码器CNN 系与 Swin 系怎么选深度学习模型在遥感分割上的差异往往没有数据质量影响大但主干选型仍有明确取舍。CNN 主干胜在成熟、显存友好、迁移权重好找窗口注意力类结构在密集城区楼挨楼、边界共享上更稳代价是显存和预处理复杂度上一个台阶。主干感受野参数量量级边界表现适用场景ResNet-34 / 50 UNet局部堆叠2030M中数据少先跑通基线EfficientNet-B4 UNet局部堆叠20M 左右中上算力受限要推理速度Swin-T / SegFormer-B2全局 局部3050M上瓦片数够边界要求高数据少于两千张瓦片时先用 ResNet 系把整套流程跑通再换主干做消融否则你分不清涨点是来自主干还是来自换了损失函数。3.2 解码器与跳跃连接的处理UNet 的解码器靠跳跃连接把浅层高分辨率特征接回来这对建筑物边界至关重要。常见坑是浅层特征通道数太大直接 concat 会让显存爆掉所以先做一次 1×1 卷积把通道压到 64 以内再接。另一个选择是 FPN 式的多尺度融合把 stride 8、16、32 三层特征都上采样到同一尺度再相加好处是对大小建筑都友好。密集城区里小目标多FPN 的召回通常比纯 UNet 高代价是参数量和推理耗时小幅上升。工业界还有一条路线是用 Halcon 的深度学习工具做分割标注和训练流程封装得比较完整适合产线级部署但自定义损失和结构改动的空间有限做研究调参时不如 PyTorch 那条路自由。3.3 损失函数BCE 与 Dice 的组合写法单个 BCE 在正样本稀薄时梯度会被背景淹没单独用 Dice 又会在训练早期不稳定。组合起来是最稳的起点BCE 负责像素级判别Dice 负责整体重叠度正样本权重压一压背景。import torch import torch.nn as nn class BCEDiceLoss(nn.Module): def __init__(self, pos_weight2.0, bce_w1.0, dice_w1.0): super().__init__() # pos_weight 1 用来提升正样本像素的梯度占比 self.register_buffer(pos_w, torch.tensor([pos_weight])) self.bce nn.BCEWithLogitsLoss(pos_weightself.pos_w) self.bce_w, self.dice_w bce_w, dice_w def forward(self, logits, target): bce self.bce(logits, target) prob torch.sigmoid(logits) # 逐样本算 Dice 再平均避免大图把小图的贡献稀释掉 num 2 * (prob * target).sum(dim(2, 3)) 1.0 den prob.sum(dim(2, 3)) target.sum(dim(2, 3)) 1.0 dice 1 - (num / den).mean() return self.bce_w * bce self.dice_w * dice逻辑说明logits 直接喂给 BCEWithLogitsLoss内部已经带 sigmoid不用自己再激活一次重复激活会让数值剧烈抖动。Dice 的分子分母都加 1.0 是平滑项防止某些瓦片整张没有建筑时出现除零。参数说明pos_weight 从 2 开始试建筑占比低于 5% 时提到 3 到 5bce_w 与 dice_w 保持 1:1 起步如果验证集上边界糊把 dice_w 提到 1.5 更看重重叠度代价是收敛略慢。4. 训练、滑窗推理与后处理把建筑物识别的 IoU 提上去4.1 深度学习环境配置与训练超参环境这一步别照抄别人的版本按本机显卡驱动对应挑构建否则大概率卡在 CUDA 不匹配上。# 1) 建一个独立环境Python 用 3.10 这一档主流分割库都跟得上 conda create -n bldg python3.10 -y conda activate bldg # 2) 框架按本机 CUDA 驱动挑对应构建别直接复制别人的命令 pip install torch torchvision # 3) 遥感 IO 三件套rasterio 读 GeoTIFFgeopandas 读矢量shapely 做几何运算 pip install rasterio geopandas shapely # 4) 训练辅助分割模型库、数据增强、进度条 pip install segmentation-models-pytorch albumentations tqdm参数说明torch 的 wheel 索引要跟驱动匹配装完先跑一句 torch.cuda.is_available() 自检返回 False 就别往下走了白等一晚上。rasterio 依赖 GDAL用 conda 装通常比 pip 稳。训练超参的常用起点参数起点值调整方向初始学习率1e-4主干用预训练权重时降到 3e-5批大小8512 瓦片显存不够就降到 4同步调小学习率epoch60100看验证集 IoU 连续 10 轮不涨就停优化器AdamW数据量大可换 SGD cosine权重衰减1e-4过拟合时提到 5e-4学习率调度cosine配合 warmup 3 轮更稳epoch 不是越多越好。遥感数据标注噪声大训到 150 轮以后模型往往开始拟合标注错误验证集 IoU 掉、训练 loss 还在降这时候早停比继续调参有用。4.2 滑窗推理与重叠拼接整景影像动辄上万像素没法一次性塞进显存。滑窗推理加重叠加权是标准做法预测值在重叠区按到瓦片中心的距离做加权边缘权重低中心权重高接缝就不明显。import numpy as np import torch def sliding_infer(model, image, tile512, stride384, devicecuda): # image: (C, H, W) float32已归一化 model.eval() c, h, w image.shape prob np.zeros((h, w), dtypenp.float32) weight np.zeros((h, w), dtypenp.float32) # 汉宁窗做重叠加权中心权重高、边缘权重低拼缝自然消失 win np.hanning(tile) win2d np.outer(win, win).astype(np.float32) 1e-6 for y in range(0, h, stride): for x in range(0, w, stride): y2, x2 min(y tile, h), min(x tile, w) patch image[:, y:y2, x:x2] ph, pw patch.shape[1], patch.shape[2] pad np.zeros((c, tile, tile), dtypenp.float32) pad[:, :ph, :pw] patch # 边缘瓦片补零到整块 with torch.no_grad(): logits model(torch.from_numpy(pad[None]).to(device)) p torch.sigmoid(logits)[0, 0].cpu().numpy() prob[y:y2, x:x2] p[:ph, :pw] * win2d[:ph, :pw] weight[y:y2, x:x2] win2d[:ph, :pw] return prob / np.maximum(weight, 1e-6)逻辑说明stride 小于 tile 就产生重叠重叠区被多次预测按权重累加再归一化等于对多个预测做了空间加权平均。补零到整块是为了让模型输入尺寸恒定避免 BatchNorm 在奇异尺寸下统计异常。参数说明stride 取 tile 的 0.5 到 0.750.5 接缝最干净但耗时翻倍win 用 np.hanning别用矩形窗矩形窗在瓦片边界权重突变接缝会以竖条纹形式出现在成果图上。4.3 后处理连通域过滤与轮廓规整概率图阈值二值化之后还有两件事。一是连通域过滤去掉面积小于 30 像素的碎斑这些大多是屋顶设备和阴影二是轮廓规整把锯齿状边界做一次形态学闭运算再接 Douglas-Peucker 简化导出到 GIS 时相邻楼的粘连会明显减少。阈值不要固定 0.5。用验证集扫一遍 0.35 到 0.65画 precision-recall 曲线挑拐点密集城区通常落在 0.45 附近稀疏区域可以到 0.55。4.4 指标与误差诊断评估用 IoU、F1、precision、recall 四个就够。诊断时把错误分成三类看边界带内 3 像素的错分通常是分辨率问题降采样训练或者加边界损失能缓解整栋漏检多半是标注遗漏或遮挡要回查标签大面积误检往往来自阴影和地砖纹理加负样本或者引入近红外波段最有效。5. 建筑物识别成果的工程化从概率图到可用 GIS 图层5.1 跨区域泛化的低成本做法同一模型换到另一个城市IoU 掉 10 个点很常见主要是屋顶材质和建筑密度的域差异。低成本做法有两个训练时做强度类增强随机亮度、对比度、伽马模拟不同传感器的成像差异以及推理前做一次直方图匹配把新影像的亮度和色调整到与训练集接近这一步不改模型、不加标注往往能捡回三五个点。5.2 导出 GeoJSON 与大图接缝处理二值掩膜转矢量用 rasterio.features.shapes转出来是多边形集合属性里带上置信度均值方便下游按阈值筛。导出项建议做法注意坐标系与原始影像 CRS 一致别在中途转经纬度会引入二次误差简化容差12 像素对应地面距离容差过大小楼直接消失属性字段area、mean_prob下游可据此过滤碎斑拓扑修复用 make_valid 修自相交自相交多边形在部分 GIS 里打不开整景拼接的接缝除了靠汉宁窗加权还可以在大图推理时把瓦片边界向两侧各扩 64 像素的缓冲区预测后再裁掉缓冲区接缝处的上下文更完整长条形厂房的断裂会少很多。真正上线前把模型输出按行政区分块统计建筑面积和人手核对过的参考值比一比量级对不上就说明阈值或者后处理某一步偏了这比单看 IoU 更能暴露系统性问题。本文还有配套的精品资源点击获取
返回列表