如何在 Keras 中加载用于图像分割的图像遮罩(标签)

How to load Image Masks (Labels) for Image Segmentation in Keras

我正在使用 Tensorflow 作为 Keras 的后端,我正在尝试了解如何引入我的标签以进行图像分割训练。

我正在使用 LFW Parts Dataset,它同时具有地面实况图像和地面实况掩模,看起来像这样 * 1500 个训练图像:

据我了解,在训练过程中,我同时加载了

分批进行,满足我的需求。现在我的问题是,将它们(图像和蒙版图像)都加载为 NumPy 数组(N、N、3)是否足够,或者我是否需要以某种方式 process/reshape 蒙版图像。实际上,mask/labels 表示为 [R, G, B] 像素,其中:

我可以做这样的事情来将它归一化为 0-1,但我不知道是否应该这样做:

im = Image.open(path)
label = np.array(im, dtype=np.uint8)
label = np.multiply(label, 1.0/255)

所以我最终得到:

我在网上找到的所有内容都使用 tensorflow 或 keras 中的现有数据集。如果您拥有可以被视为自定义数据集的内容,那么对于如何完成任务,没有什么是真正清楚的。

我发现这与 Caffe 有关:https://groups.google.com/forum/#!topic/caffe-users/9qNggEa8EaQ

他们提倡将蒙版图像转换为 (H, W, 1) (HWC)?其中我的 类 将分别 0, 1 ,2 用于背景、头发和面部。

这里可能是重复的(类似quesiton/answers的组合):

How to implement multi-class semantic segmentation?

Tensorflow: How to create a Pascal VOC style image

我发现了一个将 PascalVOC 处理成 (N, N, 1) 的示例,我对其进行了改编:

LFW_PARTS_PALETTE = {
    (0, 0, 255) : 0 , # background (blue)
    (255, 0, 0) : 1 , # hair (red)
    (0, 0, 255) : 2 , # face (green)
}

def convert_from_color_segmentation(arr_3d):
    arr_2d = np.zeros((arr_3d.shape[0], arr_3d.shape[1]), dtype=np.uint8)
    palette = LFW_PARTS_PALETTE

    for i in range(0, arr_3d.shape[0]):
        for j in range(0, arr_3d.shape[1]):
            key = (arr_3d[i, j, 0], arr_3d[i, j, 1], arr_3d[i, j, 2])
            arr_2d[i, j] = palette.get(key, 0) # default value if key was not found is 0

    return arr_2d

我认为这可能接近我想要的但不准确。我想我需要它是 (N, N, 3) 因为我有 3 类?以上版本和另一个版本来自这两个位置:

https://github.com/martinkersner/train-CRF-RNN/blob/master/utils.py#L50

https://github.com/DrSleep/tensorflow-deeplab-resnet/blob/ce75c97fc1337a676e32214ba74865e55adc362c/deeplab_resnet/utils.py#L41(这个 link one-hot 的值)

Keras 要求标签进行单热编码。所以你的输入必须是 (N x N x n_classes) 维度。

由于这是语义分割,您要对图像中的每个像素进行分类,因此您很可能会使用交叉熵损失。 Keras 以及 TensorFlow 要求您的掩码是一个热编码的,而且,您的掩码的输出维度应该类似于 [batch, height, width, num_classes] <- 你将不得不重塑与计算交叉熵掩码之前的掩码相同,这实际上意味着您必须将 logits 和掩码重塑为张量形状 [-1, num_classes],其中 -1 表示 'as many as required'。

Have a look here at the end

由于你的问题是关于加载你自己的图像,我刚刚自己构建了一个用于分割的输入管道,虽然它是在TensorFlow中,所以我不知道它是否对你有帮助,如果你有兴趣看看: Tensorflow input pipeline for segmentation

我遇到了同样的问题,我想出了一个纯 Tensorflow 解决方案,它将 RGB 值从加载的蒙版图像 (128,128,3) Tensor 转换为 128x128 RGB 图像的 (128,128) Tensor,其中 Tensor在区间 [0...number_of_classes] 中编码 class.. 请看我的博文:https://www.spacefish.biz/2020/11/rgb-segmentation-masks-to-classes-in-tensorflow/

您也可以通过省略最后一个“tf.argmax”步骤来获得单热编码张量,例如 (128,128,number_of_classes)。