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

Posted

技术标签:

【中文标题】地面实况图像到一个热编码阵列(语义分割)【英文标题】:Ground Truth Image to One Hot Encoded Array (Semantic Segmentation) 【发布时间】:2020-01-02 02:08:04 【问题描述】:

我正在为人员和街道分割创建自己的数据集。下面,您会看到一个标记的地面实况 (GT) 图像。

过去我在模型输出和 GT Image 之间做了一个简单的回归(过去我只使用 Streets)。现在我读到,在这种情况下,交叉熵损失更为常见。因为,我的 GT 和模型输出图像具有与输入图像相同的宽度 w 和高度 h,所以我必须创建一个大小为 h x w x c,其中 c 是类的数量(在我的例子中是 3,背景、街道、人)。我想,这叫做 One-Hot-Encoded Array。

我解决了这个问题:

        for height in range(len(img_as_np_array)):
            for width in range(len(img_as_np_array[0])):
                temp = np.zeros(classes)
                if get_class(img_as_np_array[height,width]) == 1:
                    temp[1] = 1
                    one_hot_label[height,width] = temp
                if get_class(img_as_np_array[height,width]) == 2:
                    temp[2] = 1
                    one_hot_label[height,width] = temp

get_class(channels) 方法根据像素颜色决定像素类别。

def get_class(channels):
    threshold = 40
    # Class 1 corresponds to streets, roads
    if channels[0] in np.arange(243-threshold,243+threshold,1) and \
        channels[1] in np.arange(169-threshold,169+threshold,1) and \
        channels[2] in np.arange(0,threshold,1):
        return 1

    # Class 2 corresponds to people
    if channels[0] in np.arange(0,threshold,1) and \
        channels[1] in np.arange(163-threshold,163+threshold,1) and \
        channels[2] in np.arange(232-threshold,232+threshold,1):
        return 2

    # Class 0 corresponds to background respectively other things
    return 0

我有两个问题:

    我的方法很慢(全高清图像大约需要 3 分钟),有没有办法加快速度?

    我注意到颜色在通道值的意义上是不同的。例如,橙色应该是 [243,169,0] (RGB),但我发现像这样的条目 [206,172,8] 甚至是 [207,176,24] 会发生这种情况,因为我将标签存储为 jpg?有没有比我上面的阈值更好的方法来找到橙色和蓝色像素?

编辑:

我自己解决了第一个问题。全高清图像需要 2 或 3 秒:

threshold = 40
class_1_shape_cond_1 = (img_as_array[:, :, 0] >= 243 - threshold) * (img_as_array[:, :, 0] <= 243 + threshold)
class_1_shape_cond_2 = (img_as_array[:, :, 1] >= 171 - threshold) * (img_as_array[:, :, 1] <= 171 + threshold)
class_1_shape_cond_3 = (img_as_array[:, :, 2] >= 0) * (img_as_array[:, :, 2] <= threshold)
class_1_shape = (class_1_shape_cond_1 * class_1_shape_cond_2 * class_1_shape_cond_3)

然后我对第 2 类和第 3 类(我能做的一切)做同样的事情:

class_3_shape = 1 - (class_1_shape + class_2_shape)

之后我必须调整类型:

class_1_shape = class_1_shape.astype(np.uint8)
class_2_shape = class_2_shape.astype(np.uint8)
class_3_shape = class_3_shape.astype(np.uint8)

问题 2 仍然是一个开放的问题。

【问题讨论】:

【参考方案1】:

请勿将标签保存为 JPEG 图像!

jpeg 是一种lossy compression 方法 - 也就是说,它旨在使用更少的位保存图像,即使它改变了一点像素值,只要它对人类观察者“看起来不错”。 对于存储为图像的训练标签,情况并非如此!您不能承受标签中的不准确之处。您必须使用lossless compression 方法,例如png。

更好的是,将您的标签存储为 indexed RGB 图像开始,省去从 RGB 值推断离散标签的所有麻烦。

【讨论】:

【参考方案2】:

对于第一个问题 如果你使用的是 Tensorflow 框架,tf 提供了一个快速生成 one-hot 矩阵的功能。

tf.one_hot(
    indices,#your image with label
    depth, #the number of classes
    on_value=None,
    off_value=None,
    axis=None,
    dtype=None,
    name=None
)

更多详情,请参阅 (https://www.tensorflow.org/api_docs/python/tf/one_hot?version=stable)

【讨论】:

谢谢,我已经解决了,我正在使用 Pytorch。不过,很高兴知道。

以上是关于地面实况图像到一个热编码阵列(语义分割)的主要内容,如果未能解决你的问题,请参考以下文章

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

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

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

自然和医学图像的深度语义分割:网络结构

基于深度学习的图像语义分割方法综述

《基于深度学习的图像语义分割方法综述》阅读理解