I am trying to do a deep learning model using Keras and VGG16 algorithm on DICOM images. I used thhe following data generator to process my images:
``
# tested on tf 2.1
from keras_preprocessing.image.dataframe_iterator import DataFrameIterator
class DCMDataFrameIterator(DataFrameIterator):
def __init__(self, *arg, **kwargs):
self.white_list_formats = ('dcm')
super(DCMDataFrameIterator, self).__init__(*arg, **kwargs)
self.dataframe = kwargs['dataframe']
self.x = self.dataframe[kwargs['x_col']]
self.y = self.dataframe[kwargs['y_col']]
self.color_mode = kwargs['color_mode']
self.target_size = kwargs['target_size']
def _get_batches_of_transformed_samples(self, indices_array):
# get batch of images
batch_x = np.array([self.read_dcm_as_array(dcm_path, self.target_size, color_mode=self.color_mode)
for dcm_path in self.x.iloc[indices_array]])
batch_y = np.array(self.y.iloc[indices_array].astype(np.uint8)) # astype because y was passed as str
# transform images
if self.image_data_generator is not None:
for i, (x, y) in enumerate(zip(batch_x, batch_y)):
transform_params = self.image_data_generator.get_random_transform(x.shape)
batch_x[i] = self.image_data_generator.apply_transform(x, transform_params)
# you can change y here as well, eg: in semantic segmentation you want to transform masks as well
# using the same image_data_generator transformations.
return batch_x, batch_y
@staticmethod
def read_dcm_as_array(dcm_path, target_size=(256, 256), color_mode='rgb'):
img = tf.io.read_file(dcm_path)
img = tfio.image.decode_dicom_image(img, dtype=tf.uint16)
img = tf.image.resize(img, target_size)
img = tf.image.grayscale_to_rgb(img, name=None) # convert image grayscale to rgb for model VG16
#img = np.expand_dims(img, -1)
return img
``
and: `` # you can use preprocessing_function instead of rescale in all generators # if you are using a pretrained network train_augmentation_parameters = dict( rescale=1.0/255.0, rotation_range=10, zoom_range=0.2, horizontal_flip=True, fill_mode='nearest', brightness_range = [0.8, 1.2], validation_split = 0.2 )
valid_augmentation_parameters = dict(
rescale=1.0/255.0,
validation_split = 0.2
)
test_augmentation_parameters = dict(
rescale=1.0/255.0
)
# training parameters
BATCH_SIZE = 32
CLASS_MODE = 'sparse'
COLOR_MODE = 'grayscale'
TARGET_SIZE = (300, 300)
EPOCHS = 10
SEED = 1337
train_consts = {
'seed': SEED,
'batch_size': BATCH_SIZE,
'class_mode': CLASS_MODE,
'color_mode': COLOR_MODE,
'target_size': TARGET_SIZE,
'subset': 'training'
}
valid_consts = {
'seed': SEED,
'batch_size': BATCH_SIZE,
'class_mode': CLASS_MODE,
'color_mode': COLOR_MODE,
'target_size': TARGET_SIZE,
'subset': 'validation'
}
test_consts = {
'batch_size': 1, # should be 1 in testing
'class_mode': CLASS_MODE,
'color_mode': COLOR_MODE,
'target_size': TARGET_SIZE, # resize input images
'shuffle': False
} ``
and:
``
# Using the training phase generators
train_augmenter = ImageDataGenerator(**train_augmentation_parameters)
valid_augmenter = ImageDataGenerator(**valid_augmentation_parameters)
train_generator = DCMDataFrameIterator(dataframe=df_merged,
x_col='files',
y_col='class',
image_data_generator=train_augmenter,
**train_consts)
valid_generator = DCMDataFrameIterator(dataframe=df_merged,
x_col='files',
y_col='class',
image_data_generator=valid_augmenter,
**valid_consts)
``
Result of last command:
``
Found 7828 validated image filenames belonging to 4 classes.
Found 1956 validated image filenames belonging to 4 classes.
``
After:
``
base_model = VGG16(weights='imagenet', include_top=False)
n_class = 4 #
# Freezer les couches du VGG16
for layer in base_model.layers:
layer.trainable = False
model = Sequential()
model.add(base_model) # Ajout du modèle VGG16
model.add(GlobalAveragePooling2D())
model.add(Dense(1024,activation='relu'))
model.add(Dropout(rate=0.2))
model.add(Dense(512, activation='relu'))
model.add(Dropout(rate=0.2))
model.add(Dense(n_class, activation='softmax'))
``
I compile but but when I do .fit I have the following message:
ValueError: Input arrays must be multi-channel 2D images.
Could you help me ? Thank you in advance, Thibaut
I had a look on stackoverflow to try to find a solution !