我遵循了tensorflow图像分割教程,但是预测的蒙版为空白

时间:2020-03-15 02:59:40

标签: tensorflow machine-learning keras deep-learning image-segmentation

我想用灰度tif图像(原始图像的形状为(512,512),每个像素的值在0-2或NaN之间,为float32类型,蒙版图像为0)进行图像分割,1或NaN(也为float32类型)。我遵循https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#rolling-back-a-deploymentGoogle Colab创建以下代码:

from glob import glob
from PIL import Image
from tensorflow import keras
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf
from tensorflow.python.keras import layers
from tensorflow.python.keras import losses
from tensorflow.python.keras import models
from tensorflow.python.keras import backend as K

#get the path of my data
img = sorted(glob('train_sub_5/*.tif'))
mask = sorted(glob('train_mask_sub_5/*.tif'))

#split into train and test data
img, img_val, mask, mask_val = train_test_split(img, mask, test_size=0.2, random_state=42)

#load image as array and append to a list
train_image = []
for m in img:
    img= Image.open(m)
    img_arr = np.array(img)
    stacked_img = np.stack((img_arr,)*1, axis=-1)
    train_image.append(stacked_img)

train_mask = []
for n in mask:
    mask= Image.open(n)
    mask_arr= np.array(mask)
    stacked_mask = np.stack((mask_arr,)*1, axis=-1)
    train_mask.append(stacked_mask)

test_img = []
for o in img_val:
    img= Image.open(o)
    img_arr = np.array(img)
    stacked_img = np.stack((img_arr,)*1, axis=-1)
    test_img.append(stacked_img)

test_mask = []
for p in mask_val:
    mask= Image.open(p)
    mask_arr = np.array(mask)
    stacked_mask = np.stack((mask_arr,)*1, axis=-1)
    test_mask.append(stacked_mask)

#create TensorSliceDataset
for i, j in zip(train_image, train_mask):
    train= tf.data.Dataset.from_tensor_slices(([i], [j])) 

for k, l in zip(test_img, test_mask):
    test= tf.data.Dataset.from_tensor_slices(([k], [l]))

#for visualization
def display(display_list):
    plt.figure(figsize=(15, 15))
    title = ['Input Image', 'True Mask', 'Predicted Mask']
    for i in range(len(display_list)):
        plt.subplot(1, len(display_list), i+1)
        plt.title(title[i])
        plt.imshow(display_list[i])
        plt.axis('off')
    plt.show()

for img, mask in train.take(1):
    sample_image = img.numpy()[:,:,0]
    sample_mask = mask.numpy()[:,:,0]

display([sample_image, sample_mask])

可视化的输出看起来很正常,如下所示: tensorflow tutorial

#build the model
train_length = len(train_image)
img_shape = (512,512,1)
batch_size = 8
buffer_size = 5
epochs = 5

train_dataset = train.cache().shuffle(train_length).batch(batch_size).repeat()
train_dataset = train_dataset.prefetch(buffer_size)
test_dataset = test.batch(batch_size).repeat()

def conv_block(input_tensor, num_filters):
    encoder = layers.Conv2D(num_filters, (3, 3), padding='same')(input_tensor)
    encoder = layers.BatchNormalization()(encoder)
    encoder = layers.Activation('relu')(encoder)
    encoder = layers.Conv2D(num_filters, (3, 3), padding='same')(encoder)
    encoder = layers.BatchNormalization()(encoder)
    encoder = layers.Activation('relu')(encoder)
    return encoder

def encoder_block(input_tensor, num_filters):
    encoder = conv_block(input_tensor, num_filters)
    encoder_pool = layers.MaxPooling2D((2, 2), strides=(2, 2))(encoder)

    return encoder_pool, encoder

def decoder_block(input_tensor, concat_tensor, num_filters):
    decoder = layers.Conv2DTranspose(num_filters, (2, 2), strides=(2, 2), padding='same')(input_tensor)
    decoder = layers.concatenate([concat_tensor, decoder], axis=-1)
    decoder = layers.BatchNormalization()(decoder)
    decoder = layers.Activation('relu')(decoder)
    decoder = layers.Conv2D(num_filters, (3, 3), padding='same')(decoder)
    decoder = layers.BatchNormalization()(decoder)
    decoder = layers.Activation('relu')(decoder)
    decoder = layers.Conv2D(num_filters, (3, 3), padding='same')(decoder)
    decoder = layers.BatchNormalization()(decoder)
    decoder = layers.Activation('relu')(decoder)
    return decoder

inputs = layers.Input(shape=img_shape)
# 256

encoder0_pool, encoder0 = encoder_block(inputs, 32)
# 128

encoder1_pool, encoder1 = encoder_block(encoder0_pool, 64)
# 64

encoder2_pool, encoder2 = encoder_block(encoder1_pool, 128)
# 32

encoder3_pool, encoder3 = encoder_block(encoder2_pool, 256)
# 16

encoder4_pool, encoder4 = encoder_block(encoder3_pool, 512)
# 8

center = conv_block(encoder4_pool, 1024)
# center

decoder4 = decoder_block(center, encoder4, 512)
# 16

decoder3 = decoder_block(decoder4, encoder3, 256)
# 32

decoder2 = decoder_block(decoder3, encoder2, 128)
# 64

decoder1 = decoder_block(decoder2, encoder1, 64)
# 128

decoder0 = decoder_block(decoder1, encoder0, 32)
# 256

outputs = layers.Conv2D(1, (1, 1), activation='sigmoid')(decoder0)

model = models.Model(inputs=[inputs], outputs=[outputs])

def dice_coeff(y_true, y_pred):
    smooth = 1.
    # Flatten
    y_true_f = tf.reshape(y_true, [-1])
    y_pred_f = tf.reshape(y_pred, [-1])
    intersection = tf.reduce_sum(y_true_f * y_pred_f)
    score = (2. * intersection + smooth) / (tf.reduce_sum(y_true_f) + tf.reduce_sum(y_pred_f) + smooth)
    return score

def dice_loss(y_true, y_pred):
    loss = 1 - dice_coeff(y_true, y_pred)
    return loss

def bce_dice_loss(y_true, y_pred):
    loss = losses.binary_crossentropy(y_true, y_pred) + dice_loss(y_true, y_pred)
    return loss

model.compile(optimizer='adam', loss=bce_dice_loss, metrics=[dice_loss])

model.summary()

#save model
save_model_path = 'tmp/weights.hdf5'
cp = tf.keras.callbacks.ModelCheckpoint(filepath=save_model_path, monitor='val_dice_loss', mode='max', save_best_only=True)

#start training
history = model.fit(train_dataset, 
                   steps_per_epoch=int(np.ceil(train_length / float(batch_size))),
                   epochs=epochs,
                   validation_data=test_dataset,
                   validation_steps=int(np.ceil(len(test_img) / float(batch_size))),
                   callbacks=[cp])

#training process visualization
dice = history.history['dice_loss']
val_dice = history.history['val_dice_loss']

loss = history.history['loss']
val_loss = history.history['val_loss']

epochs_range = range(epochs)

plt.figure(figsize=(16, 8))
plt.subplot(1, 2, 1)
plt.plot(epochs_range, dice, label='Training Dice Loss')
plt.plot(epochs_range, val_dice, label='Validation Dice Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Dice Loss')

plt.subplot(1, 2, 2)
plt.plot(epochs_range, loss, label='Training Loss')
plt.plot(epochs_range, val_loss, label='Validation Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')

plt.show()

培训过程可视化的输出如下所示: out put of the visualization 该模型似乎正常运行。

#make prediction
def show_predictions(dataset=None, num=1):
    for image, mask in dataset.take(num):
        pred_mask = model.predict(image)
        display([image[0,:,:,0], mask[0,:,:,0], create_mask(pred_mask)])

def create_mask(pred_mask):
    pred_mask = tf.argmax(pred_mask, axis=-1)
    pred_mask = pred_mask[..., tf.newaxis]
    return pred_mask[0,:,:,0]

show_predictions(test_dataset, 3)

预测的输出如下: The output of the training process visualization

我尝试使用以下方法检查变量test和test_dataset:

for img, mask in test:
    print(img,mask)

但是我只有一个图像阵列和一个掩模阵列。这是否意味着数据集中只有一个图像阵列和一个遮罩阵列?我的代码创建训练和测试TensorSliceDataset有什么问题?

第二个问题是为什么我得到了预测的口罩空白?是因为我的某些补丁有难感吗?如您在输出中看到的,即输入图像的白色部分和真实蒙版,大海由NaN表示。如果这是问题所在,如果我希望模型可以忽略海,如何设置NaN的值?

谢谢您的帮助。

1 个答案:

答案 0 :(得分:0)

def display(display_list):
    fig = plt.figure(figsize=(15, 15))
    title = ['Input Image', 'True Mask', 'Predicted Mask']

    for i in range(len(display_list)):
        plt.subplot(1, len(display_list), i + 1)
        plt.title(title[i])
        plt.imshow(tf.keras.preprocessing.image.array_to_img
        (display_list[i]))
        plt.axis('off')
    plt.show()

def show_predictions(dataset=None, num=1):
    for image, mask in dataset.take(num):
        pred_mask = model.predict(image)
        pred_mask *= 255.0
        print(pred_mask.min())
        print(pred_mask.max())
        print(np.unique(pred_mask, return_counts=True))
        display([image[0], mask[0], pred_mask[0]])

show_predictions(test_dataset, 3)