双支FCN-8s提升高分遥感森林分类精度的方法与实战
发布时间:2026/9/30 3:53:38来源:尧图网络
简介这份PDF文档是一篇面向遥感图像分析、森林资源监测及深度学习应用等方向的专业文献适合高校研究生、科研人员以及从事林地分类与生态遥感的一线工程师阅读。内容围绕一种改进的高空间分辨率遥感影像森林类型精细分类方法展开重点介绍双支FCN-8s网络结构如何通过空间与频谱两个分支并行提取特征并将两路信息融合用于森林树种和类别的细粒度识别。文中针对高分辨率影像地物细节丰富、类别边界复杂、样本标注成本高等问题给出了网络设计与训练层面的解决思路涉及数据预处理、特征提取、特征融合与分类输出等关键环节可作为方法选型、论文写作或模型复现时的参考依据。该PDF同时覆盖深度学习、数据分析与专业指导等应用视角能帮助读者在遥感分类网络设计、实验对比和文献综述中找到明确抓手。资源包共1个PDF文件大小8.15MB轻量便于离线查阅。目前已有242人学习下载对于需要快速把握双支FCN-8s方法脉络和精细分类技术要点的读者具有较高参考价值。1. 双支FCN-8s把高分辨率遥感影像里的森林类型分得更细干遥感分类的人应该都有这种体会一张0.5米分辨率的影像里同一片林子的树冠纹理、阴影走向、光谱反射率差异极大单靠像元级分类器很容易把相邻的落叶松和桦树混成一团。FCN-8s这个老牌语义分割网络本身是好的但直接拿来跑高分影像的森林类型分类精度往往卡在某个瓶颈上不去。我拆这份论文资源时最惊讶的一点是作者没有堆更深的网络而是把FCN-8s拆成双支结构空间特征一支、光谱特征一支再把两支特征融合起来——就这么一个改动分类准确率和对边界区域的判别能力都明显提升。这份PDF完整给出了方法设计、网络结构细节和实验流程适合正在做遥感影像分类、森林资源调查相关课题的研究生和工程师尤其是被类别不平衡和地物边界模糊折磨过的人。下面我把这篇论文里能直接落地的内容拆开讲。2. 双支结构到底改了FCN-8s的什么两大特征流的分工逻辑2.1 从FCN-8s到双支先搞清楚原始结构为什么不够用FCN-8s是FCN家族里融合了三个不同层级特征图的版本。VGG-16作为骨干conv3、conv4、conv5三层的特征图分别被上采样8倍、16倍、32倍然后相加融合。相比FCN-32s那种只在最后做一次上采样的做法FCN-8s保留了不少浅层细节所以它天然适合做像素级分类。但这里有个实际问题高分遥感影像的波段数多常见4波段或8波段地物的光谱曲线差异有时比空间纹理更容易区分树种比如阔叶林和针叶林在近红外波段的反射率差距明显但在可见光波段看起来差不多。而标准FCN-8s的主干网络对光谱维度的利用是被动式的——它不管输入有几个波段都是直接卷积网络自己折腾了半天也未必能学到波段间的组合特征。双支FCN-8s的做法是把这个隐式学习过程显式拆开。一支叫空间流输入原始影像负责提取纹理、边缘、几何形状信息另一支叫光谱流对同一幅影像做强化的光谱特征提取。光谱流可以是手工设计的光谱指数特征通道拼接进去也可以是小规模卷积网络对多波段数据做专门编码。两个分支最后在某个中间层或者解码器的某个位置融合再送入后续的卷积和上采样模块完成分类。这种结构设计背后有一个很实用的直觉空间特征和光谱特征在语义层面是不同的东西混在一起让网络自己学容易互相干扰分开提取再融合每个分支的网络复杂度可以做得比较轻。实际上双支结构的参数量不一定比原始FCN-8s大多少但在小样本量的遥感场景下更容易收敛因为每个分支要学的东西更单纯。2.2 双支融合的位置和方式早融合与晚融合的取舍论文里双支网络的融合位置是有讲究的。如果融合太早光谱特征还没被充分编码就被空间卷积稀释了融合太晚两支特征已经各自定型再融合只是简单叠加交互不够。常见的做法有两类作者采用的是偏晚融合的方案我复现时也是这么处理的在解码器倒数第二层把空间流特征图和光谱流特征图在通道维度上拼接再接一个 1×1 卷积把通道数压到分类类别数。1×1卷积在这里起的作用是让网络自己学习两支特征在哪些通道上更应该被信任。我在自己数据集上验证过直接用相加融合的效果不如拼接1×1卷积因为相加隐含了两支特征同等重要的假设而在某些林地场景里空间线索占主导另一些场景里光谱线索更可靠权重应该自适应调整。如果是用PyTorch搭建双支融合这一块的核心代码大致长这样import torch import torch.nn as nn class DualBranchFCN8s(nn.Module): def __init__(self, n_channels, n_classes, fusion_modeconcat): super().__init__() # 空间分支带空洞卷积的轻量编码器 self.spatial_branch nn.Sequential( nn.Conv2d(n_channels, 64, 3, padding2, dilation2), nn.BatchNorm2d(64), nn.ReLU(inplaceTrue), nn.Conv2d(64, 128, 3, padding4, dilation4), nn.BatchNorm2d(128), nn.ReLU(inplaceTrue), ) # 光谱分支逐波段独立编码后融合强化波段差异 self.spectral_branch nn.Sequential( nn.Conv2d(n_channels, 32, 1), nn.ReLU(inplaceTrue), nn.Conv2d(32, 128, 3, padding1), nn.BatchNorm2d(128), nn.ReLU(inplaceTrue), ) self.fusion_mode fusion_mode if fusion_mode concat: self.fusion nn.Conv2d(256, 128, kernel_size1) else: self.fusion nn.Conv2d(128, 128, kernel_size1) # 最后接上采样和分类头 self.classifier nn.Conv2d(128, n_classes, kernel_size1) def forward(self, x): spatial_feat self.spatial_branch(x) spectral_feat self.spectral_branch(x) if self.fusion_mode concat: fused torch.cat([spatial_feat, spectral_feat], dim1) else: fused spatial_feat spectral_feat fused self.fusion(fused) return self.classifier(fused)这段代码里有两个细节值得注意。第一空间分支的卷积用的是膨胀率2和4的空洞卷积这样做是为了在不缩小特征图分辨率的前提下扩大感受野对高分影像的大树冠特别有用——一棵成年树在0.5米分辨率影像上往往有好几十个像素感受野不够时一个树冠会被拆成好几块分类。第二光谱分支的第一层是1×1卷积它先把每个波段的原始信息分别映射到高维空间然后再做3×3卷积提取波段间的组合特征。这个设计的另一个实际好处是可以用分组卷积来实现每个波段一组显存占用会小很多。2.3 融合通道数的经验值和调参方向通道数的设定上论文资源和一般经验数值接近空间支输出128维光谱支输出128维拼接后256维。如果你要复现建议从6464的组合起步而不是直接上128128尤其在显存有限或者训练数据量不大的时候。小通道数能显著降低过拟合代价是分类精细度下降。三个可控参数对结果的影响最大光谱支的1×1卷积输出通道数、两个分支dropout率、融合后分类头之前的卷积层数。我的调参经验是光谱支1×1卷积输出通道设成输入的1.5到2倍效果较好dropout设在0.3到0.5之间因为遥感样本量通常不大分类头之前最多加一层额外的3×3卷积加多了会稀释已经融合好的特征。另外如果你使用的是支持多尺度的数据WorldView、QuickBird这类0.5米级影像可以在输入侧加一个3×3卷积做快速下采样把分辨率降到原图的四分之一再送进两个分支很多情况下精度只损失不到1个百分点训练速度翻倍。3. 把遥感影像变成能训练的数据切片、标签与波段处理3.1 影像切片的大小和步长怎么定高分辨率遥感影像一般是几千乘几千像素的大图直接送进网络训练不现实。常见做法是切成固定大小的patch搭配重叠步长。这里的切片参数直接决定样本量和边界切损问题。论文采用的方案是256×256像素大小、128像素步长即50%重叠。这个参数组合是遥感语义分割里比较稳妥的起点。切片不是单纯地用窗口去裁有两点需要注意。首先步长如果太小重叠区域太多相邻patch高度相似模型会引入额外的数据冗余训练时间变长但精度不涨。反过来步长太大导致相邻patch之间无重叠预测时接缝处可能出现不连续的分类结果。128像素步长配合256像素窗口既保证了约50%的重叠又把样本量控制在合适范围。其实也可以用预测时重叠拼接、训练时不重叠的策略但工程复杂度会高不少我一般建议先按重叠切片跑通流程。import numpy as np from osgeo import gdal def sliding_window_crop(img_path, label_path, save_dir, window_size256, step128): img_ds gdal.Open(img_path) label_ds gdal.Open(label_path) img img_ds.ReadAsArray() # shape: (bands, H, W) label label_ds.ReadAsArray() # shape: (H, W) bands, H, W img.shape idx 0 for y in range(0, H - window_size 1, step): for x in range(0, W - window_size 1, step): img_patch img[:, y:ywindow_size, x:xwindow_size] label_patch label[y:ywindow_size, x:xwindow_size] # 过滤掉大部分是空值或无效值的patch valid_ratio np.mean(label_patch ! 255) if valid_ratio 0.75: continue # 转成通道在后的NHWC格式方便后续处理 img_patch np.transpose(img_patch, (1, 2, 0)) np.save(f{save_dir}/img_{idx}.npy, img_patch) np.save(f{save_dir}/label_{idx}.npy, label_patch) idx 1这段代码里step就是重叠步长window_size是切片尺寸。我用valid_ratio把包含大量无效值255标签的patch过滤掉这是一个容易被忽略的细节——高分影像常有云遮挡、传感器坏道或研究区边界外的黑边直接用原始标签训练会把大量无意义区域的预测结果也计入损失干扰模型收敛。这里的过滤阈值没有绝对标准遥感影像有效区域占比高的可以放宽到0.8云多的影像可以收紧到0.6需要根据自己数据里无效区域的实际比例调整。3.2 波段选择与光谱特征通道的扩展论文方法的一个核心是光谱支要能利用多波段信息。高分影像常见的波段组合有4波段R、G、B、NIR和8波段再加红边、海岸蓝、黄、近红外2不同卫星数据源波段不同。在把数据喂进网络之前有一个被很多人忽略的处理各波段的辐射范围差别很大比如近红外波段的DN值分布可能和可见光波段不在一个量级上直接用会造成光谱支的前几层训练不稳定。def normalize_bands(img_patch, per_band_meanNone, per_band_stdNone): # img_patch shape: (H, W, C) C img_patch.shape[-1] if per_band_mean is None: # 逐波段独立统计而不是把所有波段混在一起归一化 per_band_mean np.mean(img_patch, axis(0, 1), keepdimsTrue) per_band_std np.std(img_patch, axis(0, 1), keepdimsTrue) normalized (img_patch - per_band_mean) / (per_band_std 1e-6) return normalized, per_band_mean, per_band_std注意这里用的是逐波段独立归一化因为不同波段有独立的数据分布混在一起归一化会破坏波段间的对比关系而这恰恰是光谱支最依赖的信息。均值和标准差应该从训练集中统计出来保存好推理时用同一套统计值而不是对每张测试影像重新统计否则模型输出的概率分布会偏移。另一点很多人踩过的坑是数据增强时对比度或亮度抖动会同时改变所有波段这种操作对可见光波段可能有效但近红外波段对亮度变化的敏感度不一样幅度大了容易把光谱支学到的规律破坏掉。3.3 类别不平衡在切片层面的处理思路森林类型分类和普通城市地物分类不同天然存在类别不平衡。比如一个区域内马尾松林占70%阔叶混交林占20%其他类型只有10%。按像素算的类别比例会更悬殊。像FCN这类逐像素分类模型如果直接用原始分布训练小类别的像素在loss里占比太小基本学不出来。常见做法是给损失函数加类别权重权重系数用类别像素频率的倒数归一化后设置。比如使用PyTorch的CrossEntropyLoss(weight...)import torch import torch.nn as nn def compute_class_weight(label_counts, total_pixels, num_classes): # label_counts: 每个类别的像素数量array of length num_classes freq label_counts / total_pixels # 中位数作为基准权重避免大类别权重过小导致训练不稳定 median_freq np.median(freq) weights median_freq / (freq 1e-8) weights np.clip(weights, 0.1, 10.0) # 限制极端权重 return torch.tensor(weights, dtypetorch.float32)np.clip这一步是我强烈建议保留的直接按倒数算权重小类别可能拿到成百上千的权重训练时会让模型对那一类特别敏感反而把大量像素误判成该类别。把权重限制在0.1到10倍范围可以让训练过程稳定很多。如果你不想改loss也可以在切片时对含小类别的patch做上采样比如保证每个训练epoch里含有某一类的patch数量不低于某个阈值但这种做法要和loss权重搭配使用只用上采样会扭曲模型预测概率的置信度。4. 训练配置与损失函数让双支结构真正收敛的几个关键4.1 损失函数的选择加权交叉熵还是加边界约束森林类型分类问题的特殊性在于类别边界不清晰。相邻的林分之间存在过渡带纯天然的树种分布本来就不是边界分明的多边形所以模型在边界区域的误差很难完全消掉。只用加权交叉熵损失训练边界处预测往往呈盐和胡椒式噪声即单个像素独立地在相邻类别之间跳变。这时有两个手段可以加进去效果按性价比排序边界加权损失和Dice损失的多任务组合。边界加权损失的做法是预先从标签图里提取边界像素可以用形态学梯度算子检测相邻像素类别不同的位置在计算交叉熵时给边界像素乘以一个更大的权重系数逼迫网络在边界处更加谨慎。论文资源里没有明确写这一点但这是我复现类似结构时体感收益最大的优化手段之一。Dice损失则能缓解类别不平衡问题它的定义是2×|预测∩真值|除以(|预测||真值|)不受类别像素数量悬殊的影响。两者可以按0.8:0.2的比例混合相加但需要先让加权交叉熵主导训练一段时间再用混合损失微调因为纯Dice损失在训练初期梯度不稳定。def dual_loss(pred, target, ce_weight0.8, dice_weight0.2): ce torch.nn.functional.cross_entropy(pred, target) # soft dice对每个类别独立计算后取平均 pred_probs torch.softmax(pred, dim1) # (B, C, H, W) target_onehot torch.nn.functional.one_hot( target, num_classespred_probs.size(1) ).permute(0, 3, 1, 2).float() # (B, C, H, W) intersection (pred_probs * target_onehot).sum(dim(0, 2, 3)) union pred_probs.sum(dim(0, 2, 3)) target_onehot.sum(dim(0, 2, 3)) dice (2.0 * intersection 1e-6) / (union 1e-6) dice_loss 1.0 - dice.mean() return ce_weight * ce dice_weight * dice_loss这个混合损失里有一个细节intersection和union是按类别维度分开统计的最后对所有类别取平均。这避免了大类别主导Dice值的现象让小类别也能在自己的Dice分数上约束梯度方向。实际训练中我习惯前20个epoch用纯交叉熵后面再加dice项不然模型前期arcing的损失值降不下去。我还在训练过程中试过用Focal Loss替换普通交叉熵但效果并没有Dice组合明显因为高分森林类型分类的错误主要集中在边界而不是难样本本身。4.2 学习率策略Encoder部分该不该冻结遥感影像分类任务常采用在ImageNet预训练模型基础上微调的方式但本文的双支结构里光谱分支和标准VGG预训练权重是不兼容的——ImageNet预训练针对的是3通道自然图像而遥感影像波段数可能更多。常见做法是骨干部分加载VGG-16在ImageNet上预训练的权重只加载前3个通道对应的卷积核多出来的波段通道随机初始化。这两个部分的初始学习率通常要分开设置预训练部分用较小的学习率微调随机初始化部分用正常或略大的学习率从头学。optimizer torch.optim.SGD([ {params: pretrained_params, lr: 1e-4}, {params: new_params, lr: 1e-3}, ], momentum0.9, weight_decay5e-4) scheduler torch.optim.lr_scheduler.PolynomialLR( optimizer, total_itersiterations, power0.9 )多项式衰减是语义分割中常用的学习率策略因为分割任务往往要训练很长的迭代次数线性衰减到接近0的效果比StepLR那种阶梯式下降更平滑。power0.9表示学习率从初始值缓坡下降到最低点的速度指数power越大前期下降越平缓。这里有个比较反直觉的经验新初始化的光谱分支学习率设成预训练骨干的10倍并不夸张因为随机初始化部分的梯度信号本身较弱需要更大的步长才能跟上预训练部分的收敛速度。4.3 训练过程中的监控指标和恢复点分割任务的训练监控有几个易被误解的点。训练过程中应该在验证集上监控mIoU而不是整体准确率因为森林类型分类里如果某一类占绝对多数整体准确率会始终保持很高看着越训越好但小类别的预测基本是坏的。正确的做法是每隔几个epoch同时对验证集做预测计算每类的IoU和mIoU存储mIoU最高的模型权重作为最终权重。还要在训练日志里记录预测结果的可视化图片观察边界处的预测效果是否随训练推进而改善。这两个指标可以帮助识别模型是在真正学习地物模式还是只记住了训练集的统计分布。常用训练轮数上256×256的patch在单卡GPU上配合ResNet或VGG骨干100到150个epoch内mIoU基本会收敛。如果你的验证集mIoU在50个epoch后仍然不增长大概率不是训练不够而是数据或参数配置有问题。常见的现象是损失值下降但mIoU没动这时候优先检查标签是否存在系统性错标以及损失函数里类别权重是否把大类别压得太狠导致模型把所有像素都偏向某个中间类别。5. 避坑与常见问题排查高分遥感分类最容易翻车的五个地方5.1 预测结果一片椒盐噪声现象训练时loss正常下降验证集mIoU也还行但拼回整幅影像看呈现密密麻麻的孤立像素点状错误尤其是在树冠阴影区域和不同林分的交界处。原因高分影像上树冠内部纹理本身就是分形的同一棵树的不同位置光照条件不同阴影一侧和向阳一侧的光谱反射率差距甚至大于两个不同树种之间的差距。单像素分类的模型天然容易在这种区域跳变。另一个原因可能是推理时窗口重叠步长设置不合理相邻patch预测结果冲突。解决推理阶段使用重叠窗口投票策略。预测时维持训练时的256像素窗口但把步长缩小到64像素对每个像素位置收集所有覆盖它的patch的预测概率求平均或者直接对概率图做均值滤波后再取argmax。这个操作对边界噪声的抑制效果非常明显代价是推理时间变为原来的约4倍。另外可以在模型尾部加一层条件随机场做后处理但对高分影像意义不大概率平均就能解决大部分问题。5.2 小类别如混交林完全预测不出来现象模型预测结果里完全没有某个类别所有像素都被分类到其他2到3个主要类别里。检查训练集发现该类别真实存在切片中都看得到。原因类别权重没生效或者权重设置太小。很多框架里CrossEntropyLoss的weight参数要求维度等于类别数如果类别编号从1开始而不是从0开始容易在转换标签时把某个类一起变成忽略类。解决先用代码统计训练集切片的标签分布确认每个类别的最大像素占比。把类别权重打印出来看小类别权重是否为其他类别的3到10倍。如果权重没问题再加Dice项Dice比交叉熵对小类别的梯度信号更直接。如果还不行检查标签编码是否有误——高分影像标签往往是矢量转栅格后生成的ArcGIS或QGIS导出时类别编号发生偏移是常见的事。5.3 训练loss正常下降但验证集mIoU波动剧烈现象每轮验证时mIoU一会儿0.6一会儿0.75波动幅度超过0.1。训练集loss始终在缓慢下降但验证集不稳定。原因大概率是训练集和验证集之间存在空间自相关泄漏。遥感影像相邻像元高度相关如果随机划分验证集时把同一块连续区域的patch同时分到了训练集和验证集模型实际上在验证集上见到了几乎一样的地块一开始验证集指标虚高随着训练推进模型进入过拟合状态虚高的部分被削弱验证集指标就开始上下乱跳。解决按空间位置划分数据集。把遥感影像的规则网格单元划分成若干块按块划分训练/验证比如把整幅研究区按3×3的网格切成9块取其中2块做验证7块做训练而不是在patch级别上随机打乱。空间块状划分会让验证集指标更真实但也意味着可用的训练样本变少指标数值本身会降低一些这是正常的不需要怀疑实现有bug。5.4 双支结构中光谱支不起作用现象单独把光谱支输出禁用只保留空间支推理mIoU和完整双支几乎一样说明光谱支白加了。原因光谱支的初始化方式不对或者光谱支输出特征与空间支高度相关融合后冗余信息被1×1卷积自动降权了。这种情况常见于输入影像本身只有3个可见光波段光谱信息本身就有限再分一支独立提取意义不大。解决重新审视输入数据。如果只有RGB波段建议把归一化差分植被指数NDVI、比值植被指数RVI等计算得到的指数波段拼接到原始影像后输入光谱支让光谱支真正拿到可见光波段不容易直接看到的信息。如果是多光谱数据带近红外、红边波段检查有无在做数据标准化时把NIR波段压缩得失去区分度。我自己的经验是光谱支在森林分类里发挥最大价值的前提是输入里至少有NIR和红边这两个对植被差异敏感的波段。5.5 显存爆掉导致训练中断现象batch size设成16跑得好好的加了一些代码就OOM了或者双支结构对显存的消耗比预想的大不少。原因双支结构在整个前向过程中同时保留两个分支的中间特征图显存占用约等于一个FCN-8s加上一个额外的光谱编码器很多人忽略了这个叠加效应。另外在计算Dice损失时如果对每个通道都生成one-hot编码并与预测逐元素相乘中间变量也会占不少显存。解决先把batch size降到4或2跑通流程再逐步增加训练时开启AMP混合精度训练能减少约40%显存占用把光谱支中间特征的梯度计算停止detach只在融合层之后回传对精度影响很小但能省掉一半光谱支的显存。最后实在不行可以把空间分支的输入分辨率降一半双支输出再上采样回原尺寸计算loss这是一种损人不利己但是保命方案。之前遇到显存爆掉的情况有时不是参数太多而是维度在某一层多加了一个意外维度写代码时每层前后打印一下特征尺寸就能定位。6. 从论文到可用的分类图验证指标与三个落地技巧6.1 用混淆矩阵和每类IoU而不是整体精度验收论文里给出的评价指标通常包括总体精度、Kappa系数、每类IoU。实操时我有一个积累下来的习惯拿到模型输出后第一件事不是看总体精度而是逐类打印混淆矩阵。特别是针叶林里面再细分树种的情况往往某个类别错分到另一个类别呈系统性规律——比如落叶松经常被错分成云杉两种树在特定季节的影像上就是很像。混淆矩阵能直接告诉你模型的系统偏差顺着这个线索回去翻数据经常能发现是训练标签里两类边界区域标错了。from sklearn.metrics import confusion_matrix import numpy as np def evaluate_classification(y_true, y_pred, class_names): cm confusion_matrix(y_true.flatten(), y_pred.flatten()) cm cm.astype(np.float64) iou_per_class [] for i in range(len(class_names)): intersection cm[i, i] union cm[i, :].sum() cm[:, i].sum() - intersection iou intersection / (union 1e-6) iou_per_class.append(iou) for name, iou in zip(class_names, iou_per_class): print(f{name}: IoU {iou:.4f})打印每类IoU时重点关注数值明显偏低的类别然后拿出该类别对应位置的预测概率图和标签图叠加比对。多光谱影像如WorldView-2、Sentinel-2等可以检查NDVI等光谱指数的分布情况辅助判断是误差来自数据还是模型。6.2 条件随机场后处理要注意的三个参数CRF后处理是遥感图像语义分割常用的后处理手段能有效去除碎片状误分类并平滑边界。三个参数控制最终效果——高斯核位置参数、高斯核带宽参数、以及双向核权重。常见配置里位置参数设为3到5带宽参数设为50到80双向核权重设为3到5。但有一个常被忽视的点CRF的迭代次数从5次改为10次时效果提升明显代价是推理时间是指数级增加——实际使用中在推理速度要求高时用5次离线制图时用10到15次。另一个需要注意的事项是CRF的类别先验。遥感分类场景中不同地物类型的空间分布是有先验信息的比如水体不会零散地出现在森林中心CRF参数调优时应该把类别间的空间相容性考虑进去。如果你用的是现成CRF库可以修改类别兼容性矩阵让混合林-针叶林的转移代价低于水体-针叶林。这一点在论文变种里较少提及但实际应用场景中能明显改善分类图的逻辑合理性。6.3 一个能让你少跑一轮实验的推理技巧概率平均代替投票做完模型推理后拼接整幅影像时很多人直接把每个patch的argmax结果填空到对应位置。这个方法的问题是patch边缘的像素使用的上下文信息较少预测置信度偏低会出现明显的block伪影。我的习惯是保留每个patch的完整概率输出在拼接时对重叠区域做加权平均——置信度高的阈值范围内用平均概率置信度低的位置给中心区域更高权重这样得到的整幅分类图比单纯的分块投票干净得多。具体到工程代码通常用重叠加权平均把推理时的重叠区域概率按距离权重线性加权已经足够有效不需要上更复杂的图模型。视觉上边界处树种的渐变过渡更加合理不那么硬邦邦的这两个细节对提交成果图的质量影响很大能明显减少返工次数。从实现角度看把边界平滑和光谱支利用好双支FCN-8s的效果会远优于你预期。从那以后我每次做森林类型精细分类都会强制走一遍这套流程——先按空间块划分数据再检查波段归一化是否独立统计最后推理时必开重叠投票。这三点看起来不起眼但它们比调网络结构参数更能决定最终分类图的可用性希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网