用于语义分割的 PASCAL VOC 中的地面实况像素标签

Posted

技术标签:

【中文标题】用于语义分割的 PASCAL VOC 中的地面实况像素标签【英文标题】:Ground truth pixel labels in PASCAL VOC for semantic segmentation 【发布时间】:2018-09-12 18:31:06 【问题描述】:

我正在试验 FCN(全卷积网络),并试图重现原始论文(Long 等人 CVPR'15)中报告的结果。

在那篇论文中,作者报告了 PASCAL VOC 数据集的结果。下载并解压 2012 年的 train-val 数据集后 (http://host.robots.ox.ac.uk/pascal/VOC/voc2012/VOCtrainval_11-May-2012.tar ),我注意到 SegmentationClass 中有 2913 个 png 文件,而 SegmentationObject 子目录中有相同数量的文件。

这些 png 文件中的像素值似乎是 32 的倍数(例如 0、128、192、224...),它们不在 0 到 20 之间的范围内。我只是想知道什么是像素值和像素的地面实况标签之间的对应关系。还是我在看错误的文件?

【问题讨论】:

我最近复制了这些 FCN 结果,效果很好。你如何阅读你的图像?你调整它们的大小了吗?我曾经盲目地这样做,并且在调整大小时因为插值或平均值而弄乱了标签...... 你发现了吗?我也在原始字节数据中看到了很多 224 个值。我在彩色地图的任何地方都看不到 224。这是否意味着它们未定义? VOC_COLORMAP = [[0, 0, 0], [128, 0, 0], [0, 128, 0], [128, 128, 0], [0, 0, 128], [128, 0, 128] , [0, 128, 128], [128, 128, 128], [64, 0, 0], [192, 0, 0], [64, 128, 0], [192, 128, 0], [ 64, 0, 128], [192, 0, 128], [64, 128, 128], [192, 128, 128], [0, 64, 0], [128, 64, 0], [0, 192, 0], [128, 192, 0], [0, 64, 128]] 【参考方案1】:

我知道这个问题是不久前提出的。但是在尝试使用 tensorflow deeplab 的 PASCAL VOC 2012 时,我提出了一个类似的问题。

如果您查看file_download_and_convert_voc2012.sh,有几行标有“# Remove the colormap in ground truth annotations”。这部分处理原始SegmentationClass文件并生成原始分割图像文件,每个像素值在0:20之间。(如果您可能会问为什么,请查看此帖子:Python: Use PIL to load png file gives strange results)

注意这个神奇的功能:

def _remove_colormap(filename):
  """Removes the color map from the annotation.

  Args:
    filename: Ground truth annotation filename.

  Returns:
    Annotation without color map.
  """
  return np.array(Image.open(filename))

我不得不承认我并不完全理解

的操作
np.array(Image.open(filename))

我在下面展示了一组图像供您参考(从上到下:原始图像、分割类和分割原始类)

【讨论】:

【参考方案2】:

刚刚下载了 Pascal VOC。数据集中的像素值如下:

0:背景

[1 .. 20] 区间:分段对象,类 [Aeroplane, ..., Tvmonitor]

255:void 类别,用于边界区域(5px)和遮盖困难对象

您可以在数据集here 上找到更多信息。

船长之前的回答讨论了用调色板保存的png文件,我认为这与原始问题无关。链接的 tensorflow 代码只需加载一个使用颜色图(调色板)保存的 png,然后将其转换为 numpy 数组(在此步骤中调色板丢失),然后再次将数组另存为 png。在这个过程中数值不会改变,只是调色板被移除了。

【讨论】:

【参考方案3】:

原问题中提到的值看起来像“颜色图”值,可以通过getpalette()函数从PIL Image模块获得。

对于 VOC 图像的注释值,我使用以下代码片段来检查它们:

import numpy as np
from PIL import Image

files = [ 
        'SegmentationObject/2007_000129.png',
        'SegmentationClass/2007_000129.png',
        'SegmentationClassRaw/2007_000129.png', # processed by _remove_colormap()
                                                # in captainst's answer...
        ]

for f in files:
    img = Image.open(f)
    annotation = np.array(img)
    print('\nfile: \nanno: \nimg info: '.format(
        f, set(annotation.flatten()), img))

代码中使用的三张图片如下所示(分别从左到右):

代码对应的输出如下:

file: SegmentationObject/2007_000129.png
anno: 0, 1, 2, 3, 4, 5, 6, 255
img info: <PIL.PngImagePlugin.PngImageFile image mode=P size=334x500 at 0x7F59538B35F8>

file: SegmentationClass/2007_000129.png
anno: 0, 2, 15, 255
img info: <PIL.PngImagePlugin.PngImageFile image mode=P size=334x500 at 0x7F5930DD5780>

file: SegmentationClassRaw/2007_000129.png
anno: 0, 2, 15, 255
img info: <PIL.PngImagePlugin.PngImageFile image mode=L size=334x500 at 0x7F5930DD52E8>

我从上面的输出中学到了两件事。

首先,SegmentationObject文件夹中图像的标注值是由对象的个数来分配的。在这种情况下,有 3 个人和 3 辆自行车,标注的值是从 1 到 6。但是,对于 SegmentationClass 文件夹中的图像,它们的值由对象的类值分配。所有人都属于15级,所有的自行车都是2级

其次,正如mkisantal已经提到的,在np.array()操作之后,调色板被移除了(我通过观察结果“知道”它但我仍然不明白下面的机制引擎盖...)。我们可以通过检查输出的image mode 来确认这一点:

SegmentationObject/2007_000129.pngSegmentationClass/2007_000129.png 都有 image mode=P

SegmentationClassRaw/2007_000129.pngimage mode=L。 (参考:The modes of PIL Image)

【讨论】:

“我通过观察结果“知道”它,但我仍然不了解引擎盖下的机制......” - 保存颜色需要 3 个字节,一个用于 R,G,海滩。当你在整个数据集中只有 20 个类,即前景 20 种颜色和背景颜色 1 种时,每个像素只有 21 个唯一值,最多可以编码为 5 位(2^5=32)所以为什么使用 3 个字节。现在,这可以使用 PNG 图像来完成,您可以在其中存储 LUT,即查找颜色表。 如果您检查原始像素值,它会存储 0、1、20、255 等。但大多数图像查看器会读取图像,然后在这些值上应用 LUT 以获得红色。查找表仅使用 256 个颜色条目存储,即 0 映射到黑色,1 映射到颜色 X 等,并且此查找表存储在元数据中 最后,您可以通过运行identify -verbose &lt;imagepath&gt; 来检查图像元数据。标识是 imagemagick 命令并预装在 ubuntu 中 P.S.此 LUT 在 PIL 库中称为调色板

以上是关于用于语义分割的 PASCAL VOC 中的地面实况像素标签的主要内容,如果未能解决你的问题,请参考以下文章

地面实况图像到一个热编码阵列(语义分割)

用于语义分割的全卷积神经网络

如何为多类语义分割预处理 RGB 分割掩码?

如何将图像转换为数据集以进行语义分割

用于训练的线性变换输出和地面实况的损失

python 用于PASCAL VOC数据集的颜色映射函数的Python实现。