CIFAR 10 renormalization issue with PIL saved images

username: GirardR1006
cooked: <p>Hello fellows,</p>
<p>I do have an issue to properly display images with CIFAR10 and PIL.<br>
My dataset is loaded using torchvision.datasets as follow (mean and std values are from the CIFAR 10 standard mean and std values):</p>
<pre><code>        dataset=datasets.CIFAR10('CIFAR10', train=False, 
                   download=True,
                   transform=transforms.Compose([
                       transforms.ToTensor(),
                       transforms.Normalize(mean=[0.485, 0.456, 0.406],
                                            std=[0.229, 0.224, 0.225])
                   ]))
</code></pre>
<p>Later in my code, I want to unnormalize some image to save them on disk and visualize them later:</p>
<p>I thus follow the definition of <code>transforms.Normalize</code> at <a href="https://pytorch.org/docs/master/torchvision/transforms.html#torchvision.transforms.Normalize" rel="noopener nofollow ugc">https://pytorch.org/docs/master/torchvision/transforms.html#torchvision.transforms.Normalize</a> to obtain my original images:</p>
<pre><code>def convert_cifar10(t,pil):
    """Function to convert a cifar10 image tensor (already normalized)
    onto a plotable image.
    
    :param t: image tensor of size (3,32,23)
    :type t: torch.Tensor
    :param pil: output is of size (3,32,32) if True, else (32,32,3)
    :type pil: bool
    """
    im = t.detach().cpu()
    # approximate unnormalization 
    im[0] = im[0]*0.229 + 0.485
    im[1] = im[1]*0.224 + 0.456
    im[2] = im[2]*0.225 + 0.406
    if not pil:
        im = im.numpy()
        im = np.transpose(im,(1,2,0))
    return im
</code></pre>
<p>The minimal example is the following:</p>
<pre><code>dataiter = iter(dataset)
data, label = dataiter.next()
original_img = convert_cifar10(data[0],pil=False)
plt.imshow(original_img)
plt.show()
second = convert_cifar10(data[0],pil=False)
plt.imshow(second)
plt.show()
</code></pre>
<p>The first plot displays something normal (cannot diplay it as a new user, but they are for sure the original dataset images).<br>
The second one is much less coloured:<br>
<div class="lightbox-wrapper"><a class="lightbox" href="https://discuss.pytorch.org/uploads/default/original/2X/1/1f0c057320a3d5a9e821da6a88d2682a4b56c2c9.png" data-download-href="https://discuss.pytorch.org/uploads/default/1f0c057320a3d5a9e821da6a88d2682a4b56c2c9" title="Figure_2"><img src="https://discuss.pytorch.org/uploads/default/original/2X/1/1f0c057320a3d5a9e821da6a88d2682a4b56c2c9.png" alt="Figure_2" data-base62-sha1="4qEyxote7flh2TDpTtfhQosOpId" width="517" height="129" data-dominant-color="EAE9E5"><div class="meta"><svg class="fa d-icon d-icon-far-image svg-icon" aria-hidden="true"><use href="#far-image"></use></svg><span class="filename">Figure_2</span><span class="informations">956×241 8.13 KB</span><svg class="fa d-icon d-icon-discourse-expand svg-icon" aria-hidden="true"><use href="#discourse-expand"></use></svg></div></a></div></p>
<p>I may have applied twice the transformation on the input tensor, but the documentation explicitly states that the operation is made out of place:<br>
<code>This transform acts out of place, i.e., it does not mutates the input tensor.</code></p>
<p>Is there anything I have misunderstood?</p>
<p>Thank you in advance <img src="https://discuss.pytorch.org/images/emoji/apple/slight_smile.png?v=12" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p>

username: GirardR1006
cooked: <p>My mistake, I double checked my code today and I realized I used the <code>.cpu()</code> routine. According to the documentation at <a href="https://pytorch.org/docs/stable/tensors.html#torch.Tensor.cpu" rel="nofollow noopener">https://pytorch.org/docs/stable/tensors.html#torch.Tensor.cpu</a>:</p>
<p><code>Returns a copy of this object in CPU memory. If this object is already in CPU memory and on the correct device, then no copy is performed and the original object is returned.</code></p>
<p>So I was just normalizing twice my inputs, since the second call returned me the already unnormalized image.</p>
<p>A solution to work on a copy of the tensor is to use <code>torch.Tensor.clone()</code>.</p>