基于SRCNN的哨兵2号影像超分辨率重建:从10米到2.5米的实践
2026/9/16 21:21:53 网站建设 项目流程

说实话,我第一次对着哨兵2号的10米分辨率发愁时,心里想的是:“要是能不花钱就把它变成2.5米就好了。” 后来我确实把这件事做成了——方法就是SRCNN深度学习模型做图像超分重建。哨兵2号(Sentinel-2)提供了全球免费、重访周期短的多光谱影像,10米分辨率已经能看清大片农田和林地,但要数房子、认小路、画小地块边界时就非常吃力。商业高分影像的成本不是每个项目都扛得住,于是我开始琢磨:能不能用深度学习把10米影像超分到2.5米?这篇文章会把整条链路从头到尾拆开讲,包括SRCNN的原理、训练数据怎么准备、模型怎么训练、推理发布要注意什么,以及我实测过程中踩过的坑。无论你是遥感专业的学生和从业者,还是做深度学习但想进遥感领域的算法工程师,都可以照着这套方法跑一遍。

1. 为什么我要对哨兵2号做超分:10米数据的痛点与2.5米目标的由来

1.1 Sentinel-2的分辨率结构决定了超分的起点

哨兵2号不是所有波段都长一个样。它搭载的MSI多光谱仪把波段分成三组:B2蓝、B3绿、B4红、B8近红外这4个波段是10米;B5、B6、B7红边波段和B8A、B11、B12短波红外是20米;B1、B9、B10主要用于大气校正,是60米。所以谈“哨兵2号分辨率”,一定要先明确你是要超分哪个波段组合。通常做真彩色或者标准假彩色,用的就是B4-B3-B2或者B8-B4-B3这组10米波段,这也是我们最容易想到要提升分辨率的目标。

10米分辨率是什么概念?一个像元在地面上是10米乘10米。一条乡村水泥路如果宽度在3到4米,它在10米影像上通常只占不到半个像元,边缘混合得非常厉害。小地块的农田边界、城市里的民房轮廓、河道两侧的细碎植被,在10米影像上都是一团一团的混合像元。做目视解译还能勉强应付,但如果想把结果喂给后续的深度学习分割模型,10米影像在很多场景下达不到精度要求。

1.2 2.5米是4倍超分,不是随便定的目标

2.5米这个数不是拍脑袋来的,它刚好是10米的四分之一,也就是把每个10米像元拆成4乘4共16个子像元,对应4倍超分。SRCNN最早在论文里验证的就是2倍、3倍、4倍这类整数倍重建,4倍是一个比较稳妥的上限。超过4倍之后,模型要“脑补”的细节太多,容易产生明显伪影,比如树冠边缘出现水彩状纹理、屋顶轮廓被画出奇怪的直角。

另外,2.5米在实际业务里也有意义。很多地物识别任务中,2.5米分辨率已经能大致分辨出单个建筑、小型车辆集群、地块边界,价格比0.5米或1米的数据低一个量级。用深度学习把一个免费数据源推到2.5米,等于在预算不变的情况下给项目多了一层可用的底图。需要说明的是,这种“免费升级”不是无中生有,而是从数据本身的统计规律里恢复被模糊掉的边界信息,效果有上限,后面我会专门讲。

1.3 为什么不直接双三次插值到2.5米

很多人会问:既然只是把10米变成2.5米,ArcGIS或者GDAL里一个双三次插值不就搞定了吗?我一开始也这么试过。双三次插值确实能把像元尺寸变小,但它本质上是一个平滑滤波过程:它假设相邻地物变化是连续的,所以只在两个像元之间做加权平均。结果就是边缘被磨圆、细小地物被抹平,放大后看着清晰,实际上没有任何新信息。

超分重建要解决的是另一个问题。我们想知道一个10米像元内部的亚像元结构,而这个信息在采集时已经丢失了,所以必须依靠先验知识来“猜”。SRCNN这类深度学习模型做的,就是在大规模遥感影像上学习这种先验:看到这样的低分辨率纹理,大概率对应那样的高分辨率边界。用生活里的例子类比:双三次插值相当于把一张照片在PS里直接放大,SRCNN则像请一个见过无数类似地物的修图师,按经验把丢失的轮廓猜回来。

2. SRCNN在遥感影像上到底怎么工作:三层卷积背后的设计逻辑

2.1 从9×9到1×1再到5×5,每一层都有明确分工

SRCNN是2014年由Dong等人提出的,网络结构非常简单。它只有三层卷积:第一层用9×9卷积核把输入影像切成重叠的图像块并提取特征,输出64个特征图;第二层用1×1卷积核在特征维度上做非线性映射,把特征从64维压到32维;第三层用5×5卷积核把这些特征重新组合成最终的高分辨率输出。

这个结构今天看很轻量,但设计意图非常清晰。9×9卷积对应一个大感受野,保证每个输出像元能看到足够大的邻域信息,这对重建边缘很重要;1×1卷积相当于在特征空间里做通道混合,可以理解成一个可学习的非线性变换层;5×5卷积则负责把高层特征还原回像素空间。三层之间都用ReLU激活,只有最后一层不加激活函数,确保输出可以是任意实数值,不会把反射率截断到正区间。

整个SRCNN的参数量只有大约5.7万个,这在深度学习模型里小得可以忽略。即便用CPU推理,一张512×512的影像也只要几百毫秒。这也是我推荐先拿SRCNN做基线的重要原因:网络简单、容易调通、出问题好排查。等管线跑通了,再换EDSR、RCAN甚至SwinIR都不迟。

2.2 训练时最关键的一步:把HR降采样再上采样成LR

SRCNN有一个容易把人绕晕的地方:训练时,输入到底是不是低分辨率影像?答案是“不是严格意义上的小尺寸低分辨率图”。原始论文的做法是:先准备高分辨率训练块,比如128×128;然后对它做双三次下采样到1/4尺寸,也就是32×32;再把这32×32的图用双三次插值放大回128×128,把这个模糊版本作为网络输入,把原始128×128图作为标签。

也就是说,网络输入和输出的空间尺寸是一样的,输入是一张“被弄模糊的大图”,输出是我们希望恢复的清晰图。这样的设计让SRCNN不必学习如何改变分辨率,只需要学习从“模糊插值结果”到“清晰原图”的映射。推理时,我拿到一张真实10米影像,先双三次放大4倍到2.5米网格,再喂给模型,模型输出就是锐化后的2.5米图。

这个逻辑如果没想清楚,很容易踩坑。我当时第一次训练时直接把32×32的小图喂进网络,输出也变成32×32,和128×128的标签对不上,训练直接崩掉。处理办法很简单:数据加载时务必把LR输入先上采样到和HR标签相同的尺寸。

2.3 多光谱波段应该怎么输入

SRCNN的输入通道数是可以改的。如果只做真彩色,就用B2、B3、B4三个波段,网络输入通道数设为3;如果想把近红外也加进来,就用B2、B3、B4、B8四个波段,输入通道数设为4。模型本身不关心你喂的是什么波段,它只会把这几个通道当成同时出现的特征来学习。

我自己的习惯是先用三通道真彩色跑通流程,因为调试时肉眼效果好判断。等流程稳定了,再改成四通道或者更多波段。如果你想加入20米波段,比如B11短波红外,需要先把20米波段用最近邻或双三次重采样到10米网格,再作为额外通道输入。这里要提醒一句:重采样20米到10米并不会创造新的空间信息,它只是把20米像元复制到更小的网格上,加入这个通道对空间细节提升有限,但可能在某些地类分类任务中对光谱区分有帮助。使用时要记录清楚波段顺序,推理和训练必须完全一致,否则输出颜色和纹理都会乱掉。

3. 训练数据与预处理:从哨兵2号L2A产品到成对样本的完整流水线

3.1 数据源与挑选原则

训练SRCNN不需要特别大的数据量,但对数据质量要求不低。我通常从Copernicus Data Space或者AWS公开数据集上下载哨兵2号L2A产品。选择L2A而不是L1C,是因为L2A已经做过大气校正,得到的是地表反射率,省去了自己做大气校正的麻烦。如果使用GEE,可以直接导出一个区域的多波段影像,但要注意区分L2A集合,并做好云掩膜。

挑选训练影像时,我的原则是“地域跨度大、季节覆盖全、地类丰富”。比如挑10到15景左右,分别覆盖城市建成区、农田、山地森林、沿海滩涂、内陆水体。城市区域能提供大量人工建筑的锐利边缘,农田提供了规则地块边界,山地和森林提供了不规则自然纹理。这些多样性能让模型学到遥感影像中常见的各类地物结构,而不是只记住某一类场景。

云和云影是最大的坑。即使L2A产品有场景分类层,我仍然建议自己再目视检查一遍,把厚云、薄云和阴影比例高的影像直接排除。模型如果学到了云影的纹理,超分时可能会把云影边缘“锐化”得更加明显,这在业务上是不能接受的。

3.2 裁块、标准化与数据增强

拿到原始影像后,我通常把每个波段转成float32,并除以10000,把反射率归一到0到1左右。L2A产品的像元值是0到10000的整数,代表反射率乘以10000,所以这个转换是必须的。如果不做归一化,直接用原始整数喂给网络,MSE损失会被大数值的波段主导,训练极难收敛。

然后是裁块。我一般从每景影像里随机裁剪128×128的小块,步长在80左右,这样相邻块之间有重叠,能增加样本数量,又不会让训练集里出现太多重复内容。每一景10000×10000像素的影像,裁出来的块数量非常可观,实际用3万到5万块训练就足够了。裁块时要注意,HR标签块和LR输入块必须一一对应:先裁HR块,再用同一个块做双三次下采样和上采样,这样两个文件天然对齐。

数据增强我用的是最基础的一组:随机水平翻转、随机垂直翻转、随机90度旋转。对遥感影像来说,旋转180度和270度也很合理,因为卫星影像没有正北方向的语义约束。增强后的训练块数量能再乘上8到16倍,对SRCNN这种小网络来说已经非常充裕。

3.3 样本量不是越多越好,关键是样本质量

我见过有人为了图省事,直接拿一景巨大的哨兵2号影像切成几十万块训练,结果验证时发现模型只学到了这一景的纹理,换一景数据效果骤降。这就是过拟合到单景影像。要避免这个问题,训练集和验证集必须来自不同影像、不同地理位置。我通常选10景作为训练,2景完全不同区域的影像作为验证,2景作为测试。测试影像从头到尾不参与训练,也不参与验证,这样才能判断模型是否真的学到了通用超分能力。

如果你的目标是更贴近真实业务区域,还可以在训练集里多加入目标区域的样本,但一定要留出同一区域不同时相的影像做验证,否则模型可能只是“记下”了那一片的地物分布,而不是学会了超分重建。

4. 模型搭建与训练细节:参数设定、损失曲线和显存控制

4.1 一个直接可用的PyTorch SRCNN定义

SRCNN实现起来非常短。下面是我常用的版本,输入通道数用参数控制,既可以跑三通道RGB,也可以跑四通道多光谱:

import torch import torch.nn as nn class SRCNN(nn.Module): def __init__(self, num_channels=3): super(SRCNN, self).__init__() self.conv1 = nn.Conv2d(num_channels, 64, kernel_size=9, padding=4) self.conv2 = nn.Conv2d(64, 32, kernel_size=1, padding=0) self.conv3 = nn.Conv2d(32, num_channels, kernel_size=5, padding=2) self.relu = nn.ReLU(inplace=True) def forward(self, x): x = self.relu(self.conv1(x)) x = self.relu(self.conv2(x)) x = self.conv3(x) return x

padding的选择是让卷积不改变空间尺寸。因为输入已经是上采样到HR尺寸的模糊图,输出也要保持同样尺寸,所以padding分别为4、0、2。setinplace=True可以节省一点显存,虽然微不足道,但养成好习惯没坏处。

4.2 训练超参数与损失函数

训练SRCNN最经典的损失函数是MSE,也就是像素级的均方误差。MSE和PSNR直接相关,MSE越低PSNR越高,所以在“图像重建质量”这个评价体系里非常合适。如果你想追求更锐利的边缘,可以后面再加感知损失或者对抗损失,但那已经不是原始SRCNN的范畴了。

我常用的超参数如下:

参数推荐值说明
优化器Adam收敛快,不容易出现梯度爆炸
初始学习率1e-4太大容易震荡,太小收敛太慢
Batch Size64显存不够就降到32或16
Patch Size128×128改小到64×64也能训练,但效果略差
Epochs100超过100轮后验证集提升很小
学习率衰减每30轮×0.5让后期训练更稳定
权重衰减1e-5轻微抑制过拟合

按照这个配置,在3万块训练样本上,显存占用大约3GB左右。如果你的显卡是6GB也可以跑,只是Batch Size需要适当降低。训练循环本身没什么特殊,就是普通的有监督回归:

for epoch in range(epochs): model.train() for lr, hr in train_loader: lr, hr = lr.to(device), hr.to(device) out = model(lr) loss = criterion(out, hr) optimizer.zero_grad() loss.backward() optimizer.step()

这里有个容易出错的地方:train_loader返回的lr必须是已经上采样到和hr一样尺寸的模糊图,而不是小尺寸的LR图。你在数据预处理阶段准备成什么样,训练时就喂什么样,保持一致。

4.3 训练过程中怎么判断收敛和质量

我习惯每个epoch打印一次训练loss,每5个epoch在验证集上算一次PSNR和SSIM。遥感影像的PSNR不像自然图像动不动就接近40dB,因为有大量纹理和边缘复杂的区域,通常25到32dB都算正常。更重要的指标是趋势:训练loss稳步下降,验证PSNR前几十轮在上涨,后面逐渐平稳,这就是健康状态。

如果训练loss下降但验证PSNR不涨,大概率是过拟合。解决办法是先检查训练集和验证集是否来源重叠,再增加数据增强和权重衰减。如果验证PSNR一直低于24dB,我的经验是先别急着调网络,回头检查标准化和退化流程。十有八九是LR输入和HR标签没有对齐,或者反射率数值范围没归一化。

5. 推理测试与质量评估:PSNR/SSIM之外还要看什么

5.1 推理并输出带地理坐标的GeoTIFF

模型训练完,真正的考验才开始。拿到一景新的哨兵2号影像,我通常先用rasterio读取,只选择训练时用过的波段,转成float32并除以10000。然后要把整幅图切块推理,避免一次把几万乘几万的影像塞进显存。切块的尺寸和训练patch保持一致,推荐用128或者256,相邻块之间要有32像素左右的重叠,拼接时可以直接平均重叠区域,或者按距离加权,能有效避免拼缝。

推理核心是先把每个patch用双三次插值放大4倍:

import torch.nn.functional as F patch_up = F.interpolate(patch, scale_factor=4, mode='bicubic', align_corners=False) with torch.no_grad(): out = model(patch_up)

patch_up就是输入到SRCNN的模糊放大图,模型输出是锐化后的图像。全部推理完成后,把所有patch拼回完整影像。写GeoTIFF时要注意更新仿射变换:原始10米像元大小要变成2.5米,也就是把transform里的像元宽度和高度都乘以0.25,但左上角坐标保持不变。用rasterio的话,可以这样:

from rasterio.transform import Affine new_transform = transform * Affine.scale(0.25, 0.25)

这里transform是原始10米影像的仿射变换,乘以Affine.scale(0.25, 0.25)之后,像元尺寸就从10米变成了2.5米。这一步如果漏掉,输出的图片看起来没问题,但叠加到GIS里位置会全错。

5.2 没有2.5米真值,怎么客观评估

我一开始最头痛的问题就是:没有真实2.5米影像做标签,怎么量化超分效果?总不能只靠肉眼说“看起来更清晰”。后来我总结出三个替代评估方法。

第一,退化重建评估。从原始10米影像中裁出一批测试块,先把它们降采样到40米,再用训练好的4倍模型超分回10米,然后和原始10米块计算PSNR和SSIM。这个指标能反映模型在已知退化过程上的重建能力,是SRCNN论文里常用的评价方式。但它有个天然局限:它验证的是“40米到10米”,而不是真正的“10米到2.5米”,所以只能作为参考。

第二,光谱保真评估。把超分得到的2.5米影像在空间上聚合回10米,也就是对每个10米窗口内的2.5米像元求平均,然后和原始10米影像逐波段计算RMSE。这个RMSE如果很小,说明超分过程没有把反射率整体改掉,光谱信息保住了。对定量反演类业务来说,这个指标可能比PSNR更重要。

第三,边缘剖面分析。在影像上选一条穿过道路或田埂的切线,看灰度值从暗到明的变化有多陡。双三次插值的边缘剖面是缓慢过渡的,SRCNN如果有效,边缘会明显变陡。这个方法虽然主观,但特别适合判断线状地物的重建质量。

5.3 目视效果到底提升在哪

我在多组测试影像上对比过原始10米、双三次2.5米和SRCNN 2.5米,总结成一张经验表:

地物类型原始10米双三次2.5米SRCNN 2.5米
乡村道路断断续续连续但边缘发虚边缘锐利,连续性明显提升
房屋轮廓一团混合像元平滑方块边界更接近直角,细节有改善
农田地块边界模糊有边界感但发毛边界清晰,田埂可辨
大片水体平滑平滑平滑,几乎没有变化
阴影区域细节全无依然没有细节能猜测出部分纹理,但不可靠

从这张表能看出来,SRCNN对“有结构、有方向性”的地物最有效,比如道路、田埂、建筑边界。对大面积均匀地物,它不会带来坏处,但也不会有明显收益。这说明超分模型的本质是恢复结构先验,而不是凭空创造信息。真要有哪块云影区域连原始10米都是全黑的,SRCNN也不会隔空变出地物细节。

6. 实测翻车记录与改进方向:给想复现的人提个醒

6.1 我踩过的三个典型大坑

第一个坑是训练输入和输出尺寸不一致。我前面提过,第一次训练时直接把32×32的低分辨率图喂进网络,输出也是32×32,和128×128的标签没法算loss。这个问题非常隐蔽,因为很多超分教程只说“用低分辨率和高分辨率做训练对”,却不强调SRCNN采用的是“先上采样再重建”的pre-upsampling结构。解决方案就是在数据加载时先把低分辨率图双三次放大回高分辨率尺寸。

第二个坑是推理时没有切patch,直接整景影像跑导致显存爆炸。SRCNN模型本身很小,但输入一张两万像素宽的影像,哪怕三层卷积也会把中间特征图撑爆。我后来学乖了,不管模型多轻量,统一用patch推理加重叠拼接。

第三个坑是波段顺序不固定。我训练时用了B4、B3、B2三个波段,结果推理脚本里读的是B8、B4、B3,输出影像的颜色完全错乱,NDVI之类的指数也全不对。现在我会在每个训练实验的配置文件中固定波段顺序和名称,推理前先比对。

6.2 理想bicubic退化和真实传感器退化之间的差距

SRCNN最经典的训练方式是用双三次下采样作为退化模型。但实际卫星成像过程远比这个复杂:传感器光学系统有MTF衰减,大气散射和地形阴影会对辐射值产生影响,甚至轨道重采样也会引入额外平滑。也就是说,真实10米影像并不是一个“理想2.5米影像”做双三次下采样得到的,所以训练时的退化假设和实际数据之间总是存在差距。

想让模型在业务数据上更实用,有几个改进方向。一是用哨兵2号的MTF曲线来生成LR样本,让退化过程更接近真实成像;二是如果某个项目区域有无人机正射影像或0.5米航空影像,可以把这些高分辨率影像局部降尺度到10米,和对应区域的哨兵2号影像组成真正的跨传感器训练对;三是直接换用盲超分模型,让模型自己估计退化核,但训练复杂度和计算成本都会上去。

SRCNN用bicubic退化训练出来的模型,在真实哨兵2号上依然有效果,原因是卫星影像经过重采样后,局部模糊核和bicubic有一定相似性。但你要知道这个上限在哪,尤其是做定量分析时不要过度依赖。

6.3 2.5米超分产品的适用边界

我最终把SRCNN 2.5米输出接到过几个实际项目里,有成功的,也有不太顺利的。比较适合的场景是:快速目视解译、变化检测前期的目标初筛、制作专题底图、给分割模型做数据增强。不太适合的场景是:需要精确测量地物面积、反演植被生化参数、提取亚像元级光谱特征。这些任务本身对辐射精度极其敏感,超分过程哪怕只引入很小的光谱失真,都会在后面的定量模型里被放大。

如果是给客户交付成果,我都会在成果报告里写清楚:该产品是深度学习超分增强产品,不是原生2.5米高分辨率影像。同时建议客户在使用前,选取一小块区域用真实高分辨率影像做精度对比,确认可以接受再展开应用。这不是推卸责任,而是遥感产品本身就该有明确的不确定性说明。

6.4 下一步的扩展思路

SRCNN只是一个起点。如果你已经跑通了这套流程,后续可以往几个方向扩展。第一,把网络换成FSRCNN或ESPCN,用亚像素卷积直接在低分辨率空间计算,速度和效果都会有提升;第二,换EDSR或RCAN这类更深更宽的网络,在遥感影像上通常能比SRCNN再提升1到2个dB的PSNR,但训练时间会显著增加;第三,把20米波段加入输入通道,让网络同时学习空间超分和光谱增强,对某些地类可能会有意外收获;第四,利用哨兵2号的高重访频率,把多时相影像叠在一起做时空融合,让不同时间的互补信息共同参与重建。

我个人的习惯是先保留SRCNN作为基线模型。每进入一个新区域、新数据源,先跑一遍SRCNN,确认数据质量和地物可辨识度有没有提升,再决定要不要上更复杂的模型。这样做的好处是,可以快速区分“超分算法的问题”和“数据本身的问题”,避免一上来就陷入大模型的调参泥潭。

一开始我觉得SRCNN这么老的网络,肯定不如现在那些大模型。但真正把数据流跑通后我才发现,遥感影像超分的瓶颈根本不在网络结构,而在退化建模和数据分布是否贴近真实业务场景。我到现在依然保留着这套SRCNN脚本,作为任何新数据的基线模型。每次拿到一批新影像,我会先跑一遍SRCNN输出,判断数据质量和地物可辨识度。如果SRCNN都明显有效,再往上换EDSR、RCAN甚至SwinIR才有意义。这套流程里的预处理、评估、发布方法,换任何网络都能复用。最后再提醒一句:超分不是无中生有,千万别把2.5米结果直接当成原生高分辨率去做定量分析。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询