How to calculate mean and std for 1 channel using datalodaer

Hi,

I have a code that calculates mean and std of my image dataset through dataloader:

tfms = transforms.Compose([
    transforms.Resize((128, 128)),
                  transforms.ToTensor(),
                  transforms.Normalize(mean = (0, 0, 0), std  = (1, 1, 1))])

train_files = glob.glob(train_dir + '/*.jpg')
train_ds = MyDataset(train_files , transform = tfms)
train_dl = torch.utils.data.DataLoader(train_ds, 
                                       batch_size=16, 
                                       shuffle=True,)

####### COMPUTE MEAN / STD

# placeholders
psum    = torch.tensor([0.0, 0.0, 0.0]).to(device)
psum_sq = torch.tensor([0.0, 0.0, 0.0]).to(device)

# loop through images
for inputs, _ in tqdm(train_dl):
    inputs = inputs.to(device)
    psum    += inputs.sum(axis        = [0, 2, 3])
    psum_sq += (inputs ** 2).sum(axis = [0, 2, 3])


# ####### FINAL CALCULATIONS

# pixel count
print(len(train_ds))
count = len(train_ds) * resize * resize

# mean and std
total_mean = psum / count
total_var  = (psum_sq / count) - (total_mean ** 2)
total_std  = torch.sqrt(total_var)

# output
print('mean: '  + str(total_mean))
print('std:  '  + str(total_std))

I want to add transforms.Lambda(noise_extract) to transforms.Compose that extract noise residual and converts images from 3 channels to 1 channel:

tfms = transforms.Compose([
    transforms.Resize((128, 128)),
    transforms.Lambda(noise_extract),
                  transforms.ToTensor(),
                  transforms.Normalize(mean = (0, 0, 0), std  = (1, 1, 1))])

I want to know how I must change the above code for calculating mean & std for the new one channel output of the second tfms?

How do I change the above code to compute mean & std for one channel grayscale?

Since a grayscale image has only 1 channel, modify the normalize function like below

tfms = transforms.Compose([
    transforms.Resize((128, 128)),
    transforms.Lambda(noise_extract),
                  transforms.ToTensor(),
                  transforms.Normalize(mean = (0,), std  = (1,))])

And psum, psum_sq should be modified.

psum    = torch.tensor([0.0]).to(device)
psum_sq = torch.tensor([0.0]).to(device)
1 Like

Dear @thecho7, thanks for your reply.
How about [0, 2, 3]? I don’t know what it is, and should I change it?

psum    += inputs.sum(axis        = [0, 2, 3])
psum_sq += (inputs ** 2).sum(axis = [0, 2, 3])

axis or dim means to sum up along the given dimensions.

a = torch.rand(2, 3, 4, 4)
b = a.sum(dim=[0, 2, 3])

It means b is a 1-dimension with size 3 tensor.

b[0] = a[0, 0, 0, 0] + a[0, 0, 0, 1] + ... + a[0, 0, 3, 3]
     + a[1, 0, 0, 0] + a[1, 0, 0, 1] + ... + a[1, 0, 3, 3]

b[1] = a[0, 1, 0, 0] + a[0, 1, 0, 1] + ... + a[0, 1, 3, 3]
     + a[1, 1, 0, 0] + a[1, 1, 0, 1] + ... + a[1, 1, 3, 3]

b[2] = a[0, 2, 0, 0] + a[0, 2, 0, 1] + ... + a[0, 2, 3, 3]
     + a[1, 2, 0, 0] + a[1, 2, 0, 1] + ... + a[1, 2, 3, 3]
1 Like