繁体   English   中英

Tensorflow U-Net多类标签

[英]Tensorflow U-Net Multiclass Label

我是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)的图像形状。

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

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仅包含一张图片的输出, cnn_output包含整个批次的输出。

您需要找出哪个类别的分数最高。 在此, np.argmax可以帮助:

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

现在, class_index包含得分最高的班级编号。 (如果cnn_output只有2维,则将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()

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

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

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

分割图

一键编码标签图像

这两个图像都是从这里拍摄的。 我鼓励您阅读该博客。

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

对于n类分割图像,您可以获得[0,0,0]到[255,255,255]范围内的n个等距点,然后将每种颜色分配给标签。 通常情况下,你可以手动选择这样的颜色(如红色,绿色,蓝色,黄色的4类),但如果你想获得真正看中的,你可以使用类似这样

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM