How to normalize images not between 0 and 1

Hi, in the below code, I normalized the images with a formula. And, I saved images in this format. However, I want to know can I do it with torch.nn.functional. normalize … I don’t want to change images that are in the folder, because I want to visualize predicted images and I can’t see the original images with this way.

import numpy as np
from PIL import Image

files = src

def normalize(files):
    k= 0 

    for i in files:
        image = Image.open(i)
        new_image = image.resize((600, 600))
        pixels = np.asarray(image)

        pixels = pixels.astype('float32')
        mean, std = pixels.mean(), pixels.std()
        # global standardization of pixels
        pixels = (pixels - mean) / std  
        print(pixels)


        outfile_name = i.replace(".png", ".npy")  

        with open(outfile_name, 'wb') as f:
            np.save(f, pixels)
            np.save(f, np.array([mean, std]))  
        print(k)

        with open(outfile_name, 'rb') as f:
            norm_t = np.load(f)  # Load normalized array
            mean_std = np.load(f)  # Load mean and std 
            mean, std = tuple(mean_std) 
            k =k+1

            t = norm_t*std + mean  # Unnormalized (get the original pixels before normalizing)
            t = np.round(t.clip(0, 255)).astype(np.uint8)  # Convert from float to uint8
            img = Image.fromarray(t, 'RGB')
            img.save("degis{0}.png".format(k))
            
            
            img.show()
  
normalize(files)

Are you looking for Normalize — Torchvision 0.12 documentation? This doesn’t change your input images as it transforms the image tensor in memory.

Eg:

img_tensor = torchvision.io.read_image(img_path) 
mean, std = img_tensor.mean(), img_tensor.std()

normalize = torchvision.transforms.normalize(mean, std)
norm_tensor = normalize(img_tensor)
unnorm_tensor = norm_tensor * std + mean

torchvision.io.write_png(unnorm_tensor, 'degis0.png')
2 Likes

I didn’t understand one thing from the documentation. If I used it like that: transforms.Compose([transforms.Normalize()]), and yes it will not change my images, however, I have to give mean and std. And, how I can give your example code logic here? As I got from your code, I have to save new png images as like before.

I hope I explained my question as clearly. Thanks for your help.

You can use it without Compose… Normalize() is like any other module that you can call on an input.

Yes, you will need to give mean and std. In many examples, you’ll see a 3-dimensional mean and std tensor for a 3-channel image. This ensures that the normalization happens channel-wise.

You can save it if you like, I included that line because in your normalize() you are doing that. Here are some ways to visualize without needing to save the tensor to an image: https://pytorch.org/vision/stable/auto_examples/plot_visualization_utils.html#sphx-glr-auto-examples-plot-visualization-utils-py

And, how I can give your example code logic here?

Sorry, I’m not sure what you mean - can you clarify this?

1 Like
  1. I mean that if I want to use this code, how I can give these normalized images to the model?

Yes, you will need to give mean and std. In many examples, you’ll see a 3-dimensional mean and std tensor for a 3-channel image

I understood better now.
So if use this formula, find these 3-dim values and give them to the module, will it be the same/right way to implement the algorithm that I shared?

mean = 0.0
meansq = 0.0
count = 0

for index, data in enumerate(train_loader):
    mean = data.sum()
    meansq = meansq + (data**2).sum()
    count += np.prod(data.shape)

total_mean = mean/count
total_var = (meansq/count) - (total_mean**2)
total_std = torch.sqrt(total_var)
print("mean: " + str(total_mean))
print("std: " + str(total_std))

cited from (https://discuss.pytorch.org/t/computing-the-mean-and-std-of-dataset/34949/20)

What I want to do overall:

I should actually find the mean and standard deviation for the channel of the image I am interested in. Then, calculate the new value (p-m)/s of the pixel in that channel and use it as input.

But, I couldn’t find a proper way to use it without saving images after applying this algorithm.

Does my problem make sense? @suraj.pt

You don’t need to save the image to disk. You can directly use the returned tensor in your function.

# load img from disk
img_tensor = torchvision.io.read_image(img_path) 
mean, std = img_tensor.mean(), img_tensor.std()

# normalize
normalize = torchvision.transforms.normalize(mean, std)
normalized_img_tensor = normalize(img_tensor)

# use normalized image as inputs to your func
my_fn(inputs=normalized_img_tensor)