Tensorflow U-Net多类标签

时间:2018-12-03 20:53:56

标签: python tensorflow unity3d-unet

我是Stackoverflow的新手,所以对任何典型的新手错误深表歉意。

我想在Python和Tensorflow中建立具有U-Net架构的CNN。我尝试重用一些可以用于二进制分类的代码,并希望对其进行修改以检测3个类。我得到的代码非常适合2个输出层,其中有一个二进制图像作为标签groundtruth。

现在我的问题是:是否有任何约定使多类标签看起来像?我是否应该只使用一层(灰度)的labelimage,为我的不同类(例如0、127、255)使用三个值?还是应该为每个类别使用一种颜色的rgb图像(例如,类别0为255、0、0;类别1为0、255、0,依此类推...)?

""" 0) Creating placeholders for input images and labels """
# Placeholder for input images
x = tf.placeholder(tf.float32, [None, 3*img_size]) # None = arbitrary (Number of images)
# Arrangeing images in 4D format
x_shaped = tf.reshape(x, [-1, img_height, img_width, 3]) # 3 for 3 channels RGB
# Placeholder for labels of input images (ground truth)
y = tf.placeholder(tf.float32, [None, 2*img_size])
# Arrangeing labels in 4D format
y_shaped = tf.reshape(y, [-1, img_size, 2])


""" 1) Defining FCN-8 VGGNet-16 """
network = conv_layer(x_shaped, 64, filter_size=[3, 3], name='conv1a')
network = conv_layer(network, 64, filter_size=[3, 3], name='conv1b')
network = max_pool_layer(network, name='pool1')

network = conv_layer(network, 128, filter_size=[3, 3], name='conv2a')
network = conv_layer(network, 128, filter_size=[3, 3], name='conv2b')
network = max_pool_layer(network, name='pool2')

network = conv_layer(network, 256, filter_size=[3, 3], name='conv3a')
network = conv_layer(network, 256, filter_size=[3, 3], name='conv3b')
network = conv_layer(network, 256, filter_size=[3, 3], name='conv3c')
network = max_pool_layer(network, name='pool3')
net_pool3 = network

network = conv_layer(network, 512, filter_size=[3, 3], name='conv4a')
network = conv_layer(network, 512, filter_size=[3, 3], name='conv4b')
network = conv_layer(network, 512, filter_size=[3, 3], name='conv4c')
network = max_pool_layer(network, name='pool4')
net_pool4 = network

network = conv_layer(network, 512, filter_size=[3, 3], name='conv5a')
network = conv_layer(network, 512, filter_size=[3, 3], name='conv5b')
network = conv_layer(network, 512, filter_size=[3, 3], name='conv5c')
network = max_pool_layer(network, name='pool5')

network = deconv_layer(network, 256, filter_size=[3, 3], name='deconv1')
network = tf.concat([network, net_pool4], 3)
network = conv_layer(network, 256, filter_size=[5, 5], name='conv6')

network = deconv_layer(network, 128, filter_size=[3, 3], name='deconv2')
network = tf.concat([network, net_pool3], 3)
network = conv_layer(network, 128, filter_size=[5, 5], name='conv7')

# in the next lines I would have to change 2 into 3 to get 3 output classes
network = deconv_layer(network, 2, filter_size=[7, 7], strides=[8, 8], name='deconv3')
network = conv_layer(network, 2, filter_size=[7, 7], activation=' ', name='conv8')
y_ = tf.nn.softmax(network)

计算后,我会生成输出图像(在测试阶段,训练完成后)

for i in range(rows):
    for j in range(cols):
        for k in range(layers):
            imdata[i*img_height:(i+1)*img_height, j*img_width:(j+1)*img_width, k] = cnn_output[cols*i+j, :, :, k]
imdata = imdata[0:im.height, 0:im.width]
for row in range(real_height):
            for col in range(real_width):
                if(np.amax(imdata[row,col,:]) == imdata[row,col,0]):
                    imdata[row,col,:] = 255, 0, 0
                elif(np.amax(imdata[row,col,:]) == imdata[row,col,1]):
                    imdata[row,col,:] = 0, 255, 0
                else:
                    imdata[row,col,:] = 0, 0, 255
                #img[row][col] = imdata[row][col]
        # Save the image
        scipy.misc.imsave(out_file, imdata)
        im.close()

imdata具有3层(1080、1920、3)图像的形状。

2 个答案:

答案 0 :(得分:0)

分类标签通常是一个向量,其中每个元素代表一个类:

class A: [1, 0, 0]
class B: [0, 1, 0]
class C: [0, 0, 1]

原因是您网络的输出是一个softmax函数,它将产生一个介于0和1之间的值的向量。它可以输出[0.1, 0.1, 0.8]。这些值将总为1,因此使用softmax假定图片上的每个像素只能属于一个类别,因为增加一个类别的网络输出会降低其他类别的输出。

在细分中,将一个类分配给每个点,因此您的输入现在是3*img_size而不是2*img_size

# Placeholder for labels of input images (ground truth)
y = tf.placeholder(tf.float32, [None, 3*img_size])
# Arranging labels in 4D format
y_shaped = tf.reshape(y, [-1, img_size, 3])


对于输出:

我假设cnn_output仅包含一张图片的输出,而不包含整个批次的图片。

您需要找出哪个班的分数最高。 np.argmax可以帮助您:

class_index = np.argmax(cnn_output, axis=2)

class_index现在包含分数最高的班级编号。 (如果cnn_output仅是二维的,请将axis设置为1。)接下来,您需要将这些值映射为颜色:

colors = {0 : [255, 0, 0], 1 : [0, 255, 0], 2 : [0, 0, 255]}
colored_image = np.array([colors[x] for x in np.nditer(class_index)], 
                         dtype=np.uint8)
output_image = np.reshape(colored_image, (img_height, img_width, 3))

首先,我们创建了colored_image,它现在包含每个点的颜色,但是它是一维数组,因此您必须通过np.reshape将其转换为3维数组。您现在可以绘制output_image

plt.imshow(output_image)
plt.show()

答案 1 :(得分:0)

如果我对您的问题理解正确,那么您想知道3类问题的标签图像应该如何。

让我们首先看看两类问题应该如何处理。标签图像将仅由零和一组成,并且您将对每个像素使用二进制交叉熵损失,然后(也许)对整个图像进行平均。

对于n类问题,您的标签图像的大小为H x W x n,如果您在整个深度上进行切片,则该图像将是单点编码的矢量。因此,向量将具有除零以外的所有零和一个零(与该类相对应)。

Segmentation map

One-hot encoded label-image

这两个图像均来自here。我鼓励您阅读该博客。

一旦您预测了标签图像,就可以通过为标签分配特定的颜色来轻松地对其进行转换。例如,在2类分割图像中,标签0 =>颜色0和标签1 =>颜色255-这是二进制图像。

对于n类分割图像,您可以获得[0,0,0]到[255,255,255]范围内的n个等距点,然后将每种颜色分配给标签。通常,您可以手动选择此类颜色(例如4种颜色的红色,绿色,蓝色,黄色),但是如果您真的想花哨的话,可以使用类似this的颜色。