nikhilroxtomar / Unet-with-Pretrained-Encoder

The repository contains the Jupyter Notebook that perform semantic segmentation using the famous U-Net. The encoder of the U-Net is replaced with the pretrained encoder.
https://idiotdeveloper.com
42 stars 10 forks source link

How to add data augmentation? #1

Open mona-commits opened 3 years ago

mona-commits commented 3 years ago

Hi, I came here from your youtube channel. Good work btw. Helped me a lot, but how I do go about if I want to add online data augmentation to this code? Am new to machine learning, so your help would be highly appreciated!

nikhilroxtomar commented 3 years ago

For online data augmentation: https://albumentations.ai/docs/examples/example/ I have dedicated video for offline data augmentation. https://youtu.be/bSxz_EWwZtA

mona-commits commented 3 years ago

Yes, I did try to use something similar, I tried to use 'augmentor' library and it kind of works but I am not sure how I could process the images to make them suitable for training

mona-commits commented 3 years ago

Also how can I integrate keras generator into the model? That looks easier

nikhilroxtomar commented 3 years ago

I haven't tried Keras generator for online augmentation. So, can't help you with it.

mona-commits commented 3 years ago

I tried to integrate data augmentations using albumentations library but I get an error saying my predicted values are negative.....I checked online but couldn't find a solution `class DataGeneratorFolder(Sequence): def init(self, root = "", image_folder= 'img/', mask_folder='masks/', batch_size=7, image_size=256, nb_y_features=1, augmentation=None, suffle=True):

os.path()

    self.image_filenames = listdir_fullpath(os.path.join(root, image_folder))
    self.mask_names = listdir_fullpath(os.path.join(root, mask_folder))
    self.batch_size = batch_size
    self.currentIndex = 0
    self.augmentation = augmentation
    self.image_size = image_size
    self.nb_y_features = nb_y_features
    self.indexes = None
    self.suffle = suffle

def __len__(self):
    """
    Calculates size of batch
    """
    return int(np.ceil(len(self.image_filenames) / (self.batch_size)))

def on_epoch_end(self):
    """Updates indexes after each epoch"""
    if self.suffle==True:
        self.image_filenames, self.mask_names = shuffle(self.image_filenames, self.mask_names)

def read_image_mask(self, image_name, mask_name):
    return imread(image_name, plugin = 'matplotlib'), (imread(mask_name, plugin = 'matplotlib', as_gray=True) > 0).astype(np.int8)

def __getitem__(self, index):
    """
    Generate one batch of data

    """
    # Generate indexes of the batch
    data_index_min = int(index*self.batch_size)
    data_index_max = int(min((index+1)*self.batch_size, len(self.image_filenames)))

    indexes = self.image_filenames[data_index_min:data_index_max]

    this_batch_size = len(indexes) # The last batch can be smaller than the others

    # Defining dataset
    X = np.empty((this_batch_size, self.image_size, self.image_size, 3), dtype=np.float32)
    y = np.empty((this_batch_size, self.image_size, self.image_size, self.nb_y_features), dtype=np.float32)

    for i, sample_index in enumerate(indexes):

        X_sample, y_sample = self.read_image_mask(self.image_filenames[index * self.batch_size + i], 
                                                self.mask_names[index * self.batch_size + i])

        # if augmentation is defined, we assume its a train set
        if self.augmentation is not None:

            # Augmentation code
            augmented = self.augmentation(self.image_size)(image=X_sample, mask=y_sample)
            image_augm = augmented['image']
            mask_augm = augmented['mask'].reshape(self.image_size, self.image_size, self.nb_y_features)
            X[i, ...] = np.clip(image_augm, a_min = 0, a_max=1)
            y[i, ...] = mask_augm
            return X,y

            # if augmentation isnt defined, we assume its a test set. 
        # Because test images can have different sizes we resize it to be divisable by 32
        elif self.augmentation is None and self.batch_size ==1:
            X_sample, y_sample = self.read_image_mask(self.image_filenames[index * 1 + i], 
                                                  self.mask_names[index * 1 + i])
            augmented = Resize(height=((X_sample.shape[0])//32)*32, width=((X_sample.shape[1])//32)*32)(image = X_sample, mask = y_sample)
            X_sample, y_sample = augmented['image'], augmented['mask']
            # image_augm = X_sample
            # mask_augm = y_sample.reshape(self.image_size, self.image_size, self.nb_y_features)
            # X[i, ...] = np.clip(image_augm, a_min = 0, a_max=1)
            # y[i, ...] = mask_augm

            return X_sample.reshape(1, X_sample.shape[0], X_sample.shape[1], 3).astype(np.float32),\
                    y_sample.reshape(1, X_sample.shape[0], X_sample.shape[1], self.nb_y_features).astype(np.uint8)

    #return X, y

I used this code for data generation for both training and validation set after performing augmentation and the results looked fine when viewed individually but when I tried to run the model it says

InvalidArgumentError: labels contains negative values Condition x >= 0 did not hold element-wise: x (shape=(196608,) dtype=int64) = ['1', '1', '1', '...']

mona-commits commented 3 years ago

I also tried changing np.float32 to np.float64 and then I got this error InvalidArgumentError: labels out of bound Condition x < y did not hold. First 3 elements of x: [0 0 0] First 1 elements of y: [2]