恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

DeepLabv3+航拍语义分割实战:编码器-解码器与骨干网络替换

  • 首页
  • 资讯中心
  • /
  • DeepLabv3+航拍语义分割实战:编码器-解码器与骨干网络替换

相关资讯

基于Hadoop的电商手机推荐系统毕业设计实战:从架构到实现 2026/10/5 11:10:58
JSP+MySQL野生动物保护网站源码实战:环境搭建、功能拆解与避坑指南 2026/10/5 11:05:57
实战KNN算法:从数据可视化到模型预测全流程解析 2026/10/5 11:05:57

最新资讯

时空Transformer船舶轨迹预测:从AIS数据处理到海上冲突预警实战
AI网关实战:多模型统一接入与Token成本治理
AI智能体安全防线:从提示词注入到自主入侵的防护实战
免费AI视频编辑工具实战:从素材到成片的专业级工作流
拆解六款开源RAG,构建可复用的自研检索增强生成蓝图
A+B模式实战:大模型+ComfyUI高效生成专业PPT

今日推荐

第26课:OpenClaw|日志审计与问题诊断:把日志链路改到 TaoToken 的排查清单
YOLOv5 OBB旋转框训练实战:从DOTA数据准备到调参避坑全流程
Zeron 终端、Worktree 与 Diff 面板:像 IDE 一样查看并驱动你的代码变更

本周热门

MR25H40CDF + PIC18F65K40:工业记录仪高可靠存储实战
基于STM32的数控恒压恒流电源设计:从硬件到PID调参全解析
LT9211 MIPI重定时器原理与双路扇出实战指南

本月精选

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)

DeepLabv3+航拍语义分割实战:编码器-解码器与骨干网络替换

发布时间:2026/10/5 11:10:58
DeepLabv3+航拍语义分割实战:编码器-解码器与骨干网络替换 简介基于DeepLabv3的Python高分辨率航拍图像语义分割项目面向计算机视觉方向毕业设计、遥感图像分析入门及语义分割方法对比研究场景。项目以DeepLabv3为整体框架同时整合ResNet、HRNet、Swin、Twins、BiSeNetV2、BEiT等多种backbone实现能够直接对比不同特征提取网络在高分辨率航拍影像上的分割精度与效果也便于针对特定场景替换或改进网络结构。压缩包共184个文件以95个Python脚本和84个pyc编译文件为主体另含3个Jupyter Notebook实验记录、1个说明文档和1个README整体仅477KB文件结构简洁适合直接阅读源码并快速复现。notebook区分离线输出与在线运行两种流程可辅助理解模型在不同条件下的调试方法代码按backbone模块化划分便于在此基础上扩展训练流程、接入自有航拍数据集或进行消融实验。目前已有204人学习下载对于需要以DeepLabv3为基线完成毕业设计课题、撰写技术文档或开展遥感语义分割对比实验的读者是一份轻量而完整的参考资料。1. 航拍图像语义分割这块硬骨头DeepLabv3 为什么还能打做高分辨率航拍图像的语义分割最烦的不是模型跑不起来而是跑起来了效果一塌糊涂小目标糊成一团、地物边缘锯齿严重、显存动不动就爆。这个基于 Python 的 DeepLabv3 毕业设计项目把编码器-解码器结构和空洞卷积的思路完整落到了代码里我拆完第一感觉是——它把「高分辨率输入」这个最磨人的约束直接当成了设计前提来处理。项目自带基线训练 Notebook、在线/离线推理脚本和六个骨干网络定义文件适合两类人一是拿它做毕业设计、需要完整跑通训练到评估全流程的同学二是做遥感影像分析、想快速对比不同 backbone 效果的从业者。整份资源不是那种只给个 ipynb 糊弄事的README 里把数据准备、训练入口和常见报错都交代了属于能照着复现的那一类。2. DeepLabv3 架构拆解ASPP 与编码器-解码器的设计边界2.1 编码器-解码器结构到底解决了什么问题DeepLabv3 在语义分割里是个「老但稳」的选项尤其适合航拍这类目标尺度跨度大的场景。先看它的骨架编码器部分用带空洞卷积的骨干网络提取多尺度特征解码器部分把低层细节特征和高层语义特征融合从而恢复目标边缘。航拍图像里一栋楼的屋顶可能占几百个像素一辆车可能只占十几个像素这种尺度差异单靠普通卷积堆叠很难同时照顾到。项目里deeplabv3plus_baseline_offline_out.ipynb这个 Notebook 就是标准的编码器-解码器实现我在里面看到它对低层特征的处理方式比较到位没有直接把 stride16 的特征图上采样回原尺寸而是先做 1x1 卷积降通道再与上采样后的高层特征 concat。这一步很关键因为低层特征通道数通常很大ResNet 里是 256 起步直接 concat 会带来大量冗余计算和显存开销。对应到代码层面最核心的 ASPP 模块长这样import torch import torch.nn as nn import torch.nn.functional as F class ASPP(nn.Module): def __init__(self, in_channels, out_channels256, rates(6, 12, 18)): super(ASPP, self).__init__() # 1x1 卷积分支保持原尺度感受野 self.conv1 nn.Conv2d(in_channels, out_channels, 1, biasFalse) self.bn1 nn.BatchNorm2d(out_channels) # 三个不同空洞率的 3x3 卷积分支 self.convs nn.ModuleList() for rate in rates: conv nn.Conv2d(in_channels, out_channels, 3, paddingrate, dilationrate, biasFalse) bn nn.BatchNorm2d(out_channels) self.convs.append(nn.Sequential(conv, bn)) # 全局平均池化分支捕获全局上下文 self.gap nn.AdaptiveAvgPool2d(1) self.gap_conv nn.Conv2d(in_channels, out_channels, 1, biasFalse) self.gap_bn nn.BatchNorm2d(out_channels) # 汇合后的 1x1 卷积 self.fuse nn.Sequential( nn.Conv2d(out_channels * (2 len(rates)), out_channels, 1, biasFalse), nn.BatchNorm2d(out_channels), nn.ReLU(inplaceTrue) ) def forward(self, x): h, w x.size(2), x.size(3) # 各分支独立计算 feat [self.bn1(self.conv1(x))] for conv_bn in self.convs: feat.append(conv_bn(x)) # 全局分支需要上采样回原尺寸 gap self.gap_bn(self.gap_conv(self.gap(x))) gap F.interpolate(gap, size(h, w), modebilinear, align_cornersFalse) feat.append(gap) # 所有分支 concat 后融合 x torch.cat(feat, dim1) return self.fuse(x)这段代码里rates(6, 12, 18)是三个空洞卷积的膨胀率航拍图建议按输入分辨率调整如果输入是 512x512这三个值够用如果输入拉到 768 或 1024我一般会把 rates 换成(12, 24, 36)否则感受野覆盖不到大尺度地物。align_cornersFalse这个参数在航拍分割里尤其重要因为航拍图的地物边界不是规整网格对齐方式选错会导致边缘错位半像素后处理时很别扭。2.2 解码器里的细节为什么低层特征要降维再融合解码器部分有一个经常被忽略的设计细节。DeepLabv3 原论文里对低层特征先做 1x1 卷积把通道数压到 48再与高层特征 concat。这个「48」不是拍脑袋定的而是实验出来的平衡点通道压得太低会丢掉边缘纹理信息压得不够又会让高层语义特征被低层噪声淹没。项目里的骨干网络文件如resnet.py、hrnet.py都保留了完整的 stage 输出方便在解码器里取不同层级的特征。我拆hrnet.py的时候注意到它输出的多分辨率特征比 ResNet 更适合航拍场景因为 HRNet 始终保持高分辨率分支对小目标的响应更敏感。如果你的显卡显存足够建议优先试 HRNet 做编码器显存吃紧就退回 ResNet50。解码器融合的常见写法是class DeepLabV3PlusDecoder(nn.Module): def __init__(self, low_level_channels256, high_level_channels256, out_channels256): super(DeepLabV3PlusDecoder, self).__init__() # 低层特征降维到 48 通道保留细节同时控制显存 self.low_level_proj nn.Sequential( nn.Conv2d(low_level_channels, 48, 1, biasFalse), nn.BatchNorm2d(48), nn.ReLU(inplaceTrue) ) self.conv1 nn.Sequential( nn.Conv2d(48 high_level_channels, out_channels, 3, padding1, biasFalse), nn.BatchNorm2d(out_channels), nn.ReLU(inplaceTrue) ) self.conv2 nn.Sequential( nn.Conv2d(out_channels, out_channels, 3, padding1, biasFalse), nn.BatchNorm2d(out_channels), nn.ReLU(inplaceTrue) ) def forward(self, low_level_feat, high_level_feat): # high_level_feat 已经是 stride16 的特征 high F.interpolate(high_level_feat, sizelow_level_feat.size()[2:], modebilinear, align_cornersFalse) low self.low_level_proj(low_level_feat) x torch.cat([low, high], dim1) x self.conv1(x) return self.conv2(x)航拍数据里常见的地物边界比如道路边缘和建筑轮廓非常依赖低层特征这里把低层通道压到 48 而不是 128 或 256目的就是让高层语义信息在融合时占据主导地位。实际操作里我遇到过一个问题如果骨干网络输出通道数和代码里预设不一致比如把 ResNet 换成 Swin Transformer 后通道数变成 96 或 192会直接报维度不匹配的错。解决方式是在代码里加一层 1x1 卷积做通道适配或者干脆改low_level_channels的预设值。3. 六个骨干网络文件怎么选从 ResNet 到 Swin 的替换套路3.1 各骨干网络的定位与适用边界项目里提供了resnet.py、hrnet.py、swin.py、twins.py、bisenetv2.py、beit.py六个骨干网络定义文件这个设计很聪明——同一个 DeepLabv3 解码器换编码器就是一组对比实验正好满足毕业设计里「对比不同模型性能」的常见需求。我先逐个说清楚定位骨干网络核心特点航拍场景适配度显存占用ResNet经典残差结构预训练权重最好找中规中矩适合做 baseline低HRNet全程保持高分辨率特征对小目标友好边缘细节好中高Swin Transformer窗口自注意力全局建模强大尺度地物效果好但训练收敛慢高Twins局部-全局注意力混合速度与精度平衡中BiSeNetV2双向通道设计主打实时推理速度快适合大图快速预测低BEiT预训练特征强迁移效果好数据量少时表现好高选型逻辑很简单显存 8G 以下无脑 ResNet50 起步显存 12G 以上优先试 HRNet 或 Swin如果要做大图推理且对速度有要求BiSeNetV2 是唯一能在单张 1080Ti 上跑 1024x1024 不爆显存的选择。这个对比本身就可以写进论文的实验章节省得自己再造轮子。3.2 骨干网络替换的实操套路替换骨干网络最怕的是改了编码器、解码器没跟着改导致通道数对不上。项目里这几个文件命名很规范每个文件都暴露了标准的输出接口——返回一个 dict包含low_level和out两个特征。我拆swin.py的时候发现它对 torch 版本有要求torch.einsum的调用方式在 1.12 和 2.0 之间行为略有差异建议直接用 Python 3.8 torch 1.13 或 2.0 的常见组合。骨干网络替换的核心代码逻辑是这样def build_backbone(name, pretrainedTrue): 按名称构建骨干网络返回统一格式的特征接口 if name resnet50: from resnet import resnet50 backbone resnet50(pretrainedpretrained) backbone.out_channels 2048 # stride16 输出通道 backbone.low_level_channels 256 # stride4 输出通道 elif name hrnet: from hrnet import get_hrnet backbone get_hrnet(pretrainedpretrained) backbone.out_channels 720 backbone.low_level_channels 256 elif name swin: from swin import SwinTransformer backbone SwinTransformer(embed_dim96, depths[2, 2, 6, 2]) backbone.out_channels 768 # stage4 输出通道 backbone.low_level_channels 192 # stage2 输出通道 return backbone这里最关键的是最后两行属性赋值。DeepLabv3 解码器在构建时需要知道低层特征和高层特征的通道数而不同骨干网络的通道数差异很大——ResNet 的低层是 256、高层是 2048Swin 的低层是 192、高层是 768。我见过不少人直接换 backbone 后报size mismatch错误十有八九是没在build_backbone里同步更新这两个值。另外注意swin.py里的depths参数它控制每个 stage 的 Transformer block 数量。[2, 2, 6, 2]是 Swin-Tiny 的配置显存紧张就改成[2, 2, 2, 2]代价是精度会掉 1-2 个点。我一般会先在 ResNet 上把整个流程调通再切 Swin 做精度实验这样排错范围小很多。4. 把 Notebook 跑通训练、断点续训与离线推理的完整流程4.1 数据准备与训练入口别在 Dataset 上省时间README.md里写的训练流程比较精简我补一个自己常用的做法。航拍数据集最常见的格式是原始大图 对应标签图每个图可能 5000x5000 甚至更大直接整图送进网络没有任何显卡吃得消。常见做法是先做滑窗裁剪把大图切成 512x512 或 768x768 的小块再按 8:1:1 划分训练、验证、测试集。切图这一步我建议注意重叠率。如果切 512x512 的图步长用 256 而不是 512这样相邻 patch 之间有 50% 重叠能有效避免目标正好被切在 patch 边界上导致标签丢失。代价是训练样本量增加约一倍训练时间变长但对于航拍分割来说这钱花得值。训练入口在deeplabv3plus_baseline_offline_out.ipynb里核心训练循环可以提炼成这样# 训练循环核心逻辑简化版 model.train() for epoch in range(start_epoch, epochs): for images, masks in train_loader: images images.cuda() masks masks.long().cuda() outputs model(images) loss criterion(outputs, masks) # 默认用 CrossEntropyLoss但要配 ignore_index optimizer.zero_grad() loss.backward() optimizer.step() # 每 50 个 iteration 打印一次 loss 和 lr if step % 50 0: cur_lr optimizer.param_groups[0][lr] print(fEpoch {epoch} Step {step} | Loss {loss.item():.4f} | LR {cur_lr:.1e})criterion这里有个容易被忽略的细节航拍标签图里通常有255这个值代表 ignore 区域比如图像拼接缝、云遮挡必须设置CrossEntropyLoss(ignore_index255)否则 loss 会被这些无意义像素带偏。我见过有人用默认的 CrossEntropyLoss 训了一晚上mIoU 死活上不去最后发现是 ignore 没设——这个坑在第 5 章详细说。4.2 评估脚本与离线推理两个 Notebook 的定位差异项目里deeplabv3plus_baseline_offline_out.ipynb和sam_arch_offline_out.ipynb看起来都是离线推理但定位不同。前者是单模型推理加载训练好的权重对测试集做预测并计算指标后者是架构对比实验用的可以一次加载多个不同 backbone 的模型输出同一张图的对比分割结果。评估指标建议至少算三个mIoU像素级交并比均值、F1 Score尤其关注前景类、OA整体精度。mIoU 是语义分割论文里的标配但航拍场景里地物类别极不平衡——比如一个数据集中植被占 60%、建筑占 25%、道路占 10%、车辆占 5%mIoU 会被植被这类大类拉高看不出小类效果。所以我一般额外打印每个类别的 IoU 表格看看到底是哪几类拉了后腿。评估代码的核心逻辑# 评估 mIoU 的简化实现 def compute_miou(pred_masks, gt_masks, num_classes8): ious [] for cls_id in range(num_classes): pred_cls (pred_masks cls_id) gt_cls (gt_masks cls_id) intersection (pred_cls gt_cls).sum().item() union (pred_cls | gt_cls).sum().item() if union 0: ious.append(float(nan)) # 该类别在 GT 中不存在 else: ious.append(intersection / union) return ious # 推理时注意模型输出是 logits需要 argmax 转为类别 ID with torch.no_grad(): logits model(batched_imgs) pred torch.argmax(logits, dim1).cpu().numpy()num_classes8这个参数要看你的数据集而定航拍常见的数据集类别数从 6 到 15 不等。union 为 0 时返回 nan 是常见做法但最后统计平均 mIoU 时要用np.nanmean跳过这些类否则平均值会被算成 nan。另一个坑是预测结果和标签的类别 ID 顺序必须严格一一对应如果训练时改了类别顺序评估时没改回来mIoU 会直接掉 20 个点以上。5. 语义分割避坑清单高分辨率航拍影像最容易翻车的五个地方5.1 显存溢出换小输入不如换策略现象训练刚开始没几个 step 就报CUDA out of memory显存直接吃满。原因航拍原图分辨率太高直接整图输入必然爆显存或者切图后 batch size 设太大backbone 输出特征图叠加了 ASPP 的多分支显存占用比想象中大得多。解决优先把输入尺寸从 768x768 降到 512x512batch size 降到 4 甚至 2其次是开梯度累积每 4 个 batch 更新一次参数再不够就换轻量骨干如 BiSeNetV2。我自己的习惯是先用 512x512 batch 4 跑通确认 loss 下降趋势正常后再加大输入尺寸。5.2 loss 不下降但看着代码没问题ignore_index 缺失现象训练 loss 一直在 3.4 附近震荡降不下去或者 loss 在降但验证 mIoU 纹丝不动。原因标签图里大量255像素被当成普通类参与 loss 计算模型在疯狂学习预测这些无效区域还有一种可能是标签类别从 1 开始编号而不是从 0 开始导致类别 ID 错位。解决训练前先统计标签图的像素类别分布确认255的比例在CrossEntropyLoss里显式设置ignore_index255。如果类别是从 1 开始需要先把所有标签减 1让类别 ID 从 0 开始。这一步检查只需两行代码但能省一整晚。5.3 验证 mIoU 高但查看预测图边缘破碎解码器融合细节出了问题现象mIoU 看着有 78%但把预测图拉大看建筑边缘锯齿严重道路断成一截截。原因解码器里低层特征和高层特征上采样对齐方式不对或者骨干网络的stride输出与解码器假设不一致比如用了 stride8 的 backbone但解码器默认 stride16。解决统一用align_cornersFalse做所有上采样打印 backbone 输出特征图的尺寸确认和decoder.forward的预期一致——如果 backbone 输出是输入尺寸的 1/8那解码器里的 interpolate 目标尺寸也要跟着调整不能死等 1/16。这问题我在换 HRNet 时踩过HRNet 的输出 stride 和 ResNet 不一样不改解码器就是锯齿。5.4 加载预训练权重报错key 名称不匹配现象load_state_dict报Missing key(s) and unexpected key(s)权重加载失败。原因项目里的骨干网络文件可能和官方 torchvision 预训练权重的命名不完全一致常见的是conv1.weight对应不上的情况还有分类头fc.weight是多余的。解决加载时设strictFalse把不匹配层打印出来人工核对如果只是分类头不匹配直接忽略即可。我每次换骨干网络都要先跑一次load_state_dict检查确认 backbone 主干层全部加载成功再开始训练避免带着随机初始化的 backbone 训半天还不自知。5.5 数据增强把标签搞坏了几何变换要同步现象训练集 mIoU 高到离谱验证集 mIoU 奇低明显是过拟合但增强也加了。原因用的数据增强库对图像和标签分开处理——比如随机旋转时图像转了 30 度标签转了 45 度或者随机翻转只翻了图像没翻标签。解决用专门支持「同步变换」的增强库或者在自定义 Dataset 里把图像和标签拼成一个四通道数组一起变换变换完再拆开。项目里如果自己写了train_transforms务必检查每个 transform 是否同时接收image和mask两个参数。6. 高分辨率航拍推理的验证技巧滑窗预测与 TTA毕业设计答辩的时候光交一个 mIoU 数字是不够的评委会看可视化结果——预测图叠在原图上是否边界对齐、小目标是否清晰。这一节分享一个我最常用的高分辨率推理验证技巧滑窗重叠预测 多尺度 TTA两者叠加能稳定提升 1-3 个 mIoU 点而且代码只要几十行。滑窗预测的核心思路是推理时用 512x512 的窗口在大图上滑动步长取 256 让相邻窗口有重叠每个像素的预测结果取多个窗口的平均概率再 argmax。这样做的好处是窗口边缘的预测不再孤零零重叠区域的概率被平均后更稳定。配合多尺度 TTA——把每张测试图缩放成 0.75、1.0、1.25 三个尺度分别预测再把概率图插值回原尺寸取平均——基本能达到单模型 简单后处理的精度上限。def slide_predict(model, image, window512, stride256, scales(0.75, 1.0), num_classes8): 滑窗 多尺度预测返回类别 ID 图 h, w image.shape[:2] # 概率累积器 prob_acc np.zeros((h, w, num_classes), dtypenp.float32) cnt np.zeros((h, w, 1), dtypenp.float32) for scale in scales: img_scaled cv2.resize(image, (int(w * scale), int(h * scale))) H, W img_scaled.shape[:2] for y in range(0, H - window 1, stride): for x in range(0, W - window 1, stride): patch img_scaled[y:y window, x:x window] # 归一化并转成 tensor tensor torch.from_numpy(patch).permute(2, 0, 1).float().cuda().unsqueeze(0) with torch.no_grad(): # 原始概率和窗口坐标对应在原图的位置 prob torch.softmax(model(tensor), dim1).cpu().numpy() # (1, C, 512, 512) prob prob[0].transpose(1, 2, 0) # (512, 512, C) # 将概率写回原图坐标除以 scale 映射回去 x0, y0 int(round(x / scale)), int(round(y / scale)) x1, y1 x0 window, y0 window prob_acc[y0:y1, x0:x1] prob[:min(window, h - y0), :min(window, w - x0)] cnt[y0:y1, x0:x1] 1 prob_acc / np.maximum(cnt, 1) # 被覆盖次数至少为 1 return np.argmax(prob_acc, axis2)这段代码里有三个参数值得注意stride256决定了重叠率越大精度越高但推理次数也越多scales的尺度列表会影响 TTA 效果航拍图像我用(0.75, 1.0, 1.25)比(0.5, 1.0, 1.5)效果好因为后者的最小尺度放得太大小目标直接糊没了cnt计数器的存在是为了处理图像边缘处窗口覆盖不足的情况没有它边缘像素的概率会被低估。这个技巧在答辩时很加分——你可以直接展示同一张航拍原图对比普通整图预测和滑窗TTA 预测的结果边界清晰度和目标完整性差距一眼可见。我从那以后每次做航拍分割推理都强制走一遍滑窗流程宁可推理慢个几分钟也不直接整图上模型。真心希望这个项目能帮你把毕业设计的实验部分撑起来把该踩的坑提前避开。本文还有配套的精品资源点击获取

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号