语义分割和数据集
语义分割和数据集
在 边界框— 区域卷积神经网络(R-CNN)中讨论的目标检测问题中,我们一直使用方形边界框来标注和预测图像中的目标。
本节将探讨语义分割(semantic segmentation)问题,它重点关注于如何将图像分割成属于不同语义类别的区域。
与目标检测不同,语义分割可以识别并理解图像中每一个像素的内容:其语义区域的标注和预测是像素级的。
fig_segmentation展示了语义分割中图像有关狗、猫和背景的标签。
与目标检测相比,语义分割标注的像素级的边框显然更加精细。
(图:语义分割中图像有关狗、猫和背景的标签)
图像分割和实例分割
计算机视觉领域还有2个与语义分割相似的重要问题,即图像分割(image segmentation)和实例分割(instance segmentation)。
我们在这里将它们同语义分割简单区分一下。
- 图像分割将图像划分为若干组成区域,这类问题的方法通常利用图像中像素之间的相关性。它在训练时不需要有关图像像素的标签信息,在预测时也无法保证分割出的区域具有我们希望得到的语义。以 fig_segmentation中的图像作为输入,图像分割可能会将狗分为两个区域:一个覆盖以黑色为主的嘴和眼睛,另一个覆盖以黄色为主的其余部分身体。
- 实例分割也叫同时检测并分割(simultaneous detection and segmentation),它研究如何识别图像中各个目标实例的像素级区域。与语义分割不同,实例分割不仅需要区分语义,还要区分不同的目标实例。例如,如果图像中有两条狗,则实例分割需要区分像素属于的两条狗中的哪一条。
Pascal VOC2012 语义分割数据集
最重要的语义分割数据集之一是Pascal VOC2012。
下面我们深入了解一下这个数据集。
1 | %matplotlib inline |
数据集的tar文件大约为2GB,所以下载可能需要一段时间。
提取出的数据集位于../data/VOCdevkit/VOC2012。
1 | #@save |
进入路径../data/VOCdevkit/VOC2012之后,我们可以看到数据集的不同组件。ImageSets/Segmentation路径包含用于训练和测试样本的文本文件,而JPEGImages和SegmentationClass路径分别存储着每个示例的输入图像和标签。
此处的标签也采用图像格式,其尺寸和它所标注的输入图像的尺寸相同。
此外,标签中颜色相同的像素属于同一个语义类别。
下面将read_voc_images函数定义为将所有输入的图像和标签读入内存。
1 | #@save |
1 | #@save |
下面我们绘制前5个输入图像及其标签。
在标签图像中,白色和黑色分别表示边框和背景,而其他颜色则对应不同的类别。
1 | n = 5 |
1 | n = 5 |
接下来,我们列举RGB颜色值和类名。
1 | #@save |
通过上面定义的两个常量,我们可以方便地查找标签中每个像素的类索引。
我们定义了voc_colormap2label函数来构建从上述RGB颜色值到类别索引的映射,而voc_label_indices函数将RGB值映射到在Pascal VOC2012数据集中的类别索引。
1 | #@save |
1 | #@save |
例如,在第一张样本图像中,飞机头部区域的类别索引为1,而背景索引为0。
1 | y = voc_label_indices(train_labels[0], voc_colormap2label()) |
预处理数据
在之前的实验,例如 深度卷积神经网络(AlexNet)— sec_googlenet中,我们通过再缩放图像使其符合模型的输入形状。
然而在语义分割中,这样做需要将预测的像素类别重新映射回原始尺寸的输入图像。
这样的映射可能不够精确,尤其在不同语义的分割区域。
为了避免这个问题,我们将图像裁剪为固定尺寸,而不是再缩放。
具体来说,我们使用图像增广中的随机裁剪,裁剪输入图像和标签的相同区域。
1 | #@save |
1 | #@save |
1 | imgs = [] |
1 | imgs = [] |
自定义语义分割数据集类
我们通过继承高级API提供的Dataset类,自定义了一个语义分割数据集类VOCSegDataset。
通过实现__getitem__函数,我们可以任意访问数据集中索引为idx的输入图像及其每个像素的类别索引。
由于数据集中有些图像的尺寸可能小于随机裁剪所指定的输出尺寸,这些样本可以通过自定义的filter函数移除掉。
此外,我们还定义了normalize_image函数,从而对输入图像的RGB三个通道的值分别做标准化。
1 | #@save |
读取数据集
我们通过自定义的VOCSegDataset类来分别创建训练集和测试集的实例。
假设我们指定随机裁剪的输出图像的形状为$320\times 480$,
下面我们可以查看训练集和测试集所保留的样本个数。
1 | crop_size = (320, 480) |
设批量大小为64,我们定义训练集的迭代器。
打印第一个小批量的形状会发现:与图像分类或目标检测不同,这里的标签是一个三维数组。
1 | batch_size = 64 |
整合所有组件
最后,我们定义以下load_data_voc函数来下载并读取Pascal VOC2012语义分割数据集。
它返回训练集和测试集的数据迭代器。
1 | #@save |
小结
- 语义分割通过将图像划分为属于不同语义类别的区域,来识别并理解图像中像素级别的内容。
- 语义分割的一个重要的数据集叫做Pascal VOC2012。
- 由于语义分割的输入图像和标签在像素上一一对应,输入图像会被随机裁剪为固定尺寸而不是缩放。