pythontensorflowimage-segmentationimage-preprocessing

How to use from_tensor_slices properly on MRI images?


I'm working with MRI images and I'd like to use from_tensor_slices to preprocess the paths but I don't know how to use that properly. Below are my code, the problem message and link for the dataset.

First I rearrange my data. 484 images and 484 labels

image_data_path = './drive/MyDrive/Brain Tumour/Task01_BrainTumour/imagesTr/'
label_data_path = './drive/MyDrive/Brain Tumour/Task01_BrainTumour/labelsTr/'

image_paths = [image_data_path + name 
               for name in os.listdir(image_data_path) 
               if not name.startswith(".")]

label_paths = [label_data_path + name
               for name in os.listdir(label_data_path)
               if not name.startswith(".")]

image_paths = sorted(image_paths)
label_paths = sorted(label_paths)

Then, the function to load 1 example (I use nibabel to load nii files)

def load_one_sample(image_path, label_path):

  image = nib.load(image_path).get_fdata()
  image = tf.convert_to_tensor(image, dtype = 'float32')
  label = nib.load(label_path).get_fdata()
  label = tf.convert_to_tensor(label, dtype = 'uint8')

  return image, label

Next, I tried using from_tensor_slices

image_filenames = tf.constant(image_paths)
label_filenames = tf.constant(label_paths)

dataset = tf.data.Dataset.from_tensor_slices((image_filenames, label_filenames))

all_data = dataset.map(load_one_sample)

And the error comes: TypeError: stat: path should be string, bytes, os.PathLike or integer, not Tensor

What can be wrong and how can I fix it?

Datalink: https://drive.google.com/drive/folders/1HqEgzS8BV2c7xYNrZdEAnrHk7osJJ--2 (task 1 - Brain Tumour)

Please tell me if you need more information.


Solution

  • nib.load is not a TensorFlow function.
    If you want to use anything in tf.data pipeline that is not a TensorFlow function then you have to wrap it using a tf.py_function.
    Code:

    image_data_path = 'Task01_BrainTumour/imagesTr/'
    label_data_path = 'Task01_BrainTumour/labelsTr/'
    
    image_paths = [image_data_path + name 
                   for name in os.listdir(image_data_path) 
                   if not name.startswith(".")]
    label_paths = [label_data_path + name
                   for name in os.listdir(label_data_path)
                   if not name.startswith(".")]
    
    image_paths = sorted(image_paths)
    label_paths = sorted(label_paths)
    
    def load_one_sample(image_path, label_path):
      image = nib.load(image_path.numpy().decode()).get_fdata()
      image = tf.convert_to_tensor(image, dtype = 'float32')
      label = nib.load(label_path.numpy().decode()).get_fdata()
      label = tf.convert_to_tensor(label, dtype = 'uint8')
      return image, label
    
    def wrapper_load(img_path, label_path):
      img, label = tf.py_function(func = load_one_sample, inp = [img_path, label_path], Tout = [tf.float32, tf.uint8])
      return img, label
    
    dataset = tf.data.Dataset.from_tensor_slices((image_paths, label_paths)).map(wrapper_load)
    

    The error is not due to the from_tensor_slices function but arises as nibs.load is expecting a string but gets a tensor.

    However, a better way would be to create tfrecords and use them to train the model.