Input image changes after converting it back from torch.Tensor

scubes: <p>Hello there, I can’t seem to get my input RGB image back corectly after converting it to tensor, it seems that all 9 smaller pictures differ from each other slightly.<br>
Code to reproduce the problem</p>
<pre><code class="lang-auto">rgb_img = cv2.resize(rgb_img, dsize = (160,120),interpolation=cv2.INTER_CUBIC)
#(120, 160, 3)
cv2.imwrite("rgb_original.jpg",rgb_img)
rgb_img = np.rollaxis(rgb_img, 2)
#(3, 120, 160)
rgb_img = torch.from_numpy(rgb_img)
rgb_img = rgb_img.type(torch.IntTensor)
rgb_img = rgb_img.to(device="cpu")
rgb_img= rgb_img.unsqueeze(0)# this is just to reproduce the same batch dimension of dataloader
#torch.Size([1, 3, 120, 160])
rgb_img = rgb_img.reshape(rgb_img.shape[2], rgb_img.shape[3], rgb_img.shape[1]).cpu().numpy()
cv2.imwrite("rgb_.jpg",rgb_img)
# #print(rgb_img)
</code></pre>
<p><div class="lightbox-wrapper"><a class="lightbox" href="https://discuss.pytorch.org/uploads/default/original/3X/8/d/8d07ca7bac496eb490dccbbf95d3ef19ac07ea80.png" data-download-href="https://discuss.pytorch.org/uploads/default/8d07ca7bac496eb490dccbbf95d3ef19ac07ea80" title="Screenshot_2021-10-10_15-31-10"><img src="https://discuss.pytorch.org/uploads/default/optimized/3X/8/d/8d07ca7bac496eb490dccbbf95d3ef19ac07ea80_2_690x302.png" alt="Screenshot_2021-10-10_15-31-10" data-base62-sha1="k7C0X46ZsDoBjDmRIQvToXGC83m" width="690" height="302" srcset="https://discuss.pytorch.org/uploads/default/optimized/3X/8/d/8d07ca7bac496eb490dccbbf95d3ef19ac07ea80_2_690x302.png, https://discuss.pytorch.org/uploads/default/optimized/3X/8/d/8d07ca7bac496eb490dccbbf95d3ef19ac07ea80_2_1035x453.png 1.5x, https://discuss.pytorch.org/uploads/default/optimized/3X/8/d/8d07ca7bac496eb490dccbbf95d3ef19ac07ea80_2_1380x604.png 2x" data-dominant-color="474B4B"><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">Screenshot_2021-10-10_15-31-10</span><span class="informations">1914×838 158 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>

Sayed_Nadim: <p>Hi,<br>
Your method is almost OK. You forgot to think about the permutation of the axes.<br>
I am giving two methods to save your image.</p>
<pre><code class="lang-auto">import cv2
import numpy as np
import torch
import torchvision.utils as vutils

# reading image
rgb_img = cv2.imread('1.jpg')  # read any image
rgb_img = cv2.resize(rgb_img, dsize=(160, 120), interpolation=cv2.INTER_CUBIC)

# saving original image
cv2.imwrite("rgb_original.jpg", rgb_img)

# using torchvision to save image &lt;- first method
rgb_img_tensor = torch.from_numpy(rgb_img).float() / 255.  # torchvision uses [0,1] range
rgb_img_tensor = rgb_img_tensor.unsqueeze(0).permute(0, 3, 1, 2)
rgb_img_tensor = rgb_img_tensor[:, [2, 1, 0], :, :]  # cv2 reads image in BGR, reversing it to RGB
vutils.save_image(rgb_img_tensor, "first_method.jpg")

# using your method to save image &lt;- second method
rgb_img_orig = np.rollaxis(rgb_img, 2)
rgb_img_orig = torch.from_numpy(rgb_img_orig)
rgb_img_orig = rgb_img_orig.type(torch.IntTensor)
rgb_img_orig = rgb_img_orig.unsqueeze(0)
shape = rgb_img_orig.shape
rgb_img_orig = rgb_img_orig.permute(0, 2, 3, 1).reshape(shape[2], shape[3], shape[1]).cpu().numpy() #  &lt;- permute axes here
cv2.imwrite("second_method.jpg", rgb_img_orig)
</code></pre>
<p><img src="https://discuss.pytorch.org/images/emoji/apple/slight_smile.png?v=10" title=":slight_smile:" class="emoji only-emoji" alt=":slight_smile:"></p>

scubes: <p>Worked like a charm =) Thanks!<br>
I resorted at some point to transform it back to a PIL Image which was not the prettiest way, here it is anyway x.x</p>
<pre><code class="lang-auto">from PIL import Image
import torchvision.transforms
import torchvision.transforms.functional as TF
rgb_img = TF.to_tensor(rgb_img) # rescale it 0&lt;..&lt;1
rgb_img = rgb_img.type(torch.uint8).squeeze(0)
#rgb_img = rgb_img.type(torch.FloatTensor)
img = torchvision.transforms.ToPILImage()(rgb_img)
im = Image.fromarray(img)
img.save("metamorphosis.jpeg")
</code></pre>

scubes: <aside class="quote no-group" data-username="Sayed_Nadim" data-post="2" data-topic="133857">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/sayed_nadim/48/34051_2.png" class="avatar"> Sayed_Nadim:</div>
<blockquote>
<p><code>.type(torch.IntTensor)</code></p>
</blockquote>
</aside>
<p>on an another note, is it not a good an idea to train a one class detection model with RGB values or I should follow the good practice of scaling and normalizing my tensors?</p>

Sayed_Nadim: <p>Hi,<br>
Glad it worked!<br>
I am not sure about what you mean by scaling and normalization. If you are asking about scaling the values in <code>[0,1]</code> range by dividing RGB values with 255 (pixel value max), then yes, you should use scaling. It will help the model with faster convergence.</p>
<p>I generally don’t use normalization very often as it tends to hurt color consistency in image generation task (I work with image inpainting task). But I have seen some strong arguments for normalization for classification tasks. Most of the normalization values are from ImageNet and work well with most of the images.</p>
<p>I would suggest going through some well-known classification architectures to get some pointers on input processing.</p>
<p>Maybe, you can start from <a href="https://pytorch.org/tutorials/beginner/blitz/cifar10_tutorial.html" rel="noopener nofollow ugc">here </a>.</p>
<p><img src="https://discuss.pytorch.org/images/emoji/apple/slight_smile.png?v=10" title=":slight_smile:" class="emoji only-emoji" alt=":slight_smile:"></p>

scubes: <p>Thanks, I will make sure to train my training abilities x) I will check out the ImageNet norm values and try them out, see if I get better results for my nnet. <img src="https://discuss.pytorch.org/images/emoji/apple/yum.png?v=10" title=":yum:" class="emoji" alt=":yum:"></p>