Problem with tensors size?

username: Dalal
cooked: <p>I have two generators that output images:<br>
self.syn_skin = self.G(self.image)<br>
self.syn_hair = self.G(self.image1).<br>
I then apply overlay function to get other images.</p>
<pre><code class="lang-auto">def overlay_images(hair_images, skin_images):
        #os.mkdir('/kaggle/working/Ovelayed_Images/')
        #path= "/kaggle/working/Ovelayed_Images/"
        for i, syn_hair  in enumerate(hair_images):
         for j, syn_skin in enumerate(skin_images):
            img_syn_skin= skin_images.data[i]
            img_syn_hair= hair_images.data[j]
            img_syn_skin = Tensor2Image(img_syn_skin)
            img_syn_hair = Tensor2Image(img_syn_hair)
            #has_transparency = im_has_alpha(np.array(img_syn_skin))
            #print(has_transparency)
            #img_syn_skin=img_syn_skin.convert('RGB')
            #img_syn_hair=img_syn_hair.convert('RGB')
            img_syn_hair_f= img_syn_hair.copy()
            Image.Image.paste(img_syn_hair_f, img_syn_skin) 
            #print (type(img_syn_hair_f))
            img = transforms.ToTensor()(img_syn_hair_f) 
            #print(type(img))
            #print(img.size())
            output.append(img)
            #print(output.size())
            #out=torch.FloatTensor(output)
        out = torch.stack(output)
        #out= torch.tensor(output)
        #print (out.size())
        return out
</code></pre>
<p>These function is applied as follows:<br>
self.overlay_realimage= overlay_images(self.hair, self.skin)<br>
self.overlay_fakeimage= overlay_images(self.syn_hair, self.syn_skin)</p>
<p>where self.hair and self.skin are the groundtruth and self.syn_hair, self.syn_skin are the images generated by the generators.<br>
I want  to compute the MSE loss, when I do that:<br>
self.L2 = nn.MSELoss()<br>
l3=self.L2(self.overlay_realimage, self.overlay_fakeimage)</p>
<p>I get the following error:</p>
<pre><code class="lang-auto">RuntimeError: The size of tensor a (3) must match the size of tensor b (4) at non-singleton dimension 0
</code></pre>
<p>The size of the four tensors self.hair, self.skin, self.syn_hair and self.syn_skin is [1,3,256, 256] where 1 is the batch size.</p>
<p>When I  print the size of self.overlay_realimage and self.overlay_fakeimage, I get<br>
torch.Size([1, 3, 256, 256])<br>
the size of fake images:<br>
torch.Size([2, 3, 256, 256])</p>
<p>Although both are passed through the same function image overlay. How could the result be different. I couldn’t figure it out!<br>
Thanks in advance</p>

username: eqy
cooked: <p>Could you post a short example (e.g., with dummy input data) that is runnable that reproduces the issue? From here it’s a bit hard to see what <code>self.G</code> produces etc.</p>

username: Dalal
cooked: <p>this is an example:</p>
<pre><code class="lang-auto">import torch
image1= torch.rand(1, 3, 256,256)
image2= torch.rand(1, 3, 256,256)
out= overlay_images(image1, image2)
groundtruthimage =torch.rand(1, 3, 256,256)
print (image1.size())
print (image2.size())
print(out.size())
print(type(out))
loss = nn.MSELoss()
loss=loss(out, groundtruthimage)
print (loss)
</code></pre>
<p>the problem is in out computed using overlay_images which produces a tensor of size torch.Size([6, 3, 256, 256]).</p>

username: eqy
cooked: <p>Could you provide a version the function that works with this example (e.g., <code>groundtruthimage</code> doesn’t seem to accept raw tensors and requires <code>Tensor2Image</code> which isn’t defined here):</p>
<pre><code class="lang-auto">import torch
image1= torch.rand(1, 3, 256,256)
image2= torch.rand(1, 3, 256,256)
out= overlay_images(image1, image2)
groundtruthimage =torch.rand(1, 3, 256,256)
print (image1.size())
print (image2.size())
print(out.size())
print(type(out))
loss = nn.MSELoss()
loss=loss(out, groundtruthimage)
print (loss)
</code></pre>
<p>yields<br>
<code>NameError: name 'Tensor2Image' is not defined</code></p>

username: Dalal
cooked: <p>this is the function</p>
<pre><code class="lang-auto">from torchvision import transforms
def Tensor2Image(img):
    """
    input (FloatTensor)
    output (PIL.Image)
    """
    #print('----------------object type--------------------')
    #print(type(img))
    img = img.cpu()                               #tensor.cpu() moves it back to memory accessible to the CPU. Tensor.cuda() is used to move a tensor to GPU memory.
    img = ((img * 0.5) + 0.5)                     # normalization
    img = transforms.ToPILImage()(img) #
    #img=img.convert('RGB')
    return img
    
</code></pre>

username: eqy
cooked: <p>I couldn’t reproduce the issue with a slightly modified version of the above code:</p>
<pre><code class="lang-auto">import torch

from torchvision import transforms
from PIL import Image

def Tensor2Image(img):
    """
    input (FloatTensor)
    output (PIL.Image)
    """
    #print('----------------object type--------------------')
    #print(type(img))
    img = img.cpu()                               #tensor.cpu() moves it back to memory accessible to the CPU. Tensor.cuda() is used to move a tensor to GPU memory.
    img = ((img * 0.5) + 0.5)                     # normalization
    img = transforms.ToPILImage()(img) #
    #img=img.convert('RGB')
    return img

def overlay_images(hair_images, skin_images):
        #os.mkdir('/kaggle/working/Ovelayed_Images/')
        #path= "/kaggle/working/Ovelayed_Images/"
        output = []
        for i, syn_hair  in enumerate(hair_images):
         for j, syn_skin in enumerate(skin_images):
            img_syn_skin= skin_images.data[i]
            img_syn_hair= hair_images.data[j]
            img_syn_skin = Tensor2Image(img_syn_skin)
            img_syn_hair = Tensor2Image(img_syn_hair)
            #has_transparency = im_has_alpha(np.array(img_syn_skin))
            #print(has_transparency)
            #img_syn_skin=img_syn_skin.convert('RGB')
            #img_syn_hair=img_syn_hair.convert('RGB')
            img_syn_hair_f= img_syn_hair.copy()
            Image.Image.paste(img_syn_hair_f, img_syn_skin) 
            #print (type(img_syn_hair_f))
            img = transforms.ToTensor()(img_syn_hair_f) 
            #print(type(img))
            #print(img.size())
            output.append(img)
            #print(output.size())
            #out=torch.FloatTensor(output)
        out = torch.stack(output)
        #out= torch.tensor(output)
        #print (out.size())
        return out

image1= torch.rand(1, 3, 256,256)
image2= torch.rand(1, 3, 256,256)
out= overlay_images(image1, image2)
groundtruthimage =torch.rand(1, 3, 256,256)
print (image1.size())
print (image2.size())
print(out.size())
print(type(out))
loss = torch.nn.MSELoss()
loss=loss(out, groundtruthimage)
print (loss)
</code></pre>
<p>yields</p>
<pre><code class="lang-auto">torch.Size([1, 3, 256, 256])
torch.Size([1, 3, 256, 256])
torch.Size([1, 3, 256, 256])
&lt;class 'torch.Tensor'&gt;
tensor(0.1649)
</code></pre>
<p>It might be worthwhile to check what is not matching between the original and the repro code</p>

username: Dalal
cooked: <aside class="quote no-group" data-username="eqy" data-post="7" data-topic="151334">
<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/eqy/48/46233_2.png" class="avatar"> eqy:</div>
<blockquote>
<pre><code class="lang-auto">import torch

from torchvision import transforms
from PIL import Image

def Tensor2Image(img):
    """
    input (FloatTensor)
    output (PIL.Image)
    """
    #print('----------------object type--------------------')
    #print(type(img))
    img = img.cpu()                               #tensor.cpu() moves it back to memory accessible to the CPU. Tensor.cuda() is used to move a tensor to GPU memory.
    img = ((img * 0.5) + 0.5)                     # normalization
    img = transforms.ToPILImage()(img) #
    #img=img.convert('RGB')
    return img

def overlay_images(hair_images, skin_images):
        #os.mkdir('/kaggle/working/Ovelayed_Images/')
        #path= "/kaggle/working/Ovelayed_Images/"
        output = []
        for i, syn_hair  in enumerate(hair_images):
         for j, syn_skin in enumerate(skin_images):
            img_syn_skin= skin_images.data[i]
            img_syn_hair= hair_images.data[j]
            img_syn_skin = Tensor2Image(img_syn_skin)
            img_syn_hair = Tensor2Image(img_syn_hair)
            #has_transparency = im_has_alpha(np.array(img_syn_skin))
            #print(has_transparency)
            #img_syn_skin=img_syn_skin.convert('RGB')
            #img_syn_hair=img_syn_hair.convert('RGB')
            img_syn_hair_f= img_syn_hair.copy()
            Image.Image.paste(img_syn_hair_f, img_syn_skin) 
            #print (type(img_syn_hair_f))
            img = transforms.ToTensor()(img_syn_hair_f) 
            #print(type(img))
            #print(img.size())
            output.append(img)
            #print(output.size())
            #out=torch.FloatTensor(output)
        out = torch.stack(output)
        #out= torch.tensor(output)
        #print (out.size())
        return out

image1= torch.rand(1, 3, 256,256)
image2= torch.rand(1, 3, 256,256)
out= overlay_images(image1, image2)
groundtruthimage =torch.rand(1, 3, 256,256)
print (image1.size())
print (image2.size())
print(out.size())
print(type(out))
loss = torch.nn.MSELoss()
loss=loss(out, groundtruthimage)
print (loss)
</code></pre>
</blockquote>
</aside>
<p>I tested your code. It is working perfectly. I will compare it with mine.<br>
Thanks a lot.</p>