资讯中心

Landsat影像地物分类实战:基于CNN的完整流程与PyTorch实现

📅 2026/9/22 17:06:18
Landsat影像地物分类实战:基于CNN的完整流程与PyTorch实现
简介基于CNN深度学习的遥感Landsat影像地物分类算法完整Python项目面向遥感、地信、计算机视觉及人工智能方向的在校生与从业者也可作为毕业设计或课程设计的直接参考。压缩包共10个文件总大小约14.88MB主体为3个Python脚本、2个tif遥感影像、2个xml辅助文件以及h5模型、tfw定位文件和md说明脚本按“生成影像切片→训练CNN模型→预测新数据”组织h5为训练好的权重tif和tfw用于提供实验数据与地理配准信息。目前已有468人学习资源经测试可正常运行。适合需要快速跑通算法流程的初学者也适合在项目中借鉴工程结构与调参思路借助示例影像和预训练模型可直观对比分类效果并在此基础上替换数据或修改网络结构拓展到多类别地物识别任务。1. 基于CNN深度学习的遥感Landsat影像地物分类瓶颈往往不在模型而在数据很多人拿到Landsat影像做地物分类第一反应是去调网络结构但真正让分类精度上不去的通常是训练样本和预处理环节。Landsat 30米分辨率的多光谱影像一个patch里可能同时混着水体、植被和裸地如果样本裁剪方式不合理再深的CNN也学不到干净的边界特征。这个标题里的完整源码解决的就是从Landsat原始影像到分类成图的全链路问题波段选择、样本制作、模型训练、精度评定缺一环结果都会走样。对刚接触遥感深度学习的人可以先从Patch分类入手把流程跑通再考虑更重的语义分割模型。文中所有代码基于PyTorch和GDAL依托Landsat 8/9 Collection 2 Level-2表面反射率产品这也是USGS目前推荐的科研级数据源。2. 理解Landsat影像格式与数据预处理的关键步骤2.1 Landsat 8/9波段设置与分类相关性分析Landsat 8/9搭载的OLI传感器有11个波段其中用于地物分类的反射率波段是Band 1至Band 7Band 8是全色波段15米Band 9主要用于卷云检测Band 10和Band 11是热红外。如果目标是做标准的地物分类常见做法是用Band 2蓝、Band 3绿、Band 4红、Band 5近红外、Band 6短波红外1和Band 7短波红外2这六个波段作为模型输入——它们已经覆盖了植被、水体、土壤和建筑的主要光谱差异。2.1.1 为什么需要排除Band 1和Band 9Band 1海岸/气溶胶波段在陆地场景中噪声明显Band 9基本只对高层卷云敏感二者的值域分布和6个地物波段不在同一维度上。把这两个波段塞进网络不但增加参数量还可能让卷积层学到云层的伪特征。实际处理中直接用rasterio读取指定波段即可不需要额外去云——在样本制作阶段就把含云区域避开比在模型里做云检测更省事。2.1.2 表面反射率与DN值的差别Collection 2 Level-2产品已经完成了辐射定标和大气校正像元值代表地表反射率范围01存储时乘以10000。这意味着拿来就能用不需要自行做大气校正。如果搜到的是Level-1级别的存档数据才需要考虑辐射定标和大气校正的预处理步骤常见做法是用ENVI或LASZ这类工具批处理但更推荐直接下载Level-2产品。2.2 Landsat数据下载与预处理的标准流程Landsat数据下载推荐USGS EarthExplorer平台选区域后筛Collection 2 Level-2导出GeoTIFF格式。下载后每个波段是独立的TIF文件第一步是把6个波段合成一个多波段单文件。2.2.1 用GDAL实现波段合成与坐标对齐gdal_merge.py -o landsat_stack.tif -separate \ LC08_L2SP_*.TIF_B2.TIF \ LC08_L2SP_*.TIF_B3.TIF \ LC08_L2SP_*.TIF_B4.TIF \ LC08_L2SP_*.TIF_B5.TIF \ LC08_L2SP_*.TIF_B6.TIF \ LC08_L2SP_*.TIF_B7.TIF-separate参数保证每个波段作为独立通道写入输出为一个6波段的GeoTIFF。如果影像范围覆盖多个景还要先做镶嵌gdal_merge.py不带-separate再裁剪到研究区边界避免冗余计算。2.2.2 影像裁剪与像元值归一化用gdal_translate结合-projwin参数裁剪到目标范围裁剪后对每个波段做百分比截断——常见做法是取2%98%的百分位做线性拉伸到[0, 1]区间。这一步很关键因为Landsat影像不同季节的反射率分布差异很大直接从原始数值训练会让网络的初始梯度不稳定。import numpy as np from osgeo import gdal ds gdal.Open(landsat_stack.tif) arr ds.ReadAsArray().astype(np.float32) for i in range(arr.shape[0]): band arr[i] p2, p98 np.percentile(band, (2, 98)) band np.clip((band - p2) / (p98 - p2), 0, 1) arr[i] band归一化后需要把波段维放到Pytorch默认的(C, H, W)顺序同时留意NaN值——Landsat的填云像元值为0归一化后会成为有效值需要在样本裁剪阶段联合QA波段把非有效像元筛掉。2.3 训练样本制作与数据集划分策略地物分类是逐像元的分类任务但CNN天然处理图像块所以要把标注好的像元扩展成以该像元为中心的Patch。Patch大小直接影响模型感受野和地物边界保留程度。2.3.1 使用LabelMe或QGIS标注地物类别常见工作流是用QGIS加载合成影像如5/4/3波段假彩色合成手工勾画水体、植被、裸地、建筑、道路、农田等类别多边形然后栅格化成分类标签图。类别定义宁少勿多——6~8个类别足够覆盖多数场景类别过细会让样本极不均衡模型训练难度成倍上升。2.3.2 Patch裁剪、样本增强与数据集切分以每个标注像元为中心切patchpatch尺寸通常取32×32或64×64像素。Landsat 30米分辨率下32×32像素对应960米地面范围对区分道路和建筑这种相邻地物略大用16×16可能更合适但边界效应更强。我会先试16和32两组对比哪个验证集精度高用哪个。切patch时只保留中心像元标签但patch内其他像元的标签不做约束这样分类边界会比较自然也避免模型只依赖中心先验。数据集划分按城市或区块为单位而不是按像元——按像元随机划分会让同一块区域的训练和验证样本高度相似Kappa虚高换到新区域精度立刻掉下来。import torch from torch.utils.data import Dataset class LandsatPatchDataset(Dataset): def __init__(self, image, label, patch_size32, stride16): self.image torch.from_numpy(image).float() self.label torch.from_numpy(label).long() self.patch_size patch_size self.indices self._sample_indices(stride) def _sample_indices(self, stride): h, w self.label.shape idx [] for r in range(0, h - self.patch_size, stride): for c in range(0, w - self.patch_size, stride): patch_labels self.label[r:rself.patch_size, c:cself.patch_size] center patch_labels[self.patch_size // 2, self.patch_size // 2] if center 0 and torch.sum(patch_labels center) 0: idx.append((r, c)) return idx def __len__(self): return len(self.indices) def __getitem__(self, i): r, c self.indices[i] img self.image[:, r:rself.patch_size, c:cself.patch_size] lab self.label[r self.patch_size // 2, c self.patch_size // 2] return img, lab这段代码中_sample_indices用一个stride参数在影像上滑动生成候选中心点只保留中心标签有效的patch。stride小于patch_size时产生重叠patch等于patch_size时不重叠。实际训练时stride设为patch尺寸的一半能让样本量翻倍又不过度冗余。本文还有配套的精品资源点击获取

看完文章,想为自己的企业也做一次专业网站诊断?

尧图顾问免费为您评估现有网站,并给出建站/改版建议与报价方案。

免费获取方案