title: Keras: Image segmentation using grayscale masks and ImageDataGenerator class
body: <p>I am currently trying to implement a convolutional network using Keras 2.1.6 (with TensorFlow as backend) and its <code>ImageDataGenerator</code> to segment an image using a grayscale mask. I try to use an image as input, and a mask as label. Due to a low amount of training images, and memory constraints I utilize the <code>ImageDataGenerator</code> class provided in Keras.</p>
  
  <p>However I get this error, after changing the values provided in the Keras example to the ones described later:</p>
  
  <pre><code>File "C:\Users\XXX\Anaconda3\lib\site-packages\keras\engine\training.py", line 2223, in fit_generator
  batch_size = x.shape[0]
  AttributeError: 'tuple' object has no attribute 'shape'
  </code></pre>
  
  <p>Which, as far as I know, happens because the generator does generate a tuple, and not an array. This first happened after I changed following parameters from the standard values provided in the Keras example to the following: <code>color_mode='grayscale'</code> for all mask generators, and <code>class_mode='input'</code> due to this being recommended for autoencoders.</p>
  
  <p>The Keras example can be found in <a href="https://keras.io/preprocessing/image/" rel="nofollow noreferrer">here</a>.</p>
  
  <p>The dataset I am using consists of 100 images (<code>jpg</code>) and 100 corresponding grayscale masks (<code>png</code>) and can be downloaded at <a href="http://www.ntu.edu.sg/home/asjfcai/Benchmark_Website/Semantic%20dataset100.zip" rel="nofollow noreferrer">this link</a></p>
  
  <p>The architecture I wanted to implement is an autoencoder/U-Net based network and it is shown in the provided code:</p>
  
  <pre><code>from keras.preprocessing import image
  from keras.models import Model
  from keras import optimizers 
  from keras.preprocessing.image import ImageDataGenerator
  from keras.layers import Input, Conv2D, MaxPooling2D, UpSampling2D
  from keras import initializers
  
  image_path = 
  mask_path = 
  valid_image_path = 
  valid_mask_path = 
  
  img_size=160
  batchsize=10
  samplesize = 60
  steps = samplesize / batchsize
  
  train_datagen = image.ImageDataGenerator(shear_range=0.2,
                                          zoom_range=0.2,
                                          horizontal_flip=True)
  
  data_gen_args = dict(rotation_range=90,
                       width_shift_range=0.1,
                       height_shift_range=0.1,
                       zoom_range=0.2)
  
  image_datagen = ImageDataGenerator(**data_gen_args)
  mask_datagen = ImageDataGenerator(**data_gen_args)
  
  seed = 1
  
  image_generator = image_datagen.flow_from_directory(
      image_path,
      target_size=(img_size, img_size),
      class_mode='input',
      batch_size = batchsize,
      seed=seed)
  
  mask_generator = mask_datagen.flow_from_directory(
      mask_path,
      target_size=(img_size, img_size),
      class_mode='input',
      color_mode = 'grayscale',
      batch_size = batchsize,
      seed=seed)
  
  vimage_generator = image_datagen.flow_from_directory(
      valid_image_path,
      target_size=(img_size, img_size),
      class_mode='input',
      batch_size = batchsize,
      seed=seed)
  
  vmask_generator = mask_datagen.flow_from_directory(
      valid_mask_path,
      target_size=(img_size, img_size),
      class_mode='input',
      color_mode = 'grayscale',
      batch_size = batchsize,
      seed=seed)
  
  #Model 
  input_img = Input(shape=(img_size,img_size,3))
  c11 = Conv2D(16, (3, 3), activation='relu', padding='same', kernel_initializer=initializers.random_normal(stddev=0.01))(input_img)
  mp1 = MaxPooling2D((2, 2), padding='same')(c11)
  c21 = Conv2D(16, (3, 3), activation='relu', padding='same', kernel_initializer=initializers.random_normal(stddev=0.01))(mp1)
  mp2 = MaxPooling2D((2, 2), padding='same')(c21)
  c31 = Conv2D(32, (3, 3), activation='relu', padding='same', kernel_initializer=initializers.random_normal(stddev=0.01))(mp2)
  encoded = MaxPooling2D((5, 5), padding='same')(c31)
  
  c12 = Conv2D(32, (3, 3), activation='relu', padding='same', kernel_initializer=initializers.random_normal(stddev=0.01))(encoded)
  us12 = UpSampling2D((5,5))(c12)
  c22 = Conv2D(16, (3, 3), activation='relu', padding='same', kernel_initializer=initializers.random_normal(stddev=0.01))(us12)
  us22 = UpSampling2D((2, 2))(c22)
  c32 = Conv2D(16, (3, 3), activation='relu', padding='same', kernel_initializer=initializers.random_normal(stddev=0.01))(us22)
  us32 = UpSampling2D((2, 2))(c32)
  decoded = Conv2D(1, (3, 3), activation='softmax', padding='same')(us32)
  
  model = Model(input_img, decoded)
  
  model.compile(loss="mean_squared_error", optimizer=optimizers.Adam(),metrics=["accuracy"])
  #model.summary()
  
  #Generators, tr: training, v: validation
  trgen = zip(image_generator,mask_generator)
  vgen = zip(vimage_generator,vmask_generator)
  
  model.fit_generator(
      trgen,
      steps_per_epoch= steps,
      epochs=5,
      validation_data = vgen,
      validation_steps=10)
  </code></pre>