title: Decoding RLE (run-length encoding) mask with Tensorflow Datasets
body: <p>I have been experimenting with <a href="/questions/tagged/tensorflow" class="post-tag" title="show questions tagged &#39;tensorflow&#39;" rel="tag">tensorflow</a> Datasets but I cannot figure out how to efficiently create <strong>RLE-masks</strong>.
  FYI, I am using data from the Airbus Ship Detection Challenge in Kaggle: <a href="https://www.kaggle.com/c/airbus-ship-detection/data" rel="nofollow noreferrer">https://www.kaggle.com/c/airbus-ship-detection/data</a></p>
  <p>I know my RLE-decoding function works (borrowed) from one of the kernels:</p>
  <pre><code>def rle_decode(mask_rle, shape=(768, 768)):
  '''
  mask_rle: run-length as string formated (start length)
  shape: (height,width) of array to return
  Returns numpy array, 1 - mask, 0 - background
  '''
  if not isinstance(mask_rle, str):
      img = np.zeros(shape[0]*shape[1], dtype=np.uint8)
      return img.reshape(shape).T
  
  s = mask_rle.split()
  starts, lengths = [np.asarray(x, dtype=int) for x in (s[0:][::2], s[1:][::2])]
  starts -= 1
  ends = starts + lengths
  img = np.zeros(shape[0]*shape[1], dtype=np.uint8)
  for lo, hi in zip(starts, ends):
      img[lo:hi] = 1
  return img.reshape(shape).T
  </code></pre>
  <p>.... BUT it does not seem to play nicely with the pipeline:</p>
  <pre><code>list_ds = tf.data.Dataset.list_files(train_paths_abs)
  ds = list_ds.map(parse_img)
  </code></pre>
  <p>With the following parse function, everything works fine:</p>
  <pre><code>def parse_img(file_path,new_size=[128,128]):    
      img_content = tf.io.read_file(file_path)
      img = tf.image.decode_jpeg(img_content)
      img = tf.image.convert_image_dtype(img, tf.float32)    
      img = tf.image.resize(img,new_size)
      return img
  </code></pre>
  <p>But things go rogue if I include the mask:</p>
  <pre class="lang-py prettyprint-override"><code>def parse_img(file_path,new_size=[128,128]):
      
      # Image
      img_content = tf.io.read_file(file_path)
      img = tf.image.decode_jpeg(img_content)
      img = tf.image.convert_image_dtype(img, tf.float32)    
      img = tf.image.resize(img,new_size)
      
      # Mask
      file_id = tf.strings.split(file_path,'/')[-1]
      objects = [rle_decode(m) for m in df2[df.ImageId==file_id]]
      mask = np.sum(objects,axis=0)
      mask = np.expand_dims(mask,3)   # Force mask to have 3 channels, necessary for resize step
      mask = tf.image.convert_image_dtype(mask, tf.int8)
      mask = tf.clip_by_value(mask,0,1)
      mask = tf.image.resize(mask,new_size)
      mask = tf.squeeze(mask)     # squeeze back
      mask = tf.image.convert_image_dtype(mask, tf.int8)
      
      return img, mask
  </code></pre>
  <p>Although my <code>parse_img</code> function works fine (I have checked it on a sample, it takes 271 µs ± 67.9 µs per run); the <code>list_ds.map</code> step takes forever (&gt;5 minutes) before hanging.
  I can't figure out what's wrong and it drives me crazy!
  <strong>Any idea?</strong></p>