遥感图像分类,尤其是基于深度学习的遥感图像语义分割和场景分类,是这几年本科毕设和研究生课题里出现频率很高的方向。它同时涉及图像处理、深度学习、地学应用三块知识,看起来门槛高,但把流程拆开之后,核心就是四个环节:数据准备、模型选择、训练调参、结果评估。下面直接按这个顺序写。适合正在选毕设方向、已经选了遥感影像分类但还没跑通代码、或者跑通了但精度一直上不去的人看。先说几个比较重要的判断:第一,遥感图像分类和普通自然图像分类不一样,不能直接把 ImageNet 的流程原样搬过来;第二,环境搭建和数据集准备通常比模型代码更耗时间;第三,很多人训练没效果,不是网络结构问题,而是标签、通道数、裁切尺寸这些基础设置出了问题。
1. 先分清任务类型:场景分类、语义分割、目标检测不能混着做
1.1 三种任务的区别直接决定数据格式和评价指标
遥感图像分类在论文和竞赛里通常分三类,很多人一开始没有区分,后面做起来才发现数据格式、模型选型和指标全都不一样。
| 任务类型 | 输出是什么 | 典型应用 | 常用网络 |
|---|---|---|---|
| 场景分类 | 整张影像一个类别 | 土地利用类型、地物粗分类 | ResNet、EfficientNet |
| 语义分割 | 每个像素一个类别 | 建筑物提取、水体提取、滑坡识别 | U-Net、SegFormer |
| 目标检测 | 目标框加类别 | 飞机、舰船、车辆检测 | YOLO、Faster R-CNN |
场景分类最简单,一张图判断它是农田、城市还是水体,本质是图像分类,入门最快。语义分割是遥感应用里价值最高的方向,因为它能画出地物的精确边界,比如滑坡范围、建筑物轮廓、农作物种植区域,做毕设时展示效果最直观。目标检测用在特定目标识别上,数据标注成本最高。
我见过不少同学一开始说“我要做遥感图像分类”,但实际想看的效果是“把图里的建筑物精确圈出来”,这其实是语义分割。方向没定,后面选网络、写代码、做评估都会别扭。所以第一步不是装环境,而是先确定你要的是哪一类输出。建议把题目里的动词抠出来:要的是“识别整张图属于什么”,还是“逐像素标出地物范围”,还是“找出一辆车的位置”。
1.2 为什么遥感图像不能照搬自然图像的做法
自然图像分类任务里,目标通常占图面比例大、尺度稳定,比如猫、狗、飞机。遥感图像完全不同:地物密集、尺度差异大、方向随机,同一个物体在 0.5 米分辨率和 10 米分辨率下长得完全不一样。
这个差异会直接影响两件事。第一,图像裁切方式。深度学习框架处理遥感影像时,不会把一张上万像素的大图直接塞进网络,而是切成 256×256、512×512 的瓦片输入,避免显存爆炸,同时增加样本数量。第二,数据增强策略。自然图像常用的随机水平翻转、随机裁剪,在遥感里依然有效,但旋转增强特别重要,因为遥感图像没有绝对的正立方向,飞机、房屋可能出现在任何角度。
另外,遥感图像经常是多光谱数据,比如 R、G、B、NIR 四个波段。很多教程默认只取 RGB 三通道,模型能跑,但会丢掉近红外信息。近红外对植被、水体识别非常有用,比如区分树木和水体时,光谱差异主要在近红外波段。所以预处理阶段要确认数据是几通道,模型第一层卷积也要对应调整,不能直接用预训练权重时想当然。
2. 环境搭建和数据集准备是第一个分水岭
2.1 硬件和软件环境怎么选
先说结论:跑通一个单卡训练,不需要很高的配置;但要舒服地做实验,显存至少建议 8GB 以上。
我建议的环境组合是 Python 3.8 或 3.10,深度学习框架以 PyTorch 为主,配合 torchvision 做基础图像变换。为什么优先 PyTorch 而不是 TensorFlow 或 PaddlePaddle?不全是因为性能,而是排查资料方便、调试直观、开源项目占比高。如果你在实验室或学校服务器上能用到 NVIDIA 显卡,优先安装 CUDA 版本;只有 CPU 也能跑,但训练速度会慢很多,建议把输入尺寸和 batch size 调小。
安装时最容易出问题的是 CUDA 和 cuDNN 版本不匹配。这里给一个稳妥做法:先确认 PyTorch 官方支持哪个 CUDA 版本,再安装对应驱动,不要单独下载最新版 CUDA。装完用几行代码验证:
import torch print(torch.__version__) print(torch.cuda.is_available()) print(torch.cuda.get_device_name(0) if torch.cuda.is_available() else "CPU")如果torch.cuda.is_available()返回 False,多数是 PyTorch 和 CUDA 版本不匹配,或者环境变量没生效。这个时候先不要重装系统,也不要反复卸载 PyTorch,先检查驱动版本和虚拟环境是否激活。这种问题看起来吓人,实际大部分是环境变量路径顺序导致的。
遥感影像处理还需要专门的读写库。深度学习环境是 Python、CUDA、框架,这一层比较固定;遥感影像层还需要 GDAL、rasterio、OpenCV 这些库,用来读取 tif 格式影像和标注文件。
pip install torch torchvision rasterio opencv-pythonWindows 下 GDAL 直接用 pip 安装偶尔会失败。如果卡住,可以用rasterio代替,读取 GeoTIFF 足够使用。不要在这个环节耗太久,能读取数据、能显示图片就达到目标,后面真正耗时的是数据检查。
2.2 数据集从哪里找
数据集选择直接决定结果上限。常见来源有三类:
- 公开遥感数据集:比如武汉大学发布的滑坡遥感影像数据集,带像素级标注,适合做特定任务的论文实验。
- 竞赛数据集:很多算法竞赛会公开训练集,类别覆盖广,适合练手。
- 自建标注:用 LabelMe 或 QGIS 手工勾画地物,适合小范围实验,但时间成本高。
现在关于高精度遥感、遥感影像深度学习框架搭建的讨论很多,很多人其实是在找一条完整链路。完整链路就一句话:读取影像、切瓦片、构建 Dataset、定义模型、训练、评估、输出预测图。数据是这条链路的起点,也是后面所有问题的高发区。
拿到数据集后要做的第一件事不是训练,而是完整检查数据。我一般会写一个简单统计脚本,确认影像和标签数量一致、尺寸一致、类别数符合预期。
import os from PIL import Image img_dir = "images" label_dir = "labels" imgs = sorted(os.listdir(img_dir)) labels = sorted(os.listdir(label_dir)) print(len(imgs), len(labels)) assert len(imgs) == len(labels) img = Image.open(os.path.join(label_dir, labels[0])) print(img.mode, img.size, set(img.getdata()))这一步能提前发现大量问题:标签是 RGB 格式而不是单通道、类别编号不连续、图片尺寸不一致。这些问题在训练时都会变成“loss 不下降”或“输入维度错误”之类的报错,而且非常难定位。先花十分钟做数据检查,比后面排查两小时要划算。
2.3 标注和预处理怎么做
遥感图像标注的难点在于边界精细度和类别不平衡。比如滑坡边界,不同人标出来范围差异明显。如果使用公开数据集,这个问题已经处理好了;如果是自建数据,建议至少两个人交叉检查,避免标注噪声太大。
预处理里最容易忽略的是归一化方式。遥感影像像素值范围可能是 0 到 255,也可能是 0 到 10000 的反射率值。深度学习模型一般期望输入在 0 到 1 之间,或者按均值和方差做标准化。如果直接把原始数值输入,网络前几层的梯度很容易爆炸,表现为 loss 直接变成 nan 或者一开始就特别大。
还有一个细节是裁切重叠。大影像切成瓦片时,如果目标地物恰好被切在边缘,很多训练样本只包含目标的一小部分,模型很难学到完整形状。更合理的做法是设置一定比例的重叠区域,或者让裁切窗口的中心尽量落在有标签的区域内。这样能显著提升小目标地物的分割效果。
3. 模型选型:不用一上来就追新
3.1 从 U-Net 起步,再到 SegFormer
模型选型我推荐一条比较稳的路线,而不是一上来就选最新最重的网络:
- 入门首选 U-Net。结构简单,训练数据要求不高,语义分割效果稳定。
- 进阶考虑 SegFormer。基于 Transformer 的分割模型,对全局上下文建模能力强,在遥感数据上表现通常优于纯 CNN,但显存占用更高。
- 场景分类任务用 ResNet、EfficientNet 系列就好,预训练权重多,调参成本低。
为什么遥感语义分割经常选 U-Net?因为遥感地物边界和细节重要,U-Net 的编码器-解码器结构配合跳跃连接,能把下采样过程中丢失的细节恢复回来。SegFormer 的优点是感受野大,能捕捉大范围地物之间的关系。比如大面积水域和阴影在局部光谱上很相似,单靠局部卷积容易误判,但引入全局上下文后就能区分开。
有些同学把“效果最好的网络”理解为“越新越好、参数量越大越好”,结果把训练时间拖到几天,精度却没有明显提升。毕设实验不追求极端性能,用 U-Net 做 baseline,再用 SegFormer 或改进结构做对比,这组前后对比本身就很有说服力。
3.2 预训练权重要不要用
能用就用。尤其是在遥感数据量不大时,在 ImageNet 上预训练过的骨架能明显加快收敛,也能提升最终精度。但要注意一个边界:遥感图像和自然图像分布差异大,迁移效果往往不如“用遥感大数据预训练”的模型明显。现在也有一些开源的遥感预训练模型库,可以优先尝试;如果找不到合适的,直接用 ImageNet 预训练的 ResNet 作为编码器,也一定比随机初始化好。
预训练权重还牵涉到输入尺寸问题。很多预训练模型默认输入 224×224,如果你的训练裁切尺寸是 512×512,CNN 一般可以自适应,但 Transformer 的位置编码可能有尺寸限制。SegFormer 整体比较灵活,不过部分实现版本也有输入约束,实验前先把模型源码里的尺寸判断看清楚。
4. 训练流程和核心参数设置
4.1 数据划分要按区块走
遥感图像分类的数据划分比普通分类更讲究。只按文件列表随机划分,很可能出现同一块区域的瓦片同时出现在训练集和验证集,导致验证分数虚高。因为相邻瓦片内容高度相似,模型等于提前偷看了答案。
更稳妥的做法是按片区划分:同一场景的瓦片不要同时出现在训练集和测试集,避免空间相关性造成信息泄漏。很多遥感竞赛会在规则里明确说明这一点。如果数据来自几个不同的城市或地块,最好按场景分组划分。数据比例上,我一般用 8:1:1 或 7:2:1,验证集用来调超参数,测试集只保留到最后做一次评估。
4.2 关键训练参数怎么设
| 参数 | 新手建议 | 说明 |
|---|---|---|
| 输入尺寸 | 256×256 或 512×512 | 尺寸越大显存占用越高 |
| batch size | 8 到 16 | 显存不足时优先减小 batch |
| 学习率 | 1e-4 到 1e-3 | 使用预训练权重时可适当降低 |
| epoch | 50 到 100 | 结合验证集 loss 决定 |
| 优化器 | AdamW 或 SGD | Adam 系收敛快,SGD 调好后更稳 |
学习率是最容易出问题的参数。学习率太大,loss 会震荡不下降;太小,训练几十个 epoch 都没什么变化。我一般先把学习率设为 1e-4,跑 10 个 epoch,看训练集 loss 是否稳定下降,再决定调大还是调小。调参时一次只改一个参数,不要同时改学习率和 batch size,否则出了问题根本不知道是哪个引起的。
不要一上来就把 batch size 拉满。先用 4 或 8 跑通一次完整训练,确认显存不溢出、数据加载正常,再逐步加大。
4.3 数据增强怎么配
遥感图像分类里常用的增强包括:
- 随机水平翻转和垂直翻转
- 随机旋转 90 度、180 度、270 度
- 随机亮度、对比度调整
- 随机裁剪和缩放
旋转增强对遥感特别重要,因为遥感图像没有绝对正立方向。但要注意:如果任务是识别特定方向的目标,比如检测某类朝向固定的设施,旋转增强反而会破坏语义,这种情况下要谨慎使用。
还有一个经常被忽略的点:增强策略在验证和测试阶段要保持一致。验证集和测试集不要做随机增强,只做 resize 或 pad,否则评估结果不稳定。很多人训练时 mIoU 看着不错,测试时忽高忽低,多半是这里出了偏差。
5. 结果评估不能只看一个准确率
5.1 指标按任务分
场景分类任务看 accuracy 基本够用。语义分割任务则要看 mIoU、F1、Kappa 系数,其中 mIoU 是最普遍的核心指标。
mIoU 是预测区域和真实区域的交并比在所有类别上的平均值。如果只报准确率,在类别不平衡时会被严重误导。比如一张遥感图里 90% 是背景,10% 是建筑物,模型全预测成背景,准确率也有 90%,但建筑物提取这个任务做得毫无意义。所以毕设论文里,语义分割至少报告 mIoU 和每个类别的 IoU,必要时加混淆矩阵。
5.2 可视化结果怎么展示
指标之外,一定要输出预测图。常见的论文可视化方式是把三张图并排展示:
第一列是原始遥感影像,第二列是真实标签,第三列是模型预测结果。预测结果可以用不同颜色映射表示不同类别。这种三列对比图在论文里最直观,评审也最容易看懂。
我建议除了最终结果,还要保存训练过程中部分中间预测图。比如每个 epoch 结束后在验证集上生成一张预测图,能直观看到模型是逐步变好还是出现退化,比只盯 loss 曲线有用得多。
如果预测结果出现很多散点噪声,也就是零星像素被分为其他类别,可以尝试后处理:用形态学开运算、闭运算去除小碎块,或者用条件随机场做平滑。后处理能明显提升视觉质量,但论文里要说明用了什么方法、参数怎么设置。
5.3 错误分析必须做
很多同学训练完只看总指标,完全不看错在哪里。我一般会做两件事:
- 看混淆矩阵,找出哪两个类别经常互相混淆。比如阴影和水体在光谱特征上非常接近,是遥感分割里的经典误判组合。
- 挑典型错误样本,把预测错误的图像单独保存,统计错误集中在哪些地物上。
这一步对毕设答辩特别有帮助。老师问“你这个方法还能怎么改进”,你如果能说清楚“主要误差来自阴影和水体的混淆,下一步考虑加入近红外信息或地形特征”,这个回答的含金量会明显高于“我打算换一个更强的模型”。
6. 常见报错和排查顺序
6.1 按优先级排查,不要看到报错就重装
训练过程中遇到报错,建议按这个顺序排查:
- 先看报错类型和位置:是数据读取、模型结构,还是张量维度。
- 再看输入输出:图片路径是否正确、标签类别是否连续、尺寸是否匹配。
- 再看环境:依赖版本、CUDA 是否可用、显存是否充足。
- 最后看参数:batch size、学习率、输入尺寸、类别数是否设置合理。
绝大多数报错不是模型写法的问题,而是数据和环境。看到CUDA out of memory不要第一时间怪显卡,先确认 batch size 是不是太大、输入尺寸是不是超出预期。
6.2 高频问题整理
| 现象 | 常见原因 | 处理建议 |
|---|---|---|
| CUDA out of memory | batch 太大或输入尺寸太大 | 减小 batch、降低输入尺寸、开启梯度累积 |
| loss 一直不下降 | 学习率不合适、标签全为背景、数据未归一化 | 先跑小样本、打印标签分布、调低学习率 |
| 输出全是一个类别 | 类别不平衡、模型欠拟合 | 检查训练集类别比例,尝试加权损失函数 |
| 预测图尺寸和原图不一致 | 裁切和拼接逻辑有误 | 记录瓦片坐标,拼接时按坐标回填 |
| 读取 tif 报错 | 通道数或压缩格式不支持 | 用 rasterio 检查元数据,必要时转成 PNG |
6.3 一个典型排查案例
我遇到过最典型的案例:训练 50 个 epoch 后,验证集 mIoU 只有 0.3 左右,怎么调都上不去。第一反应是网络不够强,换了更强的结构也没有明显变化。后来去检查数据,发现标注图是用 RGB 格式保存的,但代码按单通道读取,三通道的重复数值导致一个类别被映射成多个类别编号,类别数量凭空多了好几倍。把标注图转成单通道灰度图之后,mIoU 直接提升到 0.6 以上。
这个案例说明,训练问题很多时候不在模型和参数,而在数据格式。无论遇到什么报错,先确认输入数据长什么样,再动其他部分。这个顺序可以帮你省掉很多无效调参。
7. 毕设落地的整体建议
7.1 时间规划怎么排
如果做遥感图像深度学习方向的毕设,建议把时间分成四段:
- 第一到两周:确定任务类型,下载数据集,搭建环境,跑通一个官方 Demo。
- 第三到四周:完成数据处理代码、训练脚本、评估脚本,跑出第一版结果。
- 第五到八周:调参、换模型、做消融实验,记录每轮实验指标。
- 最后一个月:整理论文图表,补充对比实验,准备答辩。
第一版结果不用等所有配置都完美。先把最简单的 U-Net 跑通,后面换 SegFormer 或 ResNet 都只是替换模型文件的事。如果你卡在环境搭建超过三天,建议直接换环境方案,比如改用云 GPU 实例或学校服务器,不要和自己较劲。
7.2 实验记录比调参更重要
跑深度学习实验一定要记录每次实验的配置和结果,包括数据版本、模型结构、学习率、batch size、增强策略、训练耗时、最终指标。否则两周后你根本记不清哪个结果是用什么配置跑出来的。
建议建一个简单的表格文件,每次实验加一行。毕设论文里的实验对比表,就是从这些记录里整理出来的。前期不记录,后期补记录会非常痛苦,甚至会因为找不到关键实验而重跑一遍。
7.3 什么样的结果算比较稳
不同任务类型的合格线不一样:
- 场景分类:准确率能达到 90% 以上,通常算不错。
- 语义分割:mIoU 达到 0.6 到 0.8 属于常见水平;如果能到 0.8 以上,已经可以作为一个亮点写进论文。
- 目标检测:mAP 达到 0.5 到 0.7 比较正常。
要注意,不同数据集难度差异很大,不能只看绝对值。同一个模型在二分类数据集上 mIoU 可能达到 0.9,在复杂多类别数据集上可能只有 0.5。写论文时把数据集来源、类别数、图像尺寸、评价协议交代清楚,比单报一个数字更有说服力。
这几年的经验反复验证同一件事:遥感图像分类的难点不在“深度学习”这几个字,而在数据和工程细节。环境装好了、数据检查干净了、参数不激进,模型基本都能跑出合理结果。如果你正准备拿这个方向做毕设,先把最小的单任务流程跑通,再逐步增加数据规模和模型复杂度。跑通一次完整实验之后,剩下的问题和优化路径会清晰很多。