How can I convert a numpy array (with data type of float32 - from Nifti image) to PIL Image?

Hi PyTorch buddies,

I am reading in Nifti images using nibabel and try to do some preprocessing on the image using torchvision.transforms. However, I realised that it has to be converted to PIL Image before I can use functions in torchvision.transforms.

What I achieved was that I loaded the image and converted it to a numpy array of data type of float32. However, I could not convert the array to PIL Image with the error of “Cannot handle this data type”. I looked for some solutions online by changing the data type to “uint8”, but in this case I shouldn’t change my data type to that. I also tried different conversion of data types, but they also didn’t work out.

Below are the codes that I wrote:

image = nib.load(dir_img)
image_data = image.get_fdata().copy()  
imgData_ft = image_data.astype(np.float32)
imgData_ft = np.squeeze(imgData_ft)
imgData_tensor = transform(imgData_ft)

where transform is defined as follows:

transform = transforms.Compose([    
    transforms.ToPILImage(),
    transforms.CenterCrop(159),
    transforms.ToTensor()
    ])

I am glad to hear any clue from you! Thank you so much for your help.

torchvision.transforms. ToPILImage ( mode=None )[SOURCE]
Convert a tensor or an ndarray to PIL Image.
Converts a torch.*Tensor of shape C x H x W or a numpy ndarray of shape H x W x C to a PIL Image while preserving the value range.
Note: The shape of numpy ndarray should be HxWxC and the range of value in numpy.ndarray (H x W x C) should be [0, 255]. Your code meets such requirement?

1 Like

No… The shape should be fine. But the values I have is in the range of [-1,1]. I prefer not to alter the values of the data…

You should change range to [0, 255] like this:
imgData_fit = (imgData_fit + 1) * 127.5
imgData_fit = imgData_fit.astype(np.uint8)

then define transform like this:
transform = transforms.Compose([
transforms.ToPILImage(),
transforms.CenterCrop(159),
transforms.ToTensor(), # [0, 1]
transforms.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5)) # 3 channels -> [-1, 1]
])
finally,
imgData_tensor = transform(imgData_ft) should be right

1 Like

Thank you for your help!