How make customised dataset for semantic segmentation?

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)
1 Like

@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.

1 Like

@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).

1 Like

@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.

1 Like

@ptrblck
My code for segmentation is

train_dir = os.path.expanduser("~/TRAINTTF")
train_dir1 = os.path.join(train_dir, “IMAGEE/”)
train_dir2 = os.path.join(train_dir, “LABELL/”)
train_input_glob = sorted(glob.glob(train_dir1 + “IMAG1/image*.tif”))
train_target_glob = sorted(glob.glob(train_dir2 + “LABE1/label*.tif”))

It is for one folder of images and labels
TRAINTTF
IMAGEE
IMAG1
1.tif,2.tif, … 275.tif
TRAINTTF
LABELL
LABE1
1.tif,2.tif, … 275.tif

This code is working without any error
/
/
/
/
/
/
But,
if I use many subsubfolders as below
TRAINTTF
IMAGEE
IMAG1
1.tif,2.tif, … 275.tif
IMAG2
1.tif,2.tif, … 275.tif
.
.
IMAG20
1.tif,2.tif, … 275.tif
TRAINTTF
LABELL
LABE1
1.tif,2.tif, … 275.tif
LABE2
1.tif,2.tif, … 275.tif
.
.
LABE20
1.tif,2.tif, … 275.tif

train_dir = os.path.expanduser("~/TRAINTTF")
train_dir1 = os.path.join(train_dir, “IMAGEE/”)
train_dir2 = os.path.join(train_dir, “LABELL/”)
train_input_glob = sorted(glob.glob(train_dir1 + “IMAG*/image*.tif”))
train_target_glob = sorted(glob.glob(train_dir2 + “LABE*/label*.tif”))

I am getting the following error


a = os.fspath(a)
TypeError: expected str, bytes or os.PathLike object, not list

Thanks.
Rajan

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

image_paths = glob.glob(“C:\Users\Abolfazl\Desktop\data1\image\.tif")
target_paths = glob.glob("C:\Users\Abolfazl\Desktop\data1\labels\
.tif”)

split these path using a certain percentage

len_data = len(folder_data)
print("count of dataset: ", len_data)

I guess image_paths might be empty.
Could you print it before passing it to the Dataset?

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

3 Likes

I got this error using custom data

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)

Hi @Neda

can you please share your final working model for custom dataset ?
It would be really helpful.
thanks.

1 Like

@panks , as far as I remember it was for binary segmentation task using UNet model.

1 Like

hhh 4 years has passed, When i search custom dataset i found this issue

1 Like