Read Image and Mask (for segmentation problem) in Tensorflow-2.0 using tf.data

Viewed 1477

I am trying to read the image dataset for the segmentation problem (1-class) by following this link. My main folder contains two folders i.e. (a) img (b) mask. img contains image samples and mask contains corresponding masks. My approach was, generate the path for image and then change the string path (i.e. img->mask). I modified the code provided here which now looks as:

def process_path(file_path):
  file_path_str = str(file_path)
  file_path_mask = file_path_str.replace('img', 'mask') 
  # load the raw data from the file as a string
  img = tf.io.read_file(file_path)
  img = decode_img(img)

  mask = tf.io.read_file(str(file_path_mask))
  mask = decode_mask(mask)
  return img, mask

However, when I am trying to see the size of my samples using:

for image, mask in labeled_ds.take(1):
  print("Image shape: ", image.numpy().shape)
  print("Mask shape: ", mask.numpy().shape)

I am getting the following error:

InvalidArgumentError: NewRandomAccessFile failed to Create/Open: Tensor("arg0:0", shape=(), dtype=string) : The filename, directory name, or volume label syntax is incorrect. ; Unknown error [[{{node ReadFile_1}}]] [Op:IteratorGetNextSync]

Question: Any suggestion on how to read image and mask both from a given folder without above error?

2 Answers

We can use tf.regex.replace to rename string. So, in place of python string replacement, use:file_path_mask = tf.regex_replace(file_path, "img", "mask"). For TF 2.0, use tf.strings.regex_replace.

Alternative workaround for a similar problem. I have 200 (nb_of_images = 200) grayscale images of shape (512, 512) loaded as np.array and 200 binary masks also of shape (512, 512) and loaded as np.array. Within a for loop, I take all the images, convert them to EagerTensor (with tf.convert_to_tensor), cast them to tf.float32 through the dtype arg, add one dimension with:

img = img[:, :, tf.newaxis]

so that my images are now EagerTensors of shape (512, 512, 1), and finally I append them to an external list called images.

Within the same loop, I do the exact same operations for the masks and in the end I append them to an external list called masks.

Once the for loop is finished, I basically have two lists of EagerTensors, with

len(images) == len(masks) == nb_of_images

Lastly, I re-convert the two lists to tf.Tensor with:

images_tf = tf.convert_to_tensor(images)  # convert list back to tf.Tensor
masks_tf = tf.convert_to_tensor(masks)  # convert list back to tf.Tensor

and finally I create the tf.data.Dataset with:

dataset = tf.data.Dataset.from_tensor_slices((images_tf, masks_tf))  # create tf.data.Dataset
Related