首页 > 解决方案 > 使用 Unet 和 Keras 进行图像分割的错误

问题描述

我正在使用 Unet 模型进行卫星图像分割,输入为 512x512x3。但是在执行模型时,我收到以下错误:ValueError:无法为具有形状“(?,?,?,?)”的张量“conv2d_19_target:0”提供形状(3、512、512)的值。Unet 模型的代码是:

from __future__ import print_function
import os
from skimage.transform import resize
from skimage.io import imsave
import numpy as np
from keras.models import Model
from keras.layers import Input, concatenate, Conv2D, MaxPooling2D,     Conv2DTranspose
from keras.optimizers import Adam

from keras.callbacks import ModelCheckpoint
from keras import backend as K
from data import load_train_data, load_test_data

K.set_image_data_format('channels_last')  # TF dimension ordering in this code

img_rows = 512
img_cols = 512
image_channels=3
smooth = 1.
OUTPUT_MASK_CHANNELS = 1


def dice_coef(y_true, y_pred):
    y_true_f = K.flatten(y_true)
    y_pred_f = K.flatten(y_pred)
    intersection = K.sum(y_true_f * y_pred_f)
    return (2. * intersection + smooth) / (K.sum(y_true_f) +    K.sum(y_pred_f) + smooth)

def dice_coef_loss(y_true, y_pred):
   return -dice_coef(y_true, y_pred)


def get_unet():
   inputs = Input((img_rows, img_cols, 3))
   conv1 = Conv2D(32, (3, 3), activation='relu', padding='same')(inputs)
   conv1 = Conv2D(32, (3, 3), activation='relu', padding='same')(conv1)
   pool1 = MaxPooling2D(pool_size=(2, 2))(conv1)

   conv2 = Conv2D(64, (3, 3), activation='relu', padding='same')(pool1)
   conv2 = Conv2D(64, (3, 3), activation='relu', padding='same')(conv2)
   pool2 = MaxPooling2D(pool_size=(2, 2))(conv2)

   conv3 = Conv2D(128, (3, 3), activation='relu', padding='same')(pool2)
   conv3 = Conv2D(128, (3, 3), activation='relu', padding='same')(conv3)
   pool3 = MaxPooling2D(pool_size=(2, 2))(conv3)

   conv4 = Conv2D(256, (3, 3), activation='relu', padding='same')(pool3)
   conv4 = Conv2D(256, (3, 3), activation='relu', padding='same')(conv4)
   pool4 = MaxPooling2D(pool_size=(2, 2))(conv4)

   conv5 = Conv2D(512, (3, 3), activation='relu', padding='same')(pool4)
   conv5 = Conv2D(512, (3, 3), activation='relu', padding='same')(conv5)

   up6 = concatenate([Conv2DTranspose(256, (2, 2), strides=(2, 2), padding='same')(conv5), conv4], axis=3)
   conv6 = Conv2D(256, (3, 3), activation='relu', padding='same')(up6)
   conv6 = Conv2D(256, (3, 3), activation='relu', padding='same')(conv6)

   up7 = concatenate([Conv2DTranspose(128, (2, 2), strides=(2, 2), padding='same')(conv6), conv3], axis=3)
   conv7 = Conv2D(128, (3, 3), activation='relu', padding='same')(up7)
   conv7 = Conv2D(128, (3, 3), activation='relu', padding='same')(conv7)

   up8 = concatenate([Conv2DTranspose(64, (2, 2), strides=(2, 2), padding='same')(conv7), conv2], axis=3)
   conv8 = Conv2D(64, (3, 3), activation='relu', padding='same')(up8)
   conv8 = Conv2D(64, (3, 3), activation='relu', padding='same')(conv8)

   up9 = concatenate([Conv2DTranspose(32, (2, 2), strides=(2, 2), padding='same')(conv8), conv1], axis=3)
   conv9 = Conv2D(32, (3, 3), activation='relu', padding='same')(up9)
   conv9 = Conv2D(32, (3, 3), activation='relu', padding='same')(conv9)

   conv_final = Conv2D(OUTPUT_MASK_CHANNELS, (1, 1),activation='sigmoid')(conv9)
   #conv_final = Activation('sigmoid')(conv_final)

   model = Model(inputs, conv_final, name="ZF_UNET_224")

   #conv10 = Conv2D(1, (1, 1), activation='sigmoid')(conv9)
   #model = Model(inputs=[inputs], outputs=[conv10])

   model.compile(optimizer=Adam(lr=1e-5), loss=dice_coef_loss, metrics=[dice_coef])

   return model


def preprocess(imgs):
   imgs_p = np.ndarray((imgs.shape[0], img_rows, img_cols),       dtype=np.uint8)
for i in range(imgs.shape[0]):
    imgs_p[i] = resize(imgs[i], (img_cols, img_rows), preserve_range=True)

imgs_p = imgs_p[..., np.newaxis]
return imgs_p


def train_and_predict():
   print('-'*30)
   print('Loading and preprocessing train data...')
   print('-'*30)
   imgs_train, imgs_mask_train = load_train_data()

   #imgs_train = preprocess(imgs_train)
   #imgs_mask_train = preprocess(imgs_mask_train)

   imgs_train = imgs_train.astype('float32')
   mean = np.mean(imgs_train)  # mean for data centering
   std = np.std(imgs_train)  # std for data normalization

   imgs_train -= mean
   imgs_train /= std

   imgs_mask_train = imgs_mask_train.astype('float32')
   imgs_mask_train /= 255.  # scale masks to [0, 1]

   print('-'*30)
   print('Creating and compiling model...')
   print('-'*30)
   model = get_unet()
   model_checkpoint = ModelCheckpoint('weights.h5', monitor='val_loss',    save_best_only=True)

   print('-'*30)
   print('Fitting model...')
   print('-'*30)
   model.fit(imgs_train, imgs_mask_train, batch_size=3, epochs=20,   verbose=2, shuffle=True,
          validation_split=0.2,
          callbacks=[model_checkpoint])

   print('-'*30)
   print('Loading and preprocessing test data...')
   print('-'*30)
   imgs_test, imgs_id_test = load_test_data()
   imgs_test = preprocess(imgs_test)

   imgs_test = imgs_test.astype('float32')
   imgs_test -= mean
   imgs_test /= std

   print('-'*30)
   print('Loading saved weights...')
   print('-'*30)
   model.load_weights('weights.h5')

   print('-'*30)
   print('Predicting masks on test data...')
   print('-'*30)
   imgs_mask_test = model.predict(imgs_test, verbose=1)
   np.save('imgs_mask_test.npy', imgs_mask_test)

   print('-' * 30)
   print('Saving predicted masks to files...')
   print('-' * 30)
   pred_dir = 'preds'
   if not os.path.exists(pred_dir):
       os.mkdir(pred_dir)
for image, image_id in zip(imgs_mask_test, imgs_id_test):
    image = (image[:, :, 0] * 255.).astype(np.uint8)
    imsave(os.path.join(pred_dir, str(image_id) + '_pred.png'), image)

if __name__ == '__main__':
train_and_predict()

错误回溯如下:

File "/home/deeplearning/Downloads/Models/ultrasound-nerve-segmentation-master/train.py", line 158, in <module> train_and_predict()

  File "/home/deeplearning/Downloads/Models/ultrasound-nerve-segmentation-master/train.py", line 124, in train_and_predict callbacks=[model_checkpoint])

  File "/home/deeplearning/anaconda3/envs/myenv/lib/python3.6/site-packages/keras/engine/training.py", line 1037, in fit
    validation_steps=validation_steps)

  File "/home/deeplearning/anaconda3/envs/myenv/lib/python3.6/site-packages/keras/engine/training_arrays.py", line 199, in fit_loop
    outs = f(ins_batch)

  File "/home/deeplearning/anaconda3/envs/myenv/lib/python3.6/site-packages/keras/backend/tensorflow_backend.py", line 2672, in __call__
    return self._legacy_call(inputs)

  File "/home/deeplearning/anaconda3/envs/myenv/lib/python3.6/site-packages/keras/backend/tensorflow_backend.py", line 2654, in _legacy_call
    **self.session_kwargs)

  File "/home/deeplearning/anaconda3/envs/myenv/lib/python3.6/site-packages/tensorflow/python/client/session.py", line 767, in run
    run_metadata_ptr)

  File "/home/deeplearning/anaconda3/envs/myenv/lib/python3.6/site-packages/tensorflow/python/client/session.py", line 944, in _run
    % (np_val.shape, subfeed_t.name, str(subfeed_t.get_shape())))

ValueError: Cannot feed value of shape (3, 512, 512) for Tensor 'conv2d_19_target:0', which has shape '(?, ?, ?, ?)'

请帮我找出问题所在

标签: pythonkerasdeep-learningconv-neural-networkimage-segmentation

解决方案


您设置K.set_image_data_format('channels_last')了 ,但您的输入图像(3 X 512 X 512)首先具有通道。要么更改为K.set_image_data_format('channels_first')(可能不适用于 UNET),要么将输入图像的尺寸置换np.tranpose为具有输入形状(512,512,3)


推荐阅读