资讯动态

卫星云图理解与识别实战:预处理、模型选型与避坑指南

发布时间:2026/10/18 23:30:10 来源:尧图企业网站定制
简介卫星云层图像的理解与识别是计算机视觉课程中的典型综合任务配套高分大作业完整覆盖数据处理、模型训练到结果评估全流程。资源包内含Python源码与实验报告共140个文件其中70个py脚本构成核心实现辅以44个pyc编译文件、5个csv数据文件含训练集与多组测试结果、3个yaml配置以及sh辅助脚本、md文档、PDF实验报告和PPTX汇报材料整体体积62.35MB目录结构清晰便于直接部署与二次开发。已有216人学习下载适合计算机视觉课程设计、期末大作业及入门实践无论用于课程答辩还是实际项目练习都有较强参考价值。源码包含详细注释新手也能看懂数据划分、模型构建与预测逻辑实验报告以PDF形式完整记录实验过程与结果分析方便对照复现与拓展思路。1. 卫星云图理解与识别它不只是一个普通的图像分类题把卫星云层图像的识别当作常规图像分类来做是最常见的翻车起点。云图里的像素不是自然照片的 RGB 色彩而是辐射计对云顶亮温、反射率的物理响应薄云与厚云在灰度上可能只差几个亮度级噪声却比普通照片大得多。A同学一开始直接拿 ResNet 预训练模型硬训在验证集上卡在 72% 准确率上不去后来把辐射定标和区域投影做对了同样的模型直接涨了 5 个点。这个项目标题里真正值分的地方是「理解与识别」而不是「识别」——理解云图的物理含义、数据结构和标注方式才谈得上模型选型和调参。这篇笔记把一个可复现的完整路径拆开数据怎么拿到、预处理做到什么程度、模型怎么选、实验报告怎么组织才能拿到高分以及哪些环节最容易踩坑。2. 数据准备与预处理从原始云图到能训练的干净样本2.1 数据获取公开云图产品与标签组织形式的选型卫星云图数据来源通常是气象卫星的 L1 级及以上产品。国产风云系列、国际上的 GOES 系列、葵花系列都有公开的存档下载渠道课程作业常用的做法是下载某几个时次的全圆盘图或者目标区域的标称投影产品。需要注意的一点是下载到的产品往往有三个通道的灰度数据可见光、中红外、热红外而不是直接给你一张好看的 RGB 图。标签方面公开数据集里有标注好的云分类掩码晴空、水云、冰云、多层云、卷云等也有只做云/非云二分类的掩码。选数据时先搞清楚标签类别的粒度和样本数量分布这直接决定后面的模型设计难度。我一般会先做一张数据清单表列清楚每个文件的波段数、空间分辨率、时间分辨率、标签类别数和标签格式。格式上云图掩码常见的是 PNG 或 GeoTIFFPNG 标签图直接读取即可GeoTIFF 则需要用栅格库解析地理信息。做实验报告时这个清单表可以直接放进数据说明章节属于性价比极高的呈现方式。处理这些数据的目录结构建议按「数据集 / 图像 / 标签」分开放避免训练脚本里路径混乱cloud_dataset/ images/ train/ 001.png val/ 002.png masks/ train/ 001_mask.png val/ 002_mask.png class_dict.jsonclass_dict.json 里保存类别名与像素值的映射关系例如水云对应像素值 1冰云对应 2这种做法在写数据加载器时非常省事。2.2 辐射定标与裁剪投影为什么彩色视图不能直接当训练输入卫星云图的原始 DN 值和反射率/亮温之间有定标系数通道间定标方式不同。直接把下载到的灰度图缩放成 0-255 作为模型输入等于把物理量信息抹掉了。我见过太多复盘报告里写「做了 Min-Max 归一化后训练」但真正的定标逻辑没有实现。常见的做法是对可见光通道根据定标表把 DN 值转换为反射率范围 0-1对红外通道转换为亮温单位 K然后做 min-max 线性拉伸到 0-255。这个步骤做完图像对比度会明显改善厚云、薄云的灰度差距更容易被网络捕捉。裁剪投影同样关键。全圆盘图边缘是畸变的直接进网络会让特征学习被无效区域干扰。我用过一个方案先按卫星投影范围做经纬度边界裁切去掉四条边的无效区域再按统一尺寸比如 256×256 或 512×512缩放。裁切操作不改变数据分布但会显著减少干扰样本提高训练稳定性。下面的预处理脚本片段把「定标 裁剪 归一化」串起来是实验里实际用到的流程import numpy as np import cv2 def calibrate_cloud(chn_dn, cal_coef): 辐射定标DN值转反射率/亮温再拉伸到0-255 cal_coef: (offset, gain)不同通道系数不同 offset, gain cal_coef physical (chn_dn.astype(np.float32) - offset) * gain chn_min, chn_max np.percentile(physical, 1), np.percentile(physical, 99) chn_norm (physical - chn_min) / (chn_max - chn_min 1e-6) return np.clip(chn_norm * 255.0, 0, 255).astype(np.uint8) def crop_projection(img, bbox): 按经纬度边界裁剪全圆盘图的有效区域 bbox: (x0, y0, x1, y1)坐标由投影参数换算得到 x0, y0, x1, y1 bbox return img[y0:y1, x0:x1] def preprocess_pipeline(dn_img, bbox, cal_coef_list): if len(dn_img.shape) 2: dn_img np.stack([dn_img] * 3, axis-1) channels [] for i in range(3): c calibrate_cloud(dn_img[..., i], cal_coef_list[i]) c crop_projection(c, bbox) channels.append(c) rgb np.stack(channels, axis-1) rgb cv2.resize(rgb, (256, 256), interpolationcv2.INTER_CUBIC) return rgb这里对每个波段独立做定标和裁剪最后统一 resize 到 256×256。percentile 拉伸用 1%-99% 分位数而不是全局 min-max是为了抵抗极亮极暗像素点比如饱和亮温造成的分布偏移。cal_coef_list 在实验中直接从卫星产品的头文件读取不同通道差别很大不能共用一套系数。2.3 样本不平衡与增强策略云类占比失衡时如何稳住训练云分类数据里晴空样本往往远多于卷云、高层云样本类别不平衡比一般视觉数据集更严重。我实验里统计过某批数据晴空占 58%水云占 25%冰云占 10%其余类合计才 7%。直接拿这种分布训练模型学到的只是「大多数类」的分布输出几乎全是晴空。两种有效的手段加权采样和增强策略。加权采样先统计每个类别的像素占比给少数类赋予更高采样权重具体做法是给数据集里的每个样本按主导类别分配采样概率from torch.utils.data import WeightedRandomSampler def make_sampler(labels, class_weights): labels: 每个样本的主导类别索引; class_weights: 各类别的采样权重 sample_weights [class_weights[label] for label in labels] sampler WeightedRandomSampler( weightssample_weights, num_sampleslen(labels), replacementTrue ) return sampler class_weights { 0: 1.0, # 晴空 1: 2.5, # 水云样本略少 2: 4.0, # 冰云样本显著少 3: 8.0, # 卷云样本极少 }采样权重不是越大越好。卷云给到 8.0 之后模型能看到更多卷云样本但也会因为反复看到同一批样本而过拟合我遇到的情况是训练集指标很高、验证集掉点。下调到 5.0 配合增强使用效果更稳。增强策略上cutmix 和 mixup 对云图效果很好。云图边缘特征的连续性不强cutmix 把两块云图拼接成一个样本可以让模型学会对局部特征做决策而不是靠整图纹理猜。注意增强不要用随机旋转 90 度以外的强几何变换云图的朝向本身带有地理方向含义旋转任意角度会让模型学习到错误的方向关联。3. 模型选型与训练路径从二分类检测到多类语义分割3.1 先做云/非云二分类再上多类识别控制任务难度的常见做法拿到云图数据后不要直接做五分类甚至更多类别的识别。常见做法是先建立一个二分类模型判断「这个像素/图像区域有没有云」再在「有云」的区域内细分云的类别。这个分层策略能解决两个问题第一二分类的样本分布通常比较均衡模型容易收敛第二多类分类时「无云」区域会干扰特征学习分类器容易把注意力放在区分云与地表上忽略了不同云类之间的细微差异。具体实施上把一个多类任务拆成两个阶段第一阶段用二分类交叉熵损失训练一个 U-Net 输出云/非云概率图第二阶段只取概率图中云区域进入多分类模块。课程作业里如果数据量不大把这两个阶段合在一起做多任务学习也是常见做法网络共享一个编码器解码器分两个头一个头输出二分类掩码一个头输出多类掩码总损失 二分类损失 × 0.5 多类损失 × 0.5。多任务的好处是编码器学到兼顾两头的特征表示二分类头的梯度帮助编码器聚焦云区结构。3.2 用预训练 CNN 做迁移学习骨架选择与初始化参数配置对卫星云图任务不建议从零训练一个深层网络。云图结构和 ImageNet 自然照片差异很大但预训练模型前几层学到的边缘、纹理基础特征仍然有效。我的经验是选择编码器时优先考虑带空洞卷积的 ResNet 或 EfficientNet 系骨架输入分辨率支持到 256 甚至 512 的条件下显存占用可控。训练配置上我常用的是一套偏保守的参数适合课程实验和单人复现的显存条件model create_cloud_model( backboneresnet34, encoder_weightsimagenet, num_classes4, input_channels3, )# 优化器与调度策略 optimizer torch.optim.AdamW(model.parameters(), lr1e-4, weight_decay1e-5) scheduler torch.optim.lr_scheduler.CosineAnnealingLR( optimizer, T_max80, eta_min1e-6 ) # 损失函数多类分割用带权重的交叉熵 Dice loss_fn CombinedLoss( ce_weightclass_weights_tensor, dice_weight0.5, )关键配置说明encoder_weightsimagenet 加载预训练权重前几层冻结freeze训练 5 个 epoch再解冻全部层训练避免一开始梯度把预训练特征破坏掉。AdamW 的 weight_decay 设到 1e-5 而不是默认的 1e-2因为云图数据量小过强的权重衰减会让模型欠拟合。CosineAnnealingLR 配合 80 个 epoch先快速下降再缓慢逼近比固定学习率更容易在训练后段继续稳定提升。Dice 损失能缓解类别不平衡但单独用 Dice 在训练初期梯度不稳定和交叉熵加权组合更稳。3.3 语义分割定位云层U-Net 结构与分割头配置多类云识别本质是语义分割问题逐像素类别预测比整图分类更有解释性实验报告里呈现的分割可视化也更直观。U-Net 结构是这类任务最稳妥的选型它的跳跃连接能同时保留高分辨率细节和深层语义信息对薄云边界、碎云的细小结构效果明显好于单纯编码器-解码器。针对云图的分割头配置有一处值得注意不同云类的边缘特征差异很大卷云边缘模糊、水云边缘锐利单一尺度的输出头很难兼顾。我在实验里加了一层多尺度融合输出头把编码器不同阶段的特征图分别上采样到统一尺寸再拼接预测def forward(self, x): # 编码器各阶段输出 e1, e2, e3, e4 self.encoder(x) d4 self.decoder(e4) d3 self.decoder(d4 e3) d2 self.decoder(d3 e2) # 多尺度输出从深层到浅层分别上采样 out1 self.head(d4) # 深层次强语义 out2 self.head(d3) # 中层次边缘与语义平衡 out3 self.head(d2) # 浅层次高分辨率细节 out1 F.interpolate(out1, scale_factor2, modebilinear) out2 F.interpolate(out2, scale_factor2, modebilinear) return (out1 out2 out3) / 3.0多尺度融合输出在验证集上的 mIoU 比单输出头高了约 2.3 个百分点代价是显存增加约 20%、训练时间增加约 15%。如果实验环境显存紧张也可以去掉深层输出头只保留两个尺度效果仍然优于单头。训练完成后推理时需要在输出概率图上做 argmax 得到像素级类别再结合后处理做小连通域剔除。下面这段后处理是实验报告里可以体现工程细节的部分def postprocess_mask(prob_map, min_area16): label_map prob_map.argmax(dim1).squeeze().cpu().numpy() for cls in range(1, label_map.max() 1): cls_mask (label_map cls).astype(np.uint8) num_labels, labels, stats, _ cv2.connectedComponentsWithStats(cls_mask, 8) for i in range(1, num_labels): # 剔除面积过小的孤立预测 if stats[i, cv2.CC_STAT_AREA] min_area: label_map[labels i] 0 return label_mapmin_area 参数需要根据输入分辨率调整。256×256 输入时 16 个像素约为 0.024% 面积比太小起不到去噪效果太大会把碎云区域误删。我用 16 时碎云保留和去噪的平衡最好。3.4 训练日志与评估指标什么结果才算「真正有效」训练日志不只记录 loss还应该记录每个类别的 IoU、总体 mIoU、像素准确率。云图任务里总体准确率有欺骗性类别不平衡时 80% 总体准确率可能只是晴空覆盖率mIoU 更能反映真实能力。每 5 个 epoch 保存一次检查点并手动调整学习率策略比一次性训完更容易发现问题。评估时还应该单独统计「薄云检出率」和「厚云边界准确率」。薄云是最容易漏检的类别边界则是最容易误检的区域。实验报告里给这两个指标单独开表比只报一个总指标更有说服力评分时老师看到的是你理解任务难点的证据。4. 实验报告的结构设计与消融实验真正拉开分数差距的地方4.1 高分实验报告的骨架问题定义、数据说明、方法、实验、结论一份能拿高分的实验报告不取决于模型多新而取决于叙事完整度。我习惯按五段式组织第一段写问题定义把卫星云层图像理解的任务明确为「逐像素云分类」而不是含糊的「识别云图」第二段写数据来源与统计明确数据量、类别分布、分辨率、预处理方式第三段写方法选型与理由说明为什么选 U-Net 而不是 FCN、为什么用预训练迁移而不是从零训练第四段写实验设计与结果包含消融实验、参数对比、定量表格与可视化第五段写结论与不足。每段都要回答一个「为什么」避免只堆结果不解释过程。数据统计表格是报告中容易被忽略但性价比很高的部分。把每个类别的训练样本像素占比、验证样本像素占比、样本图像数量列清楚既体现你对数据分布的理解也为后面类别不平衡的处理方式提供了依据。4.2 消融实验的设计把「为什么这样调」写成可验证的证据消融实验的价值在于证明每个设计决策都带来了可量化的提升。常见的做法是把关键模块逐个拆除对比我做的三组消融是去辐射定标 vs 保留辐射定标、单尺度输出头 vs 多尺度输出头、不加类别权重损失 vs 加类别权重损失。每组控制其他条件不变记录 mIoU 变化。结果表大概长这样实验设置mIoU晴空IoU水云IoU冰云IoU薄云IoU基线无定标单头无加权51.289.448.738.524.3辐射定标53.890.151.241.827.6多尺度输出头56.190.354.044.230.5类别加权损失58.487.657.349.135.2注意最后一行晴空 IoU 反而轻微下降这是正常现象类别权重把部分注意力转移到少数类晴空这类多数类难免让出一些性能。报告里主动讨论这个 trade-off比只展示提升更真实可信。4.3 可视化三件套原图、真实标签、预测对照图的可信度实验报告里的可视化不能只贴一张预测结果图。我使用三件套第一排原图预处理后的输入、第二排真实标签不同类别用不同色标、第三排预测结果与标签相同色标。色标统一类别颜色严格一致方便肉眼对照差异。对错误的区域要额外用白圈或黑框标出并在图下方写一句说明例如「左下角卷云区域预测为晴空可能原因该区域云层过薄红外通道响应弱于可见光通道」。训练曲线图保留两条线训练集 loss 和验证集 mIoU。loss 曲线波动大是正常的但 mIoU 应该持续上升或平台期波动。如果 mIoU 在 30 个 epoch 后开始明显下降而 loss 还在降说明过拟合需要在报告里写明如何通过早停或增强来应对。这种「处理过拟合」的讨论是最容易拿分的点。5. 卫星云图识别的避坑指南五条典型翻车现场与处理办法5.1 翻车一把可见光通道合成 RGB 直接训练验证集准确率始终上不去现象训练 loss 降得很漂亮验证集准确率卡在 72% 附近怎么加大模型容量都没有明显提升。原因可见光、红外通道的物理量纲不一致直接三通道合成后红外通道的动态范围被可见光通道压制模型实际只用了一个有效通道。解决对每个通道独立做辐射定标和 percent 拉伸后再合成验证集准确率直接提升约 5 个百分点。5.2 翻车二类别不平衡下 mIoU 虚高单独看薄云类别几乎全漏现象总体 mIoU 55% 以上但拆开看薄云 IoU 只有 12%训练集里薄云占比仅为 2%。原因默认交叉熵损失对多数类过度拟合少数类梯度贡献太小。解决给损失函数的类别权重按样本量倒数设置薄云权重拉高到 8.0 起步配合 cutmix 增强薄云 IoU 能拉到 30% 以上。注意权重过大会导致训练震荡需要配合验证集监控调节。5.3 翻车三resize 到 512×512 后显存耗尽训练中断现象单卡 11GB 显存跑 U-Net批量大小 16 直接 OOM。原因编码器特征图在深层次虽然分辨率低但通道数大中间变量占用极高。解决批量大小降到 8多尺度输出头只在最后两个尺度做融合而不是三个尺度全融合显存占用下降约 35%。分割任务对批量大小不敏感8 和 16 在 mIoU 上差异很小。5.4 翻车四训练集和验证集来自不同时次分布偏移导致验证集指标大幅波动现象同一个模型在训练时段的验证集上 mIoU 58%换一个时次的验证集掉到 41%。原因云层分布在不同气象条件下有系统性差异某时段多云、某时段少云模型学到的分布不具备时间泛化能力。解决按时间分折验证训练集和验证集不要随机切分而是按日期切分例如用前 70% 天训练、后 30% 天验证保证验证集分布更接近实际使用场景。这样得到的指标才是真实能力。5.5 翻车五分割结果出现整块区域的「椒盐噪声」后处理反而把有效碎云删掉了现象预测图上有大量零星孤立点设定 min_area16 后碎云区域也被一起删掉。原因模型对薄云边缘置信度低概率图在类别边界处震荡简单连通域剔除不区分碎云和噪声一刀切误伤。解决先用条件随机场CRF做平滑再按连通域面积过滤。CRF 的平滑系数设中等强度过强会把薄云整片抹平。实测 CRF 后处理让碎云保留率提升约 12%边界误检减少约 8%。6. 再往上走的进阶技巧伪彩色输入与多通道融合当基础流程跑通、指标稳定之后有一个改动不大但收益明显的技巧把单通道灰度输入扩展成伪彩色多通道输入。具体做法是把定标后的可见光反射率、红外亮温、亮温梯度场组合成三通道甚至扩展到四通道输入加上云顶高度场。云顶高度和云的相态有强关联高层冰云与低层水云在灰度上可能接近在高度场上差异明显让网络多一个物理维度去区分类别。我实验里对比过三通道灰度合成 vs 伪彩色反射率-亮温-温度梯度输入同一个 U-Net 结构在验证集上的 mIoU 从 58.4% 提升到 61.7%。代价是预处理代码复杂度增加需要在数据加载器里额外计算梯度场。这个技巧在实验报告的「讨论与改进」章节里写能让报告的深度上一个档次。梯度场计算用 Sobel 算子对亮温通道做卷积核大小 3 即可不需要更复杂的算子。归一化时注意梯度场数值范围与亮温差异很大需要单独做一次 standard scale 而不是和亮温共用一套归一化参数否则梯度信息会被亮温数值压制。输入通道增加后预训练权重不再适用第一层需要随机初始化。这时可以保留其他层的预训练权重只重新训练第一个卷积层收敛速度比全随机初始化快很多。这套流程走下来我的习惯是保留每一版实验的超参数记录特别是采样权重、增强组合和后处理参数。多次实验后你会发现这些参数之间的相互作用比单参数调优更重要。做得多了看到结果反常时你会先怀疑预处理和采样而不是急着换模型结构。这是我从项目里得到的最大教训。这个方向值不值得投入如果你的目标是一份经得起推敲的实验报告和一套能复用的视觉识别流程值得。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑