1

The following method does exactly that, taking multiple horizontal slices and putting them in a 2D matrix

def slices_matrix_2D(img):
  ''' Transform a 3D MRI image into a 2D image, by obtaining 9 slices 
      and placing them in a 4x4 two-dimensional grid.
      
      All 16 cuts are from a horizontal/axial view. They are selected
      from the 30th to the 60th level of the original 3D image.
      
      Parameters:
        img -- np.ndarray with the 3D image
        
      Returns:
        np.ndarray -- The resulting 2D image
  '''
  
  # create the final 2D image 
  image_2D = np.empty(IMG_2D_SHAPE)
  
  # set the limits and the step
  TOP = 60
  BOTTOM = 30
  STEP = 2
  N_CUTS = 16
  
  # iterator for the cuts
  cut_it = TOP
  # iterator for the rows of the 2D final image
  row_it = 0
  # iterator for the columns of the 2D final image
  col_it = 0
  
  for cutting_time in range(N_CUTS):
    
    # cut
    cut = img[cut_it, :, :]
    cut_it -= STEP
    
    # reset the row iterator and move the
    # col iterator when needed
    if cutting_time in [4, 8, 12]:
      row_it = 0
      col_it += cut.shape[1]
    
    # copy the cut to the 2D image
    for i in range(cut.shape[0]):
      for j in range(cut.shape[1]):
        image_2D[i + row_it, j + col_it] = cut[i, j]
    row_it += cut.shape[0]
  
  # return the final 2D image, with 3 channels
  # this is necessary for working with most pre-trained nets
  return np.repeat(image_2D[None, ...], 3, axis=0).T
  #return image_2D

**The following method uses the previous 2D transformation to load the 3D images from disk and transforms them. Also returns the image label. **

def load_image_2D(abs_path, labels):
  ''' Load an image (.nii) and its label, from its absolute path.
      Transform it into a 2D image, by obtaining 16 slices and placing them
      in a 4x4 two-dimensional grid.
      
      Parameters:
        abs_path -- Absolute path, filename included
        labels -- Label mapper
        
      Returns:
        img -- The .nii image, converted into a numpy array
        label -- The label of the image (from argument 'labels')
        
  '''
  
  # obtain the label from the path (it is the last directory name)
  label = labels[abs_path.split('/')[-2]]
  
  # load the image with SimpleITK
  sitk_image = sitk.ReadImage(abs_path)
  
  # transform into a numpy array
  img = sitk.GetArrayFromImage(sitk_image)
  
  # apply whitening
  img = preprocessing.whitening(img)
  
  # make the 2D image
  img = slices_matrix_2D(img)
  
  return img, label

Define the complete filename for each one of the .tfrecords.

train_tfrec2D = os.path.join(DB_TF_2D_PATH, TFREC_2D_SS_TRAIN)
test_tfrec2D = os.path.join(DB_TF_2D_PATH, TFREC_2D_SS_TEST)
val_tfrec2D = os.path.join(DB_TF_2D_PATH, TFREC_2D_SS_VAL)

Design the method for creating a .tfrecords, given the all the images filenames, the name of the file and the label mapper (always the LABELS constant). It uses the previous two methods for loading the images

def create_tf_record_2D(img_filenames, tf_rec_filename, labels):
  ''' Create a TFRecord file, including the information
      of the specified images, after converting them into 
      a 2D grid.
      
      Parameters:
        img_filenames -- Array with the path to every
                         image that is going to be included
                         in the TFRecords file.
        tf_rec_filename -- Name of the TFRecords file.
        labels -- Label mapper
  '''
  
  # open the file
  writer = tf.python_io.TFRecordWriter(tf_rec_filename)
  
  # iterate through all .nii files
  for meta_data in img_filenames:

    # load the image and label
    img, label = load_image_2D(meta_data, labels)

    # create a feature
    feature = {'label': _int64_feature(label),
               'image': _float_feature(img.ravel())}

    # create an example protocol buffer
    example = tf.train.Example(features=tf.train.Features(feature=feature))

    # serialize to string and write on the file
    writer.write(example.SerializeToString())
    
  writer.close()

Finally, create the .tfrecords.

create_tf_record_2D(training_set, train_tfrec2D, LABELS)
create_tf_record_2D(test_set, test_tfrec2D, LABELS)
create_tf_record_2D(validation_set, val_tfrec2D, LABELS)
  • Did you investigate which statement or line triggers the error? When does it occur exactly? – Palo Aug 12 '21 at 17:14
  • It is worth keeping in mind that an array of size 440 has indices 0, 1, ... 439. – alle_meije Aug 16 '21 at 22:21
  • for cutting_time in range(N_CUTS): # cut cut = img[cut_it, :, :] cut_it -= STEP # reset the row iterator and move the # col iterator when needed if cutting_time in [4, 8, 12]: row_it = 0 col_it += cut.shape[1] # copy the cut to the 2D image for i in range(cut.shape[0]): for j in range(cut.shape[1]): image_2D[i + row_it, j + col_it] = cut[i, j] (it gives the error here) row_it += cut.shape[0] – ebubekir ırak Aug 25 '21 at 06:23

1 Answers1

0
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-119-7ac7d2b5c98e> in <module>
----> 1 create_tf_record_2D(training_set, train_tfrec2D, LABELS)
      2 create_tf_record_2D(test_set, test_tfrec2D, LABELS)
      3 create_tf_record_2D(validation_set, val_tfrec2D, LABELS)

<ipython-input-118-a58a668df074> in create_tf_record_2D(img_filenames, tf_rec_filename, labels)
     19 
     20     # load the image and label
---> 21     img, label = load_image_2D(meta_data, labels)
     22 
     23     # create a feature

<ipython-input-114-8a6e1c4008a3> in load_image_2D(abs_path, labels)
     27 
     28   # make the 2D image
---> 29   img = slices_matrix_2D(img)
     30 
     31   return img, label

<ipython-input-113-9f2419afd597> in slices_matrix_2D(img)
     44     for i in range(cut.shape[0]):
     45       for j in range(cut.shape[1]):
---> 46         image_2D[i + row_it, j + col_it] = cut[i, j]
     47     row_it += cut.shape[0]
     48 
    

IndexError: index 440 is out of bounds for axis 0 with size 440