简介这是一份面向计算机相关专业学生与教师的遥感图像语义分割毕业设计完整资料基于Python与UNet网络实现适合作为毕设、课程设计或项目立项参考也便于初学者进阶学习。资源包共69个文件约46.93MB包含6个Python源码文件与3个Jupyter Notebook覆盖数据制作、模型搭建、训练与预测全流程另有32张png与6个svg图示、5个tex论文源文件及pdf论文、字体与参考文献等配套部署文档与全部数据资料结构完整。该项目为个人高分毕业设计已通过导师指导与答辩评审代码经测试可正常运行。已有189人学习下载。读者可据此掌握UNet在遥感图像分割中的网络结构、训练脚本与推理流程并参考论文写作与图表组织方式快速搭建自己的实验环境或在此基础上修改扩展功能。1. 遥感语义分割毕设资源从一份 95 分项目拆开看它到底能跑什么遥感图像语义分割这个方向每年毕业季都有人踩同一个坑论文里公式推导写得满满当当代码却跑不出第一张预测图。我手上这份「基于 PythonUNet 的遥感图像语义分割」毕设资源包恰好是一个已经答辩通过、评审 95 分的完整项目包含论文源码、部署文档和全部数据资料。它解决的不是UNet 是什么这种科普问题而是我拿到一份能跑的遥感分割工程怎么把它变成自己的毕设这个落地问题。适合计算机、人工智能、通信、自动化等专业的在校生也适合想快速搭一个遥感分割 demo 的从业者。下面我按实际拆包顺序把这份资源从结构、训练、推理到避坑完整走一遍。2. 拆包先看目录UNet-AerialImageSegmentation 的工程结构怎么读拿到压缩包别急着解压完就pip install先花十分钟把目录结构读明白能省掉后面一半的翻车时间。这份资源的顶层是UNet-AerialImageSegmentation-master里面同时躺着代码、论文 LaTeX 源文件和 Jupyter Notebook 三套东西很多人第一次打开会懵——到底从哪个入口进。2.1 代码目录与论文目录的分工先看代码侧。src/是核心里面model.py定义 UNet 网络结构data.py负责数据集加载与增强train.py是训练主循环cnn.py和utils.py分别是网络组件和工具函数__init__.py把src变成一个可导入的包。demo/目录下放着三个 Notebookcreate_dataset.ipynb做数据预处理train.ipynb走训练流程predict.ipynb做推理可视化。根目录还有两个 PowerShell 脚本start_jupyter.ps1和start_tensorboard.ps1分别用来一键启动 Jupyter 和 TensorBoard。论文侧是毕业论文/目录chap1.tex到chap5.tex对应五个章节Figures/放插图Bibs/放参考文献字体/是编译中文 LaTeX 需要的字体文件。这个结构说明作者是把代码和论文放在同一个工程里管理的好处是你改完代码可以直接在论文里更新实验数据坏处是路径容易混。目录/文件作用是否必须src/model.pyUNet 网络定义是src/data.py数据集与增强是src/train.py训练入口是demo/*.ipynb交互式流程建议毕业论文/*.tex论文源文件按需start_*.ps1环境启动脚本Windows 用2.2 环境依赖与启动脚本的读法start_jupyter.ps1和start_tensorboard.ps1是 Windows PowerShell 脚本内容通常是激活虚拟环境后拉起对应服务。我一般会先打开看一眼它引用的 Python 路径确认和自己机器上的解释器一致再决定是直接用还是手动敲命令。常见做法是建一个独立虚拟环境把依赖装进去避免污染全局。# 建虚拟环境并激活Windows 用 venvLinux/macOS 同理 python -m venv venv # Windows venv\Scripts\activate # Linux / macOS source venv/bin/activate # 安装核心依赖版本按你本机 CUDA 情况调整 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 pip install numpy opencv-python matplotlib tensorboard jupyter这段命令的逻辑是先隔离环境再装 PyTorch带 CUDA 118 的 wheel 源最后补齐数据处理和可视化依赖。参数上--index-url指向 PyTorch 官方 wheel 源比默认 PyPI 快且能拿到对应 CUDA 版本如果你没有 NVIDIA 显卡把cu118换成cpu即可。装完先python -c import torch; print(torch.cuda.is_available())验证一下返回True才说明 GPU 可用否则后面训练会默默跑在 CPU 上慢到怀疑人生。提示start_tensorboard.ps1依赖训练时写出的runs/日志目录没跑过训练直接启动会看到空面板别以为是脚本坏了。3. 数据管线与 UNet 前向create_dataset 到 model.py 的完整链路工程能跑通的关键在数据管线遥感图像分割尤其如此——影像尺寸大、类别不均衡、标注格式五花八门。这一章把从原始影像到网络输入的链路拆开再对照model.py看 UNet 的前向是怎么接上的。3.1 create_dataset.ipynb 里的切图与掩码对齐遥感影像动辄几千像素见方直接塞进网络显存扛不住所以第一步是切图。create_dataset.ipynb通常做三件事读取原始大图和对应掩码、按固定窗口滑窗切块、把切块存成训练用的图像-掩码对。这里最容易翻车的是图像和掩码的切分必须严格同步一旦错位训练 loss 会卡在一个诡异的值下不去。import cv2 import numpy as np import os def sliding_crop(img, mask, size256, stride128): 滑窗切图图像与掩码同步切分 h, w img.shape[:2] patches [] for y in range(0, h - size 1, stride): for x in range(0, w - size 1, stride): img_patch img[y:ysize, x:xsize] mask_patch mask[y:ysize, x:xsize] # 跳过全背景块缓解类别不均衡 if mask_patch.sum() 0: continue patches.append((img_patch, mask_patch)) return patches img cv2.imread(raw/image.tif) mask cv2.imread(raw/mask.png, cv2.IMREAD_GRAYSCALE) patches sliding_crop(img, mask, size256, stride128) os.makedirs(dataset/train, exist_okTrue) for i, (ip, mp) in enumerate(patches): cv2.imwrite(fdataset/train/img_{i}.png, ip) cv2.imwrite(fdataset/train/mask_{i}.png, mp)逻辑说明sliding_crop用size控制窗口边长、stride控制步长步长小于窗口就能产生重叠增加样本量。mask_patch.sum() 0这行是过滤全背景块遥感场景里背景占比往往超过七成不过滤的话模型会学成全预测背景也能拿高准确率。参数上size256是显存和感受野的折中stride128即 50% 重叠是常见起点显存紧张就把 size 降到 128。3.2 model.py 中 UNet 的编码器-解码器与跳跃连接model.py里的 UNet 是经典结构编码器逐层下采样提特征解码器逐层上采样恢复分辨率中间用跳跃连接把编码器的浅层特征拼到解码器对应层。遥感分割里跳跃连接尤其重要因为地物边界这种细节信息在深层特征里已经丢得差不多了。import torch import torch.nn as nn class DoubleConv(nn.Module): def __init__(self, in_ch, out_ch): super().__init__() self.conv nn.Sequential( nn.Conv2d(in_ch, out_ch, 3, padding1), nn.BatchNorm2d(out_ch), nn.ReLU(inplaceTrue), nn.Conv2d(out_ch, out_ch, 3, padding1), nn.BatchNorm2d(out_ch), nn.ReLU(inplaceTrue), ) def forward(self, x): return self.conv(x) class UNet(nn.Module): def __init__(self, in_ch3, n_classes2): super().__init__() self.down1 DoubleConv(in_ch, 64) self.down2 DoubleConv(64, 128) self.pool nn.MaxPool2d(2) self.up nn.Upsample(scale_factor2, modebilinear, align_cornersTrue) self.up_conv DoubleConv(128 64, 64) self.out nn.Conv2d(64, n_classes, 1) def forward(self, x): c1 self.down1(x) # 浅层特征保留边界 c2 self.down2(self.pool(c1)) u self.up(c2) u torch.cat([u, c1], dim1) # 跳跃连接 u self.up_conv(u) return self.out(u)逻辑说明DoubleConv是两次卷积BNReLU 的标准块UNet.forward里c1是编码器浅层输出c2是下采样后的深层输出torch.cat([u, c1], dim1)就是跳跃连接把上采样结果和浅层特征在通道维拼接。参数上n_classes按你的地物类别数改二分类前景/背景填 2多分类填实际类别数in_ch3对应 RGB 三通道如果输入是多光谱影像要改成实际波段数。这里给的是简化版完整工程里层数更多但拼接逻辑一致。注意跳跃连接拼接时通道数要对得上up_conv的输入通道是上采样输出通道加浅层通道改网络深度时这两个数要同步改否则会报维度不匹配。4. 训练与推理实操train.py 到 predict.ipynb 的参数怎么设数据管线和网络结构都通了接下来是真正跑起来。这一章把训练主循环、损失函数选择、推理可视化的关键参数讲清楚让你改几个数字就能适配自己的数据集。4.1 train.py 的训练循环与损失函数选择train.py的主循环是标准的前向-算损失-反向-更新四步。遥感分割的难点在类别不均衡所以损失函数的选择比网络结构更影响最终效果。常见做法是交叉熵和 Dice 损失按权重相加交叉熵管像素级分类Dice 管整体区域重叠度。import torch import torch.nn as nn class DiceLoss(nn.Module): def __init__(self, smooth1.0): super().__init__() self.smooth smooth def forward(self, logits, targets): probs torch.sigmoid(logits) probs probs.view(-1) targets targets.view(-1).float() inter (probs * targets).sum() dice (2 * inter self.smooth) / (probs.sum() targets.sum() self.smooth) return 1 - dice # 组合损失交叉熵 Dice ce nn.CrossEntropyLoss() dice DiceLoss() def criterion(logits, targets): return ce(logits, targets) dice(logits, targets)逻辑说明DiceLoss用smooth防止分母为零1 - dice把相似度转成损失。组合损失里交叉熵提供稳定梯度Dice 直接优化重叠度两者相加是遥感分割的常见配方。参数上smooth1.0是经验值样本极少时可以调大两个损失的权重默认各占一半如果发现边界糊可以给 Dice 加权到 0.7 左右。训练超参方面学习率我一般从1e-3起步配 Adambatch size 按显存给到 8 或 16epoch 先跑 50 看 loss 曲线再决定要不要加。train.ipynb里通常有这些参数的集中配置改之前先备份一份原始值。4.2 predict.ipynb 的推理可视化与指标计算训练完模型要验证效果predict.ipynb负责加载权重、跑推理、把预测掩码叠到原图上。这一步别只看图好不好看要算指标。遥感分割常用 mIoU 和像素准确率前者对类别不均衡更敏感更能反映真实水平。import numpy as np import torch def compute_miou(pred, target, n_classes): pred/target 为 HxW 的整数标签图 ious [] for c in range(n_classes): p (pred c) t (target c) inter (p t).sum() union (p | t).sum() if union 0: continue ious.append(inter / union) return np.mean(ious) model.eval() with torch.no_grad(): logits model(img_tensor) pred logits.argmax(dim1).squeeze().cpu().numpy() miou compute_miou(pred, mask_np, n_classes2) print(fmIoU: {miou:.4f})逻辑说明compute_miou逐类算交并比再取平均union 0的类别跳过该类别在图中没出现。model.eval()和torch.no_grad()是推理必备前者关掉 BN 和 Dropout 的训练行为后者省显存。参数上n_classes要和训练时一致argmax(dim1)取通道维最大值作为预测类别。指标算完再叠图看两者对不上就说明可视化或标签映射有问题。提示推理时输入图像的归一化方式必须和训练时完全一致训练用了 ImageNet 均值方差推理也得用同一套否则预测结果会整体偏移。5. 避坑与常见问题这份资源跑不起来时先查这几条资源包再完整换台机器、换个数据集照样可能翻车。下面这几条是我拆这类工程时反复遇到的按现象→原因→解决列出来照着排查能省不少时间。5.1 路径与编码类问题现象运行train.py报FileNotFoundError提示找不到数据集目录。原因工程里数据路径多半是相对路径且写死了作者本机的目录结构你解压到别的位置就对不上。解决打开data.py或train.py把所有数据路径改成绝对路径或基于os.path.dirname(__file__)的相对路径别硬编码。现象Windows 下读中文路径的图片报编码错误。原因cv2.imread对中文路径支持不好底层用的还是系统编码。解决用cv2.imdecode(np.fromfile(path, dtypenp.uint8), cv2.IMREAD_COLOR)替代imread写图同理用cv2.imencode加tofile。5.2 显存与训练类问题现象训练一开始就CUDA out of memory。原因切图尺寸太大或 batch size 太高显存装不下。解决先把 batch size 降到 2 试还不行就把切图 size 从 256 降到 128或者用梯度累积模拟大 batch。现象loss 一直不降或者降到某个值就卡住。原因常见是学习率太大导致震荡或者标签映射错了比如掩码是 0/255 而网络期望 0/1。解决学习率降到1e-4再试检查掩码唯一值用np.unique(mask)确认如果是 0/255 就除以 255 或做映射。5.3 环境与依赖类问题现象import torch成功但torch.cuda.is_available()返回 False。原因装的是 CPU 版 PyTorch或者 CUDA 版本和驱动不匹配。解决卸载重装对应 CUDA 版本的 wheel用nvidia-smi看驱动支持的 CUDA 上限别超过它。现象TensorBoard 启动后看不到曲线。原因训练时没写日志或者日志目录和启动命令指定的目录不一致。解决确认train.py里有SummaryWriter写入启动时--logdir指向实际日志目录。注意这份资源的论文 LaTeX 源文件编译需要中文字体字体/目录别删否则chap*.tex编译会报缺字。6. 进阶用法把这份 UNet 工程改成你自己的遥感分割项目跑通原工程只是起点毕设要拿高分得有自己的东西。这一章讲怎么在现有代码上做增量改进以及怎么验证改进真的有效。6.1 换数据集与类别数的完整改动清单换成自己的数据集改动集中在四个地方data.py里的数据读取路径和类别数、model.py里 UNet 的n_classes、train.py里的损失函数类别权重、predict.ipynb里的可视化配色。类别数从 2 改成 N 时CrossEntropyLoss不用改但DiceLoss如果是二分类实现要改成多分类版本或者对每个类别单独算再平均。# 多分类 Dice 的常见写法 def multiclass_dice(logits, targets, n_classes): probs torch.softmax(logits, dim1) dice 0.0 for c in range(n_classes): p probs[:, c] t (targets c).float() inter (p * t).sum() dice (2 * inter 1e-6) / (p.sum() t.sum() 1e-6) return 1 - dice / n_classes逻辑说明多分类下先softmax得到每类概率再逐类算 Dice 取平均。参数上1e-6是平滑项防止空类别导致除零。改完记得同步改n_classes三处不一致是新手最常见的报错来源。6.2 验证改进是否有效的对照实验设计改完网络或损失别急着写进论文先做对照实验。固定随机种子、固定数据划分、固定训练轮数只改你要验证的那一个变量跑三组取平均。指标至少报 mIoU 和像素准确率两个单看一个容易被误导——比如全预测背景在极不均衡数据上准确率能到 90%但 mIoU 接近 0。实验组改动点mIoU像素准确率baseline原始 UNet待填待填exp1加 Dice 损失待填待填exp2换 backbone待填待填表格里的数字必须是你自己跑出来的别抄论文里的。跑完把 TensorBoard 曲线截图存好答辩时被问你怎么证明改进有效直接甩图。从那以后我每次拿到这类毕设工程都强制先跑通原始 baseline 再动任何一行代码确认基线指标能复现才敢往上加东西。希望这份拆解能帮你少走几个弯路顺利把毕设跑出来。本文还有配套的精品资源点击获取