Search code examples
pytorchcomputer-visionpython-imaging-libraryimage-segmentationfast-ai

PIL Image library load and save changing pixel values


I am currently working on an Image segmentation problem. As part of preprocessing, I'm trying to create mask values for 2 classes [0, 1].
While, saving the processed tensor and loading them back produces different mask values.
My current guess is under the hood PIL normalizing pixel values.
If so how do I stop it from doing?

I have created below a simple example explaining the same.

tensor_img = torch.where(torch.Tensor(250,250,3) > 0, 1, 0)
img_arr = tensor_img.numpy().astype(np.uint8)
np.unique(img_arr, return_counts=True)

(array([0, 1], dtype=uint8), array([148148, 39352]))

img = Image.fromarray(img_arr) 
img.save("tmp.jpg")

#read saved image
img = PIL.create("tmp.jpg")
tensor(img).unique(return_counts=True)

(tensor([0, 1], dtype=torch.uint8), tensor([62288, 212]))


Solution

  • For this simple case (only 2 classes), you need to work with png and not jpeg since jpeg is a lossy compression and png is lossless.

    tensor_img = torch.where(torch.Tensor(250,250,3) > 0, 1, 0)
    img_arr = tensor_img.numpy().astype(np.uint8)
    np.unique(img_arr, return_counts=True)
    

    (array([0, 1], dtype=uint8), array([159189, 28311]))

    img = Image.fromarray(img_arr) 
    img.save("tmp.png")
    
    #read saved image
    img = np.array(Image.open("tmp.png"))
    torch.tensor(img).unique(return_counts=True)
    

    (tensor([0, 1], dtype=torch.uint8), tensor([159189, 28311]))

    For more classes it is preferred to work with color map.