
简介基于深度学习的遥感影像地块分割项目资料包面向遥感与人工智能交叉领域的初学者及项目开发者聚焦利用Python和卷积神经网络实现地物自动识别与地块分割。包内含25个文件包括jpg与png原图及分割结果示例、md说明文档、Python推理脚本、yaml部署配置、模型权重与参数文件整体约94.95MB目录结构清晰。项目覆盖数据预处理、模型构建、训练优化、验证测试与后处理并提供PaddleSeg推理部署方案可快速复现实验并理解FCN、U-Net在像素级分割中的应用。已有177人学习适合课程设计、毕业设计或遥感解译项目参考。通过阅读说明与运行示例可掌握从遥感影像到地块分割结果的完整流程。1. 拿到 zip 之后遥感影像地块分割到底要训什么多数人下载基于深度学习的遥感影像地块分割.zip这类压缩包第一反应是解压、找 README、跑 predict然后被环境依赖和数据集路径卡住。这里先说结论这个 zip 装的是一个完整的语义分割工程而不是一个开箱即用的软件。遥感影像地块分割的本质是对影像逐像素分类把农田、裸地、水体、建筑区等地类边界画出来输出一张与输入同尺寸的掩膜图。它和你平时做的猫狗分类、目标检测最大的不同在于输入是十几 GB 的栅格影像标注是矢量面损失函数在像素级别计算而评价指标要用 IoU 或 mIoU 而非准确率。适合读这篇文章的人是已经跑过分类网络、想切入遥感领域或者正好拿到这个 zip 想把它改造到自己的数据上。以下内容按工程结构 — 数据制作 — 训练调参 — 推理后处理的顺序讲全部围绕这个 zip 能落地的主线展开不绕弯子。2. 解开 zip工程结构、代码骨架与模型选型2.1 压缩包里通常有什么先认清这些目录不是摆设拿到 zip 第一件事不是 pip install而是先看清楚目录里到底放了什么。常见的遥感分割工程包通常包含以下部分. ├── data/ # 影像与标注可能只有示例或空目录 ├── models/ # 网络定义unet.py / deeplabv3plus.py 等 ├── configs/ # yaml 或 py 配置数据路径、超参数、类别数 ├── utils/ # 栅格读写、切块、图像增强、指标计算 ├── train.py # 训练入口 ├── predict.py # 推理入口 └── requirements.txt解压后建议先执行find . -name *.py | head -50和du -sh data确认代码量和数据量。判断一个工程是否值得继续投入关键有四点第一data/里有没有真实影像样本还是只有 README 占位第二train.py是否接受命令行参数还是把路径写死在文件里第三模型文件是单文件还是依赖某个外部库第四requirements.txt里的 PyTorch 版本是否和你本机 CUDA 匹配。我见过不少 zip 解压出来训练脚本是完整的但数据集一张图都没有这种情况下后续工作重心应该放在数据制作而非读代码。2.2 模型选型U-Net 打底DeepLabV3 补边界遥感地块分割的模型选型不必追新。LabelMe 或 GID 这类数据集上跑得稳的基本是 U-Net 和 DeepLabV3 两个系列。U-Net 的编码器-解码器结构和跳跃连接在中小尺寸地块、边界相对规整的场景下表现稳定训练收敛快显存占用低。DeepLabV3 用空洞卷积扩大感受野配合 ASPP 模块捕捉多尺度上下文对地块大小差异大的影像大块农田加小块房屋更友好。ResNet 主干是标配输入分辨率通常取 512×512 或 640×640。# models/deeplabv3plus.py 中的关键结构示意 import torch.nn as nn class ASPP(nn.Module): def __init__(self, in_channels, out_channels256, rates(6, 12, 18)): super().__init__() self.convs nn.ModuleList() # 1x1 卷积分支捕捉全局上下文 self.convs.append(nn.Conv2d(in_channels, out_channels, 1)) # 三个空洞卷积分支不同扩张率覆盖不同感受野 for r in rates: self.convs.append( nn.Conv2d(in_channels, out_channels, 3, paddingr, dilationr, biasFalse))注意这里dilation和padding必须相等否则特征图尺寸对不上。很多训练报错size mismatch就出在这一行。2.3 选型对照表按数据情况决定用哪个场景推荐模型理由地块以农田为主、边界较规整U-Net收敛快、对标注噪声容忍度高地类混杂、地块大小悬殊DeepLabV3ASPP 多尺度特征更稳只有少量标注几十张U-Net 预训练编码器参数少不容易过拟合没有预训练权重从零训练先跑 50 epoch 看趋势不要直接上大模型选型的核心原则是你的 GPU 显存和数据量决定网络规模而不是论文精度决定。先跑通小模型拿到基线再考虑换主干。数据集只有几百张切块时直接上 ResNet50 的 DeepLabV3 大概率过拟合。3. 地块数据不能省遥感影像预处理与训练样本制作3.1 栅格不是照片先做几何校正和辐射预处理遥感影像和普通照片最大的区别在于像素值不是 RGB而是记录地物反射率的 DN 值或多光谱波段。直接用 JPEG 格式的截图训练等于扔掉了一大半有效信息。正规做法是先对原始影像做辐射定标和大气校正将 DN 值转换为地表反射率。Sentinel-2 的 Level-1C 产品是大气表观反射率需用 Sen2Cor 处理成 Level-2A 地表反射率再做分割否则不同时相影像之间的光谱差异会严重影响模型泛化。预处理流程上比较固定的顺序是辐射定标 → 大气校正 → 重采样统一分辨率→ 按 ROI 裁剪 → 波段选择。波段选择是另一个关键环节。Sentinel-2 有 13 个波段地块分割通常选 4、3、2相当于 RGB加 8近红外组合成 4 通道输入植被相关任务可以加 5、6、7 红边波段。通道越多模型参数和显存开销越大但对植被地块的分割精度提升也明显。没有多光谱数据时用 RGB 加 NDVI 指数作为额外通道是性价比很高的替代方案。3.2 制作训练集坐标系对齐、矢量转栅格、切块标注数据通常是 shapefile 矢量面训练前必须转成与影像完全对齐的栅格掩膜。最容易出问题的是坐标系不一致影像可能是 UTM 投影矢量是 WGS84 经纬度直接转栅格会错位几个像素到几百米。建议用 GDAL 的gdal.RasterizeLayer在影像坐标系下完成矢量化而不是先用 ArcGIS 导出再对齐# 用 gdal_rasterize 将地块矢量转成与影像对齐的标签栅格 gdal_rasterize -burn 1 -init 0 -te xmin ymin xmax ymax \ -tr 10 10 -ot Byte -l parcels parcels.shp label.tif参数说明-te指定输出范围应完全取自影像的 geotransform-tr是输出分辨率必须与影像分辨率一致这里是 10 米-burn 1将地块内部像素赋值为类别 ID多类别时用-burn配合属性字段选择或用 SQL 语句按字段值批量生成。转完掩膜后用gdalinfo对比掩膜和影像的投影、分辨率、四角坐标确认三者在像素级别完全重合。3.3 切块策略滑动窗口切 512×512重叠率设多少遥感影像动辄上万像素宽不能整图送进网络。常见做法是以 512×512 窗口按步长滑动切块步长小于窗口尺寸即为重叠切块。# data/tile.py 切块脚本核心逻辑 from osgeo import gdal import numpy as np def sliding_window_crop(img_path, label_path, crop_size512, stride256): img_ds gdal.Open(img_path) label_ds gdal.Open(label_path) width, height img_ds.RasterXSize, img_ds.RasterYSize for y in range(0, height - crop_size 1, stride): for x in range(0, width - crop_size 1, stride): # 从影像与标签中裁剪对应区域 img img_ds.ReadAsArray(x, y, crop_size, crop_size) mask label_ds.ReadAsArray(x, y, crop_size, crop_size) # 过滤掉全部为背景(0)的样本减少正负样本不平衡 if mask.max() 0: continue yield img.transpose(1, 2, 0), mask切块时有两个坑值得注意。第一个是ReadAsArray的返回维度顺序GDAL 读出来是 (bands, height, width)需要转成 (height, width, bands) 再送进 PyTorch。第二个是背景占比过高的样本应该过滤掉否则模型会学到永远输出背景这个捷径。保留标签中目标像素占比 5% 以上的块通常能有效缓解类别不平衡。步长设置方面我习惯训练时用 256即 50% 重叠推理时用完整 512 步长增强数据多样性的同时控制推理耗时。3.4 标注不够怎么办数据增强和预训练权重不能只靠翻转让过拟合遥感分割对数据增强的需求比自然图像更依赖任务特点。随机翻转、缩放、色彩抖动可以带来稳定提升但要注意遥感影像的语义不随旋转改变所以 90 度旋转和镜像翻转都是安全操作。需要控制强度的是光照类增强因为不同时相遥感影像的光照差异本就大过度调节会破坏地物的光谱特征。更有效的技巧是使用 ImageNet 预训练权重做初始化遥感数据量不大时预训练权重带来的提升通常比复杂的网络结构更明显。4. 训练与调参损失函数、学习率与遥感特化技巧4.1 损失函数别只盯着 CrossEntropy混合 Loss 是标配像素级分割最常见的损失是交叉熵但遥感地块分割存在严重的类别不平衡问题农田、林地等大类动辄占 60% 以上水体、道路等小类别可能不足 5%。单独使用交叉熵会让模型忽略小类别。常用做法是将交叉熵与 Dice Loss 按权重混合# loss.py 混合损失 import torch import torch.nn.functional as F def dice_loss(pred, target, smooth1.0): # pred: (B, C, H, W) softmax 后概率, target: (B, C, H, W) one-hot intersection (pred * target).sum(dim(2, 3)) union pred.sum(dim(2, 3)) target.sum(dim(2, 3)) return 1 - (2 * intersection smooth) / (union smooth) def hybrid_loss(logits, target, ce_weight0.6): ce F.cross_entropy(logits, target) pred F.softmax(logits, dim1) target_onehot F.one_hot(target, num_classeslogits.shape[1]).permute(0, 3, 1, 2).float() dice dice_loss(pred, target_onehot).mean() return ce_weight * ce (1 - ce_weight) * dice逻辑说明交叉熵负责逐像素分类的整体收敛Dice Loss 负责缓解类别不平衡。ce_weight取值 0.5 到 0.7 之间效果比较稳定过高则小类别被淹没过低则训练初期梯度噪声偏大。Dice Loss 对smooth参数敏感建议设置在 0.1 到 1.0 之间太小会在类别完全不存在的区域出现数值不稳定。4.2 训练参数模板直接抄这一组起步拿到的 zip 中 train.py 通常有默认参数但未必合理建议按以下模板调整参数推荐值说明输入尺寸512×512兼顾显存和上下文信息batch size8单卡 11GB 显存不够时优先降 batch 而非降分辨率优化器AdamWlr 1e-4Adam 加权重衰减更稳学习率策略polypower0.9语义分割比 StepLR 效果好epoch60-100边训练边保存最优 IoU 的权重类别权重按像素频率倒数与大类小类差异大的数据集匹配poly 学习率策略是遥感分割中很值得优先尝试的方案它在训练后期以缓慢衰减的方式微调权重比固定步长下降在分割任务上更容易收敛到更优解# 每个 iteration 调用 lr base_lr * (1 - iter / total_iters) ** 0.9 optimizer.param_groups[0][lr] lrpoly 策略的核心逻辑是让学习率随训练进度从初始值平滑下降到接近 0最后阶段的微小学习率有助于在损失曲面底部精细搜索。相比余弦退火poly 在分割任务上无需手动调节 warm restart 周期少一个需要调试的超参数。4.3 训练过程看什么监控 mIoU 而不是 Loss遥感分割训练时的监控指标应该是 mIoU各类别 IoU 的均值而不是总 Loss。Loss 下降不代表小类别的 IoU 在上升很多时候 Loss 被大类稳定下降主导小类别的预测却在退化。建议每 500 步在验证集上跑一次 mIoU 和各类别 IoU并记录到日志同时保存验证 mIoU 最高的权重而不是用最后一轮权重。训练时发现 mIoU 长时间停滞而 Loss 仍在下降优先检查大类别的 IoU 是否过高小类别是否几乎预测不出来此时可以增大 Dice Loss 的权重或者对小类别做类别重加权。4.4 过拟合和欠拟合的快速判断地块分割数据量少过拟合出现得比自然图像更快。判断方法很简单训练 mIoU 持续在 0.9 以上验证 mIoU 在 0.6 到 0.7 之间波动且每轮验证集指标震荡明显就是过拟合的典型信号。优先降低模型复杂度换 ResNet34 或更浅的主干其次增强数据增强强度最后才考虑加正则化。反过来训练和验证 mIoU 都很低像 0.5 以下且验证集和训练集走势基本同步则意味着模型容量不足或数据本身有问题检查标签对齐比调模型参数更优先。另外一个容易忽略的点是验证集切块时不要把同一地块的邻近切块分到训练集和验证集两边否则验证指标虚高生产环境表现远差于预期。5. 从掩膜到地块推理策略、后处理与精度验证5.1 推理时的重叠拼接处理拼缝噪声训练时用 50% 重叠切块能提升精度推理时同样需要重叠。直接以步长 512 无重叠推理再接回全图切块边缘常出现明显的条带噪声。标准做法是推理时也用 256 步长得到多份重叠预测每一像素取多次预测结果的平均概率作为最终输出然后再取 argmax。这样做在拼缝处的预测一致性显著提升代价是推理耗时约为无重叠推理的四倍但实际工程中这个开销值得支付。有条件的话可以保留每个像素的最大概率值而不是平均概率对边界确定性高的区域更友好。5.2 后处理三板斧投票滤波、小连通域去除、矢量化预测掩膜直接用于制图和 GIS 分析前后处理不可省略。第一步是多数投票滤波用 3×3 或 5×5 窗口对掩膜做模式滤波消除椒盐状噪声。第二步是按连通域面积过滤小于设定阈值的连通区域大概率是误检用skimage.measure.label加regionprops实现。第三步是把栅格掩膜转成矢量面用 GDAL 的Polygonize函数完成# postprocess.py 矢量化和面积过滤 from skimage import measure from osgeo import gdal, ogr def mask_to_polygons(mask, min_area100): # mask: 单类别二值掩膜, min_area 以像素计实际面积乘像元大小换算 label_img measure.label(mask, connectivity2) for region in measure.regionprops(label_img): if region.area min_area: # 过小区域直接视为噪声 mask[label_img region.label] 0 return mask # 转矢量将类别掩膜写出为 uint8 栅格后用 Polygonize参数说明connectivity2表示四连通只把上下左右相邻的像素归为同一地块按对角线连接会错误合并相邻地块min_area需要结合影像分辨率换算成平方米10 米分辨率影像上 100 像素对应 10000 平方米即 1 公顷可以按业务里最小统计单元来设。5.3 精度验证不要在像素层面自欺欺人像素级 mIoU 高不等于地块识别效果好尤其是边缘像素在一幅 512×512 的切块中占比很低。工程上验证地块分割效果应该做两件事一是像素级 mIoU 和各类别 IoU这是论文通用的做法二是基于矢量结果的地块数量、面积总和与真实矢量对比这在业务上更有意义。推荐的验证方式是随机抽 10 到 20 个切块把预测掩膜和标签按 1:1 叠放生成对比图边缘拟合程度、小地块漏检情况一眼便知比自己硬算数字更有效。最后说一个最容易被忽略的验证点把你的验证指标和参考数据集交叉对比一个 GID 数据集上的 mIoU 0.75和一个自建小数据集上的 mIoU 0.75难度完全不可比汇报数字时永远要带数据集名称和分辨率。训练管线稳定后留出 10% 数据做最终盲测用那一次的指标作为真实效果基线。本文还有配套的精品资源点击获取