首页 / 资讯中心 / 文章详情

PyTorch遥感语义分割实战:PSPNet/DeepLabv3+耕地水体建筑识别

PyTorch遥感语义分割实战:PSPNet/DeepLabv3+耕地水体建筑识别 ★ FEATURED ARTICLE
简介本资源是一套面向计算机及相关专业本科生的遥感图像国土分类课程设计实战源码聚焦基于深度学习图像分割技术PSPNet、DeepLabV3/Plus实现卫星影像地物识别与分类任务适用于课程设计、期末大作业及项目实训场景。压缩包共12个文件含8个核心Python脚本涵盖数据预处理、模型构建、训练调度与日志记录、2个训练日志文件、1个说明文本及1张成果展示图整体体积仅2.49MB轻量易部署。目前已有159人下载学习资源经严格调试支持开箱即用——提供完整可运行流程从原始遥感数据加载、标准化预处理含water增强模块到多模型对比实验与结果可视化目录结构清晰模块职责分明便于理解分割网络在遥感领域的适配逻辑与工程落地要点。1. 卫星图上画个框自动标出农田、水体、建筑——这不是GIS软件是用PyTorchPSPNet跑通的课程设计级遥感语义分割系统你手头有一张30cm分辨率的国产高分卫星图想快速知道哪片是耕地、哪块是水库、哪栋楼属于违建区——别急着打开ArcGIS或ENVI。这个课程设计项目用不到200行核心训练逻辑deecamp_train.py配合预置的PSPNet和DeepLabv3双模型结构就能在普通GTX1660显卡上完成端到端训练推理。它不依赖商业遥感平台所有数据预处理preprocess.py/preprocess_water.py、标签映射、损失函数加权、多尺度验证全写死在代码里更关键的是它专为学生场景打磨没有抽象封装每个.py文件都对应一个可调试模块连日志文件名pspnet.log/deeplab_v3.log都按模型命名方便你对照报错定位。如果你正被“课程设计要交国土分类结果但不会调参”、“测试集mIoU卡在62%不知道哪步出问题”、“导师说‘再加个水体识别’却找不到入口函数”这类问题卡住这个包就是为你写的——它不是玩具Demo而是某高校遥感AI课连续三年复用的baseline工程。2. 项目结构与技术栈从data目录到seg_zoo.py看清这个课程设计的骨架2.1 目录结构即开发路径5个核心目录7个主模块的协作关系项目解压后呈现典型的遥感深度学习工程结构不追求框架感只保证每一步都能打断点调试. ├── data/ # 原始数据占位符含保密说明 │ └── 高精卫星保密数据无法开源.txt # 明确提示真实数据需自行替换 ├── nets/ # 模型定义目录非torchvision标准库 │ ├── pspnet.py # PSPNet主干金字塔池化实现 │ ├── deeplabv3.py # DeepLabv3基础版ASPP无空洞卷积优化 │ ├── deeplabv3_plus.py # DeepLabv3完整版含Decoder上采样模块 │ └── seg_zoo.py # 模型工厂统一接口加载不同网络 ├── preprocess.py # 主预处理裁剪归一化标签编码含8类地物映射表 ├── preprocess_water.py # 水体专项预处理针对水域边缘模糊问题增强对比度 ├── data_load.py # 数据加载器支持VOC格式自定义class_weight ├── deecamp_train.py # 核心训练脚本含早停、学习率衰减、多GPU兼容开关 ├── pspnet.log / deeplab_v3.log # 按模型分离的日志记录loss/mIoU/epoch耗时 └── 26组poster展示.png # 可视化结果示例含混淆矩阵预测热力图注意data/目录下无实际图像仅保留占位文件。这是课程设计常见做法——避免版权风险同时强制学生理解数据接入流程。你只需按preprocess.py中定义的路径规则如data/images/存原图data/labels/存8位PNG标签图放入自己的遥感影像即可。2.2 技术选型直击课程设计痛点为什么不用U-Net而选PSPNet课程设计最怕“模型太重跑不动”或“效果太差没法交”。本项目在模型选择上做了三处务实妥协主干网络用ResNet50而非ResNet101pspnet.py第42行明确指定backboneresnet50参数量减少37%单卡batch_size可设为8GTX1660实测避免OOMPSPNet的金字塔池化层用4级固定尺度1,2,3,6比原始论文少一级降低显存峰值pspnet.py中self.pool1 nn.AdaptiveAvgPool2d(1)等四行直接定义无需动态计算损失函数放弃Focal Loss改用加权交叉熵deecamp_train.py第156行weighttorch.tensor([0.1,0.8,0.3,...])硬编码8类权重其中水体索引1权重0.8——因为遥感图中水体占比小但漏检惩罚大这是某次答辩被导师追问后补的血泪经验。这种“够用就好”的选型让代码量压缩到可读范围pspnet.py仅327行deeplabv3_plus.py仅412行所有空洞卷积、上采样操作都用nn.Conv2d(dilation...)和F.interpolate()直写不套用torch.nn.functional高级封装。2.3 seg_zoo.py模型切换的唯一入口3行代码切DeepLabv3当你需要对比不同模型效果时不用改训练循环——所有模型加载逻辑收束在seg_zoo.py# seg_zoo.py 第22-24行 def get_model(model_name, num_classes8, pretrainedTrue): if model_name pspnet: return PSPNet(num_classesnum_classes, pretrainedpretrained) elif model_name deeplabv3: return DeepLabV3(num_classesnum_classes, pretrainedpretrained) elif model_name deeplabv3_plus: return DeepLabV3Plus(num_classesnum_classes, pretrainedpretrained)调用时只需在deecamp_train.py第35行修改model get_model(deeplabv3_plus, num_classes8) # 原来是pspnet玄学提示实测在小样本500张图场景下deeplabv3_plus比pspnetmIoU高1.2%但训练时间多35%。如果课程设计截止前48小时建议先用PSPNet出结果再切DeepLabv3做最终提升。2.4 preprocess.py国土分类特有的8类标签映射表遥感图像分类不是简单分“车/人/路”而是按国土调查规范定义8类标签ID类别RGB值用于可视化备注0背景[0,0,0]未标注区域1水体[0,0,255]河流/湖泊/水库2耕地[0,255,0]水田/旱地不区分3林地[0,128,0]乔木/灌木不区分4草地[128,255,0]天然草/人工草5建筑用地[255,0,0]居民区/工业区/道路6未利用地[128,0,128]裸土/沙地/盐碱地7其他[255,255,0]雪地/云层训练时建议丢弃该映射表硬编码在preprocess.py第18行CLASS_COLORS { 0: [0, 0, 0], 1: [0, 0, 255], 2: [0, 255, 0], 3: [0, 128, 0], 4: [128, 255, 0], 5: [255, 0, 0], 6: [128, 0, 128], 7: [255, 255, 0] }关键细节preprocess.py第89行label np.where(label7, 0, label)会将“其他”类强制转为背景——因为课程设计通常只要求6类主体地物此举避免模型学习噪声。3. 运行全流程从环境配置到生成poster展示图每步附验证命令3.1 环境配置避开CUDA版本地狱的3个确定性方案课程设计最怕环境配三天跑不通。本项目经测试在以下三种环境中100%可运行按推荐顺序方案命令优势适用场景Conda最小依赖conda create -n rs-seg python3.8 conda activate rs-seg pip install torch1.10.0cu113 torchvision0.11.1cu113 -f https://download.pytorch.org/whl/torch_stable.html pip install opencv-python4.5.5.64 scikit-learn1.0.2 tqdm4.64.0锁定PyTorch 1.10适配CUDA 11.3避免新版PyTorch对老显卡驱动的苛刻要求GTX10系/RTX20系显卡Docker轻量版docker run --gpus all -v $(pwd):/workspace -it pytorch/pytorch:1.10.0-cuda11.3-cudnn8-runtime bash容器内已预装CUDA工具链pip install -r requirements.txt后直接运行本地环境混乱或需多项目隔离Colab速配版在Google Colab新建Notebook → Runtime → Change runtime type → GPU → 执行!pip install torch1.10.0cu113 torchvision0.11.1cu113 -f https://download.pytorch.org/whl/torch_stable.html!pip install opencv-python scikit-learn tqdm免配置3分钟启动适合紧急演示课程答辩前夜救急提示若用Conda方案务必执行conda install -c conda-forge gdal3.4.3安装GDAL处理GeoTIFF坐标信息否则data_load.py读取带地理坐标的遥感图会报错。3.2 数据准备用preprocess.py生成符合VOC格式的训练集真实遥感数据常为GeoTIFF格式需转换为模型可读的PNGTXT组合。preprocess.py提供一键转换# 假设你的原始数据在 ./my_data/ 下 # ./my_data/images/xxx.tif 多光谱需转RGB # ./my_data/labels/xxx.tif 矢量栅格化后的标签图 python preprocess.py \ --image_dir ./my_data/images/ \ --label_dir ./my_data/labels/ \ --output_dir ./data/ \ --img_size 512 \ --num_classes 8执行后生成./data/images/512×512的JPEG图像自动RGB三通道提取./data/labels/8位PNG标签图像素值0-7./data/trainval.txt训练验证集划分默认8:2可改preprocess.py第122行验证是否成功# 检查标签图是否为8位 identify -format %[depth] ./data/labels/000001.png # 应输出8 # 检查类别分布避免全黑图 python -c import numpy as np; lnp.array(Image.open(./data/labels/000001.png)); print(np.unique(l)) # 应输出类似 [0 1 2 3 4 5 6]不含7因已被过滤3.3 启动训练deecamp_train.py的5个关键参数详解deecamp_train.py是唯一需要修改的训练入口其核心参数如下参数示例值说明课程设计建议--modelpspnet模型类型见seg_zoo.py初次运行用pspnet稳定后再试deeplabv3_plus--epochs50总训练轮数小数据集300张设为30防过拟合--batch_size8单卡batch大小GTX1660最大支持8RTX3090可提至16--lr1e-3初始学习率若loss下降慢尝试5e-4若震荡降为1e-4--num_workers4数据加载线程数设为CPU核心数-1避免IO瓶颈启动命令python deecamp_train.py \ --model pspnet \ --epochs 30 \ --batch_size 8 \ --lr 0.001 \ --num_workers 4 \ --data_dir ./data/ \ --log_dir ./logs/ \ --save_interval 10训练过程监控实时查看pspnet.log末尾Epoch 12/30 | Train Loss: 0.214 | Val mIoU: 0.682每10轮保存一次模型./logs/pspnet_epoch_10.pth若Val mIoU连续5轮不升早停机制自动终止deecamp_train.py第218行3.4 推理与可视化用train.py生成poster展示图训练完成后用deecamp_train.py内置的推理功能生成答辩用图python deecamp_train.py \ --mode predict \ --model pspnet \ --weights ./logs/pspnet_epoch_30.pth \ --image_path ./data/images/000001.jpg \ --output_dir ./results/ \ --num_classes 8输出内容./results/000001_pred.png预测结果彩色标签图./results/000001_overlay.png原图预测热力图叠加红建筑蓝水体./results/confusion_matrix.png8×8混淆矩阵验证各类别识别精度关键技巧deecamp_train.py第312行cv2.addWeighted(img, 0.6, overlay, 0.4, 0)控制叠加透明度若热力图太淡把0.4改为0.6。4. 避坑指南课程设计中最常翻车的5个问题及解决方案4.1 现象训练启动报错ModuleNotFoundError: No module named nets.pspnet原因Python未将项目根目录加入sys.path导致import nets.pspnet失败。解决在deecamp_train.py开头添加两行第1-2行import sys sys.path.append(.) # 确保能import nets/下的模块血泪经验某同学在PyCharm中右键Run导致工作目录为nets/必须手动设置Run Configuration的Working directory为项目根目录。4.2 现象验证时mIoU恒为0.000且Val mIoU日志始终不更新原因data_load.py中标签图读取后未转为np.long类型PyTorch的CrossEntropyLoss要求target为long。解决在data_load.py第68行label np.array(label)后插入label label.astype(np.long) # 强制转为long类型排查方法在deecamp_train.py第185行print(Label dtype:, labels.dtype)若输出int32则必出此错。4.3 现象预测结果全是黑色全为背景类0原因preprocess.py生成的标签图是灰度PNG但OpenCV默认读为BGR三通道导致label[:,:,0]取错通道。解决在data_load.py第67行label cv2.imread(...)后加if len(label.shape) 3: label cv2.cvtColor(label, cv2.COLOR_BGR2GRAY) # 强制转单通道验证用plt.imshow(label, cmapgray)检查应显示清晰的8级灰度图而非彩色噪点。4.4 现象训练loss下降但Val mIoU卡在0.55不上升原因preprocess_water.py未启用水体边缘模糊导致模型学不会水陆分界。解决在deecamp_train.py第102行transform transforms.Compose([...])中将preprocess_water.py的增强加入from preprocess_water import WaterEnhance transform transforms.Compose([ WaterEnhance(), # 新增水体增强 transforms.ToTensor(), transforms.Normalize(mean[0.485,0.456,0.406], std[0.229,0.224,0.225]) ])原理WaterEnhance对蓝色通道做CLAHE增强提升水体纹理对比度。4.5 现象26组poster展示.png中的混淆矩阵数值异常某类召回率100%但精确率0%原因deecamp_train.py第295行混淆矩阵计算时pred pred.argmax(dim1)未排除背景类ID0。解决修改为pred pred.argmax(dim1) pred torch.where(pred0, torch.tensor(-1), pred) # 背景类设为-1不参与计算后果若不修复背景类会污染统计导致“耕地识别率100%”的假阳性。5. 二次开发实战给国土分类加“水体变化检测”功能3步改造课程设计常被要求“增加新功能”比如导师说“能不能看出水库今年比去年少了多少”——这本质是多时相遥感变化检测。本项目结构天然支持扩展只需3步改造无需重写模型5.1 步骤1扩展数据加载器支持双时相输入data_load.py原只支持单图输入需改造为接收t0_img和t1_img# data_load.py 第75行起替换原__getitem__方法 def __getitem__(self, index): img_path self.imgs[index] label_path self.labels[index] # 读取t0去年和t1今年图像 t0_img cv2.imread(img_path.replace(t1, t0)) # 假设文件名含t0/t1标识 t1_img cv2.imread(img_path) # 统一预处理 t0_img self.transform(t0_img) t1_img self.transform(t1_img) label cv2.imread(label_path, cv2.IMREAD_GRAYSCALE) label torch.from_numpy(label).long() # 返回双时相图像 标签 return t0_img, t1_img, label配套修改在deecamp_train.py第115行DataLoader中collate_fn需适配双输入def collate_fn(batch): t0_imgs, t1_imgs, labels zip(*batch) return torch.stack(t0_imgs), torch.stack(t1_imgs), torch.stack(labels)5.2 步骤2改造PSPNet输出双时相特征差分图pspnet.py原输出单图分割结果现需输出变化掩膜。在forward末尾加差分逻辑# pspnet.py 第128行起替换原return语句 def forward(self, x_t0, x_t1): # 分别提取t0和t1特征 feat_t0 self.backbone(x_t0) # [B, C, H, W] feat_t1 self.backbone(x_t1) # 特征差分绝对值 diff_feat torch.abs(feat_t0 - feat_t1) # [B, C, H, W] # 差分特征送入PSP模块复用原psp层 out self.psp(diff_feat) out self.cls(out) # 输出2类0无变化1有变化 return out # [B, 2, H, W]关键点self.cls需重新定义为2分类头原为8类在__init__中修改self.cls nn.Sequential( nn.Conv2d(512, 256, 3, padding1, biasFalse), nn.BatchNorm2d(256), nn.ReLU(), nn.Dropout2d(0.1), nn.Conv2d(256, 2, 1) # 改为2通道输出 )5.3 步骤3定制损失函数聚焦水体变化区域国土变化中水体面积变化最具业务价值。需在损失中加权水体区域# deecamp_train.py 第160行替换原loss计算 def water_change_loss(pred, target, water_mask): pred: [B,2,H,W] 预测变化概率 target: [B,H,W] 真实变化标签0无变1有变 water_mask: [B,H,W] 水体区域掩膜1水体0非水体 ce_loss F.cross_entropy(pred, target, reductionnone) # [B,H,W] # 水体区域loss权重×3 weight torch.where(water_mask 1, torch.tensor(3.0), torch.tensor(1.0)) weighted_loss (ce_loss * weight).mean() return weighted_loss # 训练循环中调用 water_mask (label 1).float() # label1即水体 loss water_change_loss(outputs, change_target, water_mask)验证效果改造后在./results/下生成change_map.png红色区域即为水体缩减区——这正是国土监测报告的核心图表。从那以后我每次接课程设计需求都强制走一遍“先看seg_zoo.py确认模型入口再查preprocess.py的标签映射最后在deecamp_train.py里找--mode开关”的三步法。因为90%的“加功能”需求本质只是改数据加载方式、换模型输出头、调损失函数权重——而不是重写整个pipeline。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站