
简介这份资源面向计算机相关专业的本科生与课程设计学习者提供一套基于UNet的遥感图像语义分割完整毕业设计项目涵盖可运行源码与配套论文适合作为毕业设计、期末大作业或课程设计参考难度适中评审分达98分。压缩包共68个文件约46.94MB包含6个Python源码文件与6个编译文件覆盖模型定义、数据处理与训练预测流程另有3个Jupyter Notebook用于数据集制作、训练与预测演示5个tex论文章节文件及配套图表、字体与参考文献以及若干png、svg示意图和说明文档结构清晰便于按模块查阅。目前已有369人学习下载。读者可据此获得一套从数据准备、模型搭建到训练评估的完整方案结合论文与Notebook快速理解UNet在遥感分割任务中的实现细节并在此基础上修改适配自己的课题节省从零搭建的时间成本。1. 遥感语义分割毕设选型为什么 UNet 在这个场景里仍是稳妥解遥感图像语义分割这个方向每年毕业设计季都会被翻出来做一遍。原因不复杂数据可获取、任务定义清晰、指标好量化而且 UNet 这种编码器-解码器结构在中等规模数据集上收敛稳定不像 Transformer 系方案那样吃显存、吃调参经验。这份资源给的是一个完整的 Python 毕业设计项目核心是基于 UNet 的遥感图像语义分割包含可运行源码、Jupyter Notebook 实验流程以及一份 LaTeX 排版的毕业论文。适合谁正在做计算机视觉方向毕设、需要一份能跑通、能改、能写进论文的基线项目的同学以及想快速搭一个分割 pipeline 验证自己想法的从业者。遥感图像和自然图像有个本质区别地物类别边界往往不规则小目标密集且同一类别在不同光照、季节下光谱差异大。UNet 的 skip connection 在这里价值很高——浅层特征保留边缘和纹理深层特征负责语义判别拼接后对细小地物更友好。这份资源没有堆砌花哨模块而是把数据制作、训练、预测、可视化拆成独立脚本和 Notebook结构上更像一个可复现的实验工程而不是一次性 demo。论文部分用 LaTeX 分章节组织chap1 到 chap5 对应绪论、相关技术、方法、实验、总结Figures 和 Bibs 目录齐全直接改校名和章节内容就能用。2. 源码结构与运行链路从 start_jupyter 到 train.ipynb 的完整走法2.1 目录拆解与模块职责拿到压缩包后先别急着跑花五分钟把目录结构看清楚后面排错会省很多时间。根目录下src是核心代码demo放演示脚本毕业论文是 LaTeX 源文件start_jupyter.ps1和start_tensorboard.ps1是两个 PowerShell 启动脚本。src里的文件分工如下文件职责关键内容model.py网络定义UNet 主体编码器下采样、解码器上采样、skip 拼接data.py数据集加载Dataset 类、增强、归一化、DataLoader 封装train.py训练入口损失函数、优化器、epoch 循环、模型保存utils.py工具函数指标计算、可视化、路径处理cnn.py卷积模块可能包含基础 conv block 或对比模型__init__.py包初始化模块导出create_dataset.ipynb负责把原始遥感影像和标注 mask 整理成训练格式train.ipynb是交互式训练流程predict.ipynb做推理和结果可视化。这种 Notebook 脚本双轨的设计好处是调试时能逐 cell 看中间结果正式训练又能走train.py批量跑。2.2 环境准备与依赖安装遥感分割项目常见的翻车点不在模型而在环境。PyTorch 版本、CUDA 驱动、torchvision 三者对不上报错信息还特别隐晦。我一般会先建独立虚拟环境再按官方推荐组合装。# 创建虚拟环境Python 版本建议 3.8 到 3.10 python -m venv venv_unet # Windows 激活 venv_unet\Scripts\activate # Linux / macOS 激活 source venv_unet/bin/activate # 安装 PyTorch以 CUDA 11.8 为例具体版本按自己显卡驱动选 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 # 安装其余依赖 pip install numpy opencv-python matplotlib jupyter tensorboard tqdm这里有个参数要留意--index-url后面跟的 cu118 表示 CUDA 11.8 编译版本。如果你显卡驱动较老换成 cu117 或 cpu 版本。装完后用下面这段验证import torch print(torch:, torch.__version__) print(cuda available:, torch.cuda.is_available()) print(device count:, torch.cuda.device_count())如果cuda available是 False先别怀疑代码九成是驱动或版本不匹配。CPU 也能跑只是训练时间会从几十分钟拉到几小时毕设演示够用正式实验建议上 GPU。2.3 数据制作create_dataset.ipynb 怎么改遥感数据一般有两种来源公开数据集如 LoveDA、DeepGlobe和自己标注的影像。create_dataset.ipynb的作用是把影像和 mask 配对切成固定尺寸 patch生成训练/验证/测试划分。常见做法是保持一个data目录结构如下data/ images/ # 原始影像jpg 或 tif masks/ # 标注 maskpng像素值即类别 id train.txt # 训练集文件名列表 val.txt test.txt在 Notebook 里需要改的通常是三个变量原始影像路径、mask 路径、输出 patch 尺寸。遥感影像分辨率高直接整图训练显存扛不住切成 256×256 或 512×512 是常规操作。切的时候要注意重叠采样否则地物跨 patch 边界会被切断影响小目标召回。# 伪代码示意实际以 notebook 内变量名为准 IMG_DIR data/images MASK_DIR data/masks PATCH_SIZE 256 STRIDE 128 # 小于 PATCH_SIZE保证重叠 # 读取影像和 mask按 stride 滑窗切块 # mask 用最近邻插值避免类别 id 被插值成小数mask 处理是血泪经验最多的地方千万不能用双线性插值缩放 mask类别 id 会被平均成 0.5 这种无意义值。要么最近邻要么先 one-hot 再插值。2.4 训练配置train.py 与 train.ipynb 的参数含义train.py是正式训练入口核心参数集中在文件头部。下面这段是典型配置具体数值以源码为准# 训练超参数 BATCH_SIZE 4 # 显存 8G 左右建议 412G 可上 8 LR 1e-4 # UNet 常用初始学习率 EPOCHS 100 # 遥感数据收敛慢别设太小 NUM_CLASSES 6 # 按自己数据集类别数改 IMG_SIZE 256 # 损失函数多分类常用 CrossEntropy类别不均衡可加 Dice criterion nn.CrossEntropyLoss() optimizer torch.optim.Adam(model.parameters(), lrLR) scheduler torch.optim.lr_scheduler.StepLR(optimizer, step_size30, gamma0.1)参数怎么调BATCH_SIZE受显存限制报 OOM 就减半LR太大 loss 震荡太小收敛慢1e-4 是安全起点NUM_CLASSES必须和 mask 里最大类别 id 对齐差一个就会报 index out of range。StepLR每 30 个 epoch 降一次学习率是 UNet 训练里比较稳的策略。启动训练# 脚本方式 python src/train.py # 或打开 notebook 逐 cell 跑 jupyter notebook train.ipynbstart_tensorboard.ps1用来启动 TensorBoard 看 loss 曲线和分割结果tensorboard --logdir runs如果 loss 前几个 epoch 不降反升先检查 mask 的像素值是不是 0/255 而不是 0/1/2/3这是最高频的翻车点。3. UNet 模型细节与训练调参编码器、skip connection 和损失函数怎么配合3.1 编码器-解码器结构与 skip connection 的作用UNet 的结构可以拆成三部分下采样编码、上采样解码、skip 拼接。编码器每经过一个 stage特征图尺寸减半、通道数翻倍逐步提取从边缘到语义的抽象特征。解码器反过来上采样恢复分辨率同时把编码器对应层的特征拼过来。为什么 skip connection 在遥感分割里特别关键遥感影像里田块、道路、建筑这些地物边界往往就是几个像素宽。如果只靠深层特征上采样边界会糊成一团。skip 把浅层的高分辨率细节直接送到解码端边界清晰度明显提升。代价是显存占用增加因为要保存编码器每一层的特征图。model.py里通常能看到这样的结构class UNet(nn.Module): def __init__(self, in_channels3, num_classes6): super().__init__() # 编码器4 次下采样 self.enc1 DoubleConv(in_channels, 64) self.enc2 DoubleConv(64, 128) self.enc3 DoubleConv(128, 256) self.enc4 DoubleConv(256, 512) self.pool nn.MaxPool2d(2) # 瓶颈层 self.bottleneck DoubleConv(512, 1024) # 解码器4 次上采样 拼接 self.up4 nn.ConvTranspose2d(1024, 512, 2, 2) self.dec4 DoubleConv(1024, 512) # ... 后续层省略 self.out nn.Conv2d(64, num_classes, 1)DoubleConv一般是两次 3×3 卷积加 BN 加 ReLU。ConvTranspose2d做上采样kernel 和 stride 都设 2正好尺寸翻倍。拼接时通道数相加所以dec4的输入是 5125121024。3.2 损失函数选择与类别不均衡处理遥感数据集天然类别不均衡背景、植被占大头某些稀有地物可能只占百分之几。纯 CrossEntropy 会让模型偏向多数类稀有类 recall 很低。常见做法有三种一是加权 CrossEntropy给稀有类更高权重# 按类别频率的倒数设权重 class_weights torch.tensor([1.0, 2.0, 5.0, 5.0, 3.0, 1.0]).to(device) criterion nn.CrossEntropyLoss(weightclass_weights)二是 CrossEntropy Dice 组合Dice 对前景区域更敏感def dice_loss(pred, target, smooth1e-6): pred torch.softmax(pred, dim1) # 对每个类别算 Dice 后平均 intersection (pred * target).sum(dim(2, 3)) union pred.sum(dim(2, 3)) target.sum(dim(2, 3)) dice (2 * intersection smooth) / (union smooth) return 1 - dice.mean() total_loss ce_loss 0.5 * dice_loss三是 Focal Loss压制易分类样本的梯度。三种没有绝对优劣我一般先跑加权 CE 看 baseline如果稀有类指标还是差再叠 Dice。3.3 训练过程监控与指标解读训练时重点看三个东西loss 曲线、验证集 mIoU、分割结果可视化。TensorBoard 里 loss 分 train 和 val 两条如果 train 一直降而 val 反弹就是过拟合加数据增强或早停。mIoU 是语义分割的主指标计算方式是每个类别的 IoU 求平均。遥感数据里如果某个类别的 IoU 长期为 0先别调模型去检查这个类别的 mask 是不是根本没出现在训练集里。# 简化的 mIoU 计算 def compute_miou(pred, target, num_classes): pred pred.argmax(dim1) ious [] for cls in range(num_classes): pred_mask (pred cls) target_mask (target cls) intersection (pred_mask target_mask).sum().item() union (pred_mask | target_mask).sum().item() if union 0: ious.append(intersection / union) return sum(ious) / len(ious) if ious else 0.0注意union 0这个判断如果某类在 batch 里完全没出现直接跳过否则会引入无意义的 0。3.4 推理与可视化predict.ipynb 怎么用训练完保存的权重一般在runs或checkpoints目录。predict.ipynb加载权重对测试集或单张影像做推理输出彩色 mask 叠加图。model.load_state_dict(torch.load(checkpoints/best.pth, map_locationdevice)) model.eval() with torch.no_grad(): output model(img_tensor.unsqueeze(0).to(device)) pred output.argmax(dim1).squeeze().cpu().numpy() # 用调色板把类别 id 映射成颜色 color_mask palette[pred]推理时model.eval()和torch.no_grad()两个都不能少前者关掉 BN 和 Dropout 的训练行为后者省显存。可视化时建议把原图、预测 mask、真值 mask 三张并排一眼就能看出模型在哪类地物上翻车。4. 避坑与排查遥感分割项目里最容易翻车的五个点4.1 现象训练 loss 一直是 nan原因学习率过大或者 mask 里有非法类别 id导致 CrossEntropy 计算出 inf。也可能是输入影像没归一化像素值 0-255 直接进网络。解决先把 LR 降到 1e-5 试一个 epoch检查 mask 的 unique 值确保都在[0, num_classes)范围内输入做ToTensor后加 Normalize均值方差用 ImageNet 的或自己数据集统计的。4.2 现象mIoU 卡在 0.2 上不去原因最常见的是 mask 和影像没对齐切 patch 时用了不同的随机种子或不同的 stride。其次是类别 id 映射错了比如背景是 0 但被当成忽略区域。解决抽几张训练样本把影像和 mask 叠在一起可视化确认地物边界对得上。再打印 mask 的直方图看类别分布是否符合预期。4.3 现象显存 OOMbatch size 降到 1 还报错原因UNet 在 512×512 输入下编码器特征图通道数到 1024显存占用很大。如果还开了多尺度训练或保存了所有中间特征更容易爆。解决把输入降到 256×256用torch.cuda.amp混合精度训练或者把编码器换成预训练的 ResNet 主干减少参数量。混合精度大概能省 30% 到 40% 显存。scaler torch.cuda.amp.GradScaler() with torch.cuda.amp.autocast(): output model(images) loss criterion(output, masks) scaler.scale(loss).backward() scaler.step(optimizer) scaler.update()4.4 现象验证集指标比训练集还高原因验证集太小或者验证集和训练集有重叠 patch。遥感影像切 patch 时如果重叠采样又没按影像划分同一张图的不同 patch 会同时出现在训练和验证里造成数据泄漏。解决按整张影像划分训练/验证/测试而不是按 patch 随机分。划分前先列出所有影像文件名按 7:2:1 分好再各自切 patch。4.5 现象TensorBoard 打不开或没有曲线原因start_tensorboard.ps1里的 logdir 路径和实际保存路径不一致或者训练时没调用SummaryWriter。解决确认train.py里有writer.add_scalar(loss/train, loss, epoch)这类调用logdir 指向runs目录的上一级。启动后浏览器开localhost:6006如果端口被占加--port 6007。5. 论文 LaTeX 工程与实验复现从 chap1 到 chap5 的落地技巧5.1 LaTeX 论文结构拆解与编译毕业论文目录下是标准的 LaTeX 工程chap1.tex到chap5.tex分章节Figures放图片Bibs放参考文献字体目录放中文字体。编译顺序一般是 xelatex → bibtex → xelatex → xelatex四次才能把交叉引用和参考文献都解析对。# 在毕业论文目录下 xelatex main.tex bibtex main xelatex main.tex xelatex main.tex如果报字体缺失检查字体目录里的 ttf 是否被主 tex 文件正确引用。中文论文建议用 xelatex 而不是 pdflatex否则中文会乱码。5.2 实验数据与论文图表的对应关系论文里的实验章节通常需要数据集介绍表、模型结构图、loss 曲线、mIoU 对比表、分割结果可视化图。这份资源的Figures目录应该已经放了部分图但用自己的实验数据替换时要注意论文位置需要的图/表来源chap3 方法UNet 结构图可用 draw.io 重画或截图 model.py 结构chap4 实验loss 曲线TensorBoard 导出或 matplotlib 重绘chap4 实验mIoU 对比训练日志里的验证指标chap4 实验分割可视化predict.ipynb 输出图表编号和正文引用要一致LaTeX 里用\label和\ref自动管理别手写编号。5.3 把训练结果写进论文的具体步骤先跑完训练把train.py输出的日志保存成 csv 或直接截图 TensorBoard。然后在 chap4 里用 pgfplots 或直接插图片的方式放 loss 曲线。mIoU 对比表用 booktabs 宏包三线表看起来更规范。\begin{table}[htbp] \centering \caption{不同方法在测试集上的 mIoU 对比} \begin{tabular}{lcc} \toprule 方法 mIoU 像素准确率 \\ \midrule UNet (本方法) 0.68 0.89 \\ FCN 0.61 0.85 \\ SegNet 0.63 0.86 \\ \bottomrule \end{tabular} \end{table}数据必须来自你自己的实验别直接抄资源里的数字评审老师一眼就能看出实验和论文对不上。5.4 复现实验的一个实用习惯我自己的习惯是每次改完超参数或数据增强先在train.ipynb里跑 5 个 epoch 看 loss 趋势确认没有 nan 或震荡再丢到train.py里跑完整训练。这样能省下大量等待时间。另外checkpoint 文件名带上时间戳和关键参数比如unet_lr1e4_bs4_ep100.pth过两周回头看还能对上号。从那以后我每次开新实验都强制走一遍「小跑验证 → 全量训练 → 日志归档」的流程翻车次数明显少了。希望帮到你。本文还有配套的精品资源点击获取