基于深度学习的多光谱图像语义分割 —— 从原理到实践(第三节)

上一节我们完成了数据加载、维度转换、多通道可视化和标签二分类。
然而,这些图像尺寸高达 9000×5000 像素以上,如果直接送入深度学习网络,单张图像就会撑爆 GPU 显存(甚至 CPU 内存也吃力)。
本节我们将学习 MATLAB 提供的分块图像(Blocked Image) 框架,轻松应对超大尺寸图像的处理与训练。


3. 分块图像与数据存储——让大图像训练不再困难

3.1 为什么要分块?

深度学习的训练过程通常需要将图像划分为小批量(mini‑batch),每批包含若干张固定尺寸的图像(例如 256×256)。对于普通大小的图像(如 224×224、512×512),这很简单。但对于遥感或医学影像这样的超高分辨率图像,直接整张送入网络会遇到两个问题:

  1. 内存/显存不足:一张 9393×5642×6 的图像(假设每个像素 float32)占用约 9393×5642×6×4 ≈ 1.27 GB,远超 GPU 显存。
  2. 计算量爆炸:卷积操作在大尺寸特征图上计算量极大,训练速度极慢。

因此,标准做法是将大图像切成若干小补片(Patch),每次只训练一个补片。这与卷积神经网络本身的滑动窗口思想一脉相承。通过随机采样补片,我们既降低了资源需求,又增加了训练样本的多样性(一张大图可产生成千上万个补片)。

3.2 MATLAB 的分块图像体系

MATLAB 从 R2019b 开始引入了 blockedImage 对象,专门用于处理无法一次性装入内存的大图像。它并不将整个图像数据加载到内存,而是只记录图像的尺寸、数据类型和文件位置,并按需从磁盘读取特定区域的数据块。配合 blockedImageDatastore,可以方便地迭代读取这些块,非常适合训练。

核心概念

  • 分块(Block):将大图像划分为规整的矩形小块(如 256×256 像素)。
  • 块位置集合(BlockLocationSet):记录所有有效块的行列索引,我们可以筛选出符合条件的块(例如避开纯背景区域)。
  • 数据存储(Datastore):MATLAB 的数据流接口,支持循环迭代、随机打乱、批量读取等。

3.3 将训练图像、标签、掩膜转换为分块图像

我们只使用前 6 个光谱通道作为网络输入(第 7 通道是掩膜,不作为特征输入),同时将训练标签和掩膜也转为分块图像。

设定补片尺寸为 256×256(这个大小可权衡精度和速度,通常 128~512 之间):

```matlab
inputTileSize = [256 256];
bim = blockedImage(train_data(:,:,1:6), BlockSize=inputTileSize);
bLabels = blockedImage(labelsTrain, BlockSize=inputTileSize);
bmask = blockedImage(maskTrain, BlockSize=inputTileSize);

此时 bim、bLabels、bmask 并没有真正读取数据,只是记录了图像的元信息和块划分方式。你可以通过 disp(bim) 查看其属性,例如 Size、BlockSize、NumBlocks 等。

3.4 选择有效的块——利用掩膜过滤

并不是所有块都值得训练。图像边界或飞行器边缘的无效区域(掩膜为 0)占比很高,如果这些块也被送入网络,会浪费计算资源并引入噪声。因此我们只选择那些有效像素占比大于 95% 的块。

为了实现这一点,我们需要生成一个“块位置集合”,即所有满足条件的块的行列索引。这里引入两个参数:

块偏移(BlockOffsets):相邻块之间的重叠像素数。适当重叠可以增加样本量,并让模型学习到边界附近的上下文信息(因为补片间有重叠,同一像素可能在多个补片中出现,相当于数据增强)。

重叠比例(overlapPct):这里设为 0.185,即 256×0.185 ≈ 47 像素的重叠。

matlab
overlapPct = 0.185;
blockOffsets = round(inputTileSize .* overlapPct);
bls = selectBlockLocations(bLabels, ...
    BlockSize=inputTileSize, BlockOffsets=blockOffsets, ...
    Masks=bmask, InclusionThreshold=0.95);

selectBlockLocations 会遍历所有可能的块位置(考虑偏移),并检查每个块中掩膜的有效像素比例,若 ≥ 0.95 则保留该位置。返回的 bls 是一个包含 BlockLocationSet 信息的结构体。

3.5 One‑Hot 编码标签

深度学习中,多分类问题的标签通常采用 one‑hot 编码(对于二分类也一样)。例如,类别 1 编码为 [1, 0],类别 2 编码为 [0, 1]。这样做是为了配合交叉熵损失函数,因为交叉熵期望预测输出是一个概率分布向量。

我们对整个标签图进行 one‑hot 编码,并将无效区域(掩膜外)设置为 NaN,这样在自定义损失函数中可以用 isnan 忽略这些位置。

matlab
labelsTrain1hot = onehotencode(labelsTrain, 3, ClassNames=1:2);
labelsTrain1hot(isnan(labelsTrain1hot)) = 0;   % 将 NaN 转为 0(但后续会用掩膜屏蔽)
bLabels = blockedImage(labelsTrain1hot, BlockSize=inputTileSize);

这里 onehotencode 的第 3 个维度是通道维,编码后每个像素变为长度为 2 的向量。

3.6 创建分块图像数据存储

现在我们需要将图像块和标签块配对,组成一个可迭代的数据源。blockedImageDatastore 可以从分块图像中按指定块位置集合读取数据,每次返回一个块(或者一批块)。

matlab
bimds = blockedImageDatastore(bim, BlockLocationSet=bls, PadMethod=0);
bimdsLabels = blockedImageDatastore(bLabels, BlockLocationSet=bls, PadMethod=0);

PadMethod=0 表示如果块不够大(例如边缘),不填充,但这些位置我们已通过掩膜筛选,所以不会出现无效块。

然后使用 combine 将两个数据存储合并成一个,训练时每次迭代会同时返回图像块和对应的标签块:

matlab
dsTrain = combine(bimds, bimdsLabels);

预览一个样本,验证数据形状:

matlab
preview(dsTrain)

输出类似:

text
ans=1×2 cell array
    256×256×6 uint16    256×256×2 double

这表明第一个元素是 256×256×6 的图像块(uint16 类型),第二个元素是同尺寸的标签块(double 类型,one‑hot 编码)。

数据存储的优势:

支持随机打乱(shuffle 方法),每轮训练可重新排列顺序。

支持 mini‑batch 批量读取(通过 read 或 readall)。

与 trainnet 无缝对接,可直接作为训练数据源。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.7 本节小结

在本节中,我们解决了大图像训练的核心难题——分块化。通过 MATLAB 的 blockedImage 框架,我们:

将大图像划分为 256×256 的小补片;

利用掩膜筛选出有效补片,避免无效区域干扰训练;

将标签进行 one‑hot 编码;

创建了可迭代的 CombinedDatastore,为后续网络训练做好了数据准备。

下一节,我们将正式构建 U‑Net 网络,并定义自定义损失函数和训练选项,然后启动训练(或直接加载预训练模型进行推理)。敬请期待第四节《U‑Net 构建与模型训练》。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐