Thanks for the information!
In that case, could you remove the lambdas and call the tranformations directly in your forward:
if any([img in self.image_paths[index] for img in self.transform_images]):
print('applying special transformation on images')
image = tf.rotate(image, 10)
image = tf.affine(image, angle=0, translate=(0, 0), scale=0.2, shear=0.2)
@ptrblck thank you. I did remove it, and it works fine now. One more question, as I mentioned before, I did specify to apply augmentation on only few images (12 images). So, these augmented image will produce and will add to the training data for each epoch ?
If it’s like that, I think I am increasing the size of training dataset. Do I need to decrease the percentage of training dataset when I am splitting the dataset to the train/valid/test? (now is 60% training, 20%valid, 20% test)
The specified images will be transformed on the fly, so that the length of your dataset stays the same.
Instead of the original images, you will now get the transformed ones. Note that the transformations you are currently applying (rotate, affine) are not applied randomly so that the result will always be the same.
@ptrblck then, it means I am not doing any augmentation?! I am confused now. Do you mean those original images and also transformed version of them which will produce on the fly will go through the training process?
Yes, you are currently not performing any augmentation, but just a static transformation.
If you would like to perform these transformations randomly, you could sample random numbers for the parameters of rotate and affine before applying them.
Make sure to use the same parameters for the transformation of your image and mask. Otherwise you will destroy the correspondence of the data-target mapping.
The original images won’t be used, since the images are now transformed (randomly if you change the code).
@ptrblck thank you for the information. Then, as I understood if I perform these transformation randomly and not static, augmentation will happen. if not, how can I do augmentation?
My aim was produce transformed version of those images (with lower quality) which is not much in my dataset, and it was unbalance between good quality and low quality images.
If you want to increase the number of the specified images, you could save them after applying the transformation. This would increase your dataset and could create a class imbalance.
I’m not sure to understand your last point about the data quality.
Hi, everyone. I just face some problems with the following code. Is there anyone to help me?
I just use the below code to load all the images and labels from a folder in my laptop as an input and target maps. But I don’t know why when I run the code I’m facing by this error:
count of dataset: 0
class CustomDataset(Dataset):
def init(self, image_paths, target_paths, transform_images, transform_masks):
self.image_paths = image_paths
self.target_paths = target_paths
self.transform_images = transform_images
self.transform_masks = transform_masks
self.transformm = transforms.Compose([transforms.Lambda(lambda x: tf.rotate(x, 10)),
transforms.Lambda(lambda x: tf.affine(x, angle=0,
translate=(0, 0),
scale=0.2,
shear=0.2))
])
self.transform = transforms.ToTensor()
self.mapping = {
0: 0,
255: 1
}
def mask_to_class(self, mask):
for k in self.mapping:
mask[mask==k] = self.mapping[k]
return mask
def __getitem__(self, index):
image = Image.open(self.image_paths[index])
mask = Image.open(self.target_paths[index])
if any([img in self.image_paths[index] for img in self.transform_images]):
print('applying special transformation')
image = self.transformm(image) #augmentation
if any([msk in self.target_paths[index] for msk in self.transform_masks]):
print('applying special transformation')
image = self.transformm(mask) #augmentation
t_image = image.convert('L')
t_image = self.transform(t_image) # transform to tensor for image
mask = self.transform(mask) # transform to tensor for mask
mask = torch.from_numpy(numpy.array(mask, dtype=numpy.uint8))
mask = self.mask_to_class(mask)
mask = mask.long()
return t_image, mask, self.image_paths[index], self.target_paths[index]
def __len__(self): # return count of sample we have
return len(self.image_paths)
get all the image and mask path and number of images
Hi Neda
Can you please share the final working code
I am trying to apply the above steps to a custom dataset
so that i can apply deep learning image segmentation models over it
TypeError: default_collate: batch must contain tensors, numpy arrays, numbers, dicts or lists; found <class ‘PIL.PngImagePlugin.PngImageFile’>
for epoch in range(1, n_epochs+1):
# monitor training loss
train_loss = 0.0
###################
# train the model #
###################
for image,mask in train_loader:
# _ stands in for labels, here
images,_ = data
# flatten images
images = images.view(images.size(0), -1).to(device)
# clear the gradients of all optimized variables
optimizer.zero_grad()
# forward pass: compute predicted outputs by passing inputs to the model
outputs = model(images)
# calculate the loss
loss = criterion(outputs, images)
# backward pass: compute gradient of the loss with respect to model parameters
loss.backward()
# perform a single optimization step (parameter update)
optimizer.step()
# update running training loss
train_loss += loss.item()*images.size(0)