'Convert image to tensor with range [0,255] instead of [0,1]?

I'm trying to use transforms.compose to convert my images into normalized images with a range of [0,255] instead of normalizing it as [0,1] for training my model. How do I make my code do this. Currently it normalizes the images from [0,1]. How would i just multiply this up to 255 to make it 0-255 or is it not that simple?

def build_model(self):
        """ DataLoader """
        train_transform = transforms.Compose([
            transforms.RandomHorizontalFlip(),
            transforms.Resize((self.img_size + 30, self.img_size+30)),
            transforms.RandomCrop(self.img_size),
            transforms.ToTensor(),
            transforms.Normalize(mean=(0.5, 0.5, 0.5), std=(0.5, 0.5, 0.5))
        ])
        test_transform = transforms.Compose([
            transforms.Resize((self.img_size, self.img_size)),
            transforms.ToTensor(),
            transforms.Normalize(mean=(0.5, 0.5, 0.5), std=(0.5, 0.5, 0.5))
        ])


Solution 1:[1]

Ideally you would normalize values between [0, 1] then standardize by calculating the mean and std of your whole training set and apply it to all datasets (training, validation and test set).

The following is essentially a x in [x_min, x_max] -> x' in [0, 1] mapping:

x_min, x_max = x.min(), x.max()
x = (x - x_min) / (x_max-x_min)

Then standardize, for instance with the z-score, which makes mean(x')=0 and std(x')=1:

mean, std = x.mean(), x.std()
x = (x - mean) / std

Back to your question, torchvision.transforms.Normalize is described as:

output[channel] = (input[channel] - mean[channel]) / std[channel]

If you divide your std argument by 255 then you will end multiply by 255 the output.

Here's an exemple with shape (b=1, c=3, h=1, w=3):

> x = torch.tensor([[[[0.2, 0.3, 0.6]], [[0.1, 0.4, 0.2]], [[0.1, 0.8, 0.6]]]])

> mean, std = x.mean(), x.std()
tensor(0.3667), tensor(0.2500)

> t = T.Normalize(mean=mean, std=std/255)

> t(x).mean(), t(x).std()
tensor(~0), tensor(255.)

However, if you're just looking to multiply your data by 255 inside the torchvision.transforms.Compose pipeline you can just do:

T.Compose([
    # other transforms
    T.ToTensor(),
    T.Normalize(mean=(0,)*3, std=(255,)*3)
])

Or with just a lambda:

T.Compose([
    # other transforms
    T.ToTensor(),
    lambda x: x*255
])

Having imported torchvision.transforms as T.

Solution 2:[2]

First Option

I noticed you can achieve the conversion without normalization when you don't use ToTensor and do the conversion over numpy instead. Then the resulting tensor will not be normalized at all.

My examples are using the pillow. When converting to image again go with numpy again and don't use ToPilImage as well.

So:

from PIL import Image
import numpy as np

image = Image.open('image.jpg')
im_arr = np.array(image)
# optional type conversion
im_arr = im_arr.astype(np.float32)
image_tensor = torch.tensor(image).unsqueeze_(0)

# do stuff with your image

img_np_arr = np.array(image_tensor_conv2d.squeeze_(0))
valid_pil_image = Image.fromarray(img_np_arr).convert('RGB')
valid_pil_image.save('image_torch.jpg')

will do the job as well.

As composer you could write like

image_transform = transfroms.Compose([
          transforms.Lambda(lambda image: torch.tensor(numpy.array(image).astype(numpy.float32)).unsqueeze(0)),
          transforms.Normalize((value,), (value,))
)]

See here for reference

Second Option

Another option would be to use PilToTensor instead. Check https://pytorch.org/vision/stable/generated/torchvision.transforms.PILToTensor.html

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2