Torchvision ToTensor, don't change channel order

himat: <p>When you use <code>transforms.ToTensor()</code>, by default it changes the input arrays from HWC to CHW order.</p>
<p>Is it possible to have ToTensor not do this if my input data are already in the ordering I want?</p>
<p>What can I replace this code with to make it keep the ordering I want and still convert to a torch tensor?</p>
<pre><code class="lang-auto">transforms.Compose([transforms.ToTensor()])
</code></pre>

Nikronic: <p>Hi,</p>
<p>As there is no parameter in <code>transforms.ToTensor()</code> to control this behavior, the easiest and probably efficient way to solve this issue is to do what PyTorch have in its source code.<br>
</p><aside class="onebox githubblob">
  <header class="source">
      <a href="https://github.com/pytorch/vision/blob/e6b4078ec73c2cf4fd4432e19c782db58719fb99/torchvision/transforms/functional.py#L78" target="_blank" rel="nofollow noopener">github.com</a>
  </header>
  <article class="onebox-body">
    <h4><a href="https://github.com/pytorch/vision/blob/e6b4078ec73c2cf4fd4432e19c782db58719fb99/torchvision/transforms/functional.py#L78" target="_blank" rel="nofollow noopener">pytorch/vision/blob/e6b4078ec73c2cf4fd4432e19c782db58719fb99/torchvision/transforms/functional.py#L78</a></h4>
<pre class="onebox"><code class="lang-py"><ol class="start lines" start="68" style="counter-reset: li-counter 67 ;">
<li>        img = torch.from_numpy(np.array(pic, np.int16, copy=False))</li>
<li>    elif pic.mode == 'F':</li>
<li>        img = torch.from_numpy(np.array(pic, np.float32, copy=False))</li>
<li>    elif pic.mode == '1':</li>
<li>        img = 255 * torch.from_numpy(np.array(pic, np.uint8, copy=False))</li>
<li>    else:</li>
<li>        img = torch.ByteTensor(torch.ByteStorage.from_buffer(pic.tobytes()))</li>
<li>
</li><li>    img = img.view(pic.size[1], pic.size[0], len(pic.getbands()))</li>
<li>    # put it from HWC to CHW format</li>
<li class="selected">    img = img.permute((2, 0, 1)).contiguous()</li>
<li>    if isinstance(img, torch.ByteTensor):</li>
<li>        return img.float().div(255)</li>
<li>    else:</li>
<li>        return img</li>
<li>
</li><li>
</li><li>def pil_to_tensor(pic):</li>
<li>    """Convert a ``PIL Image`` to a tensor of the same type.</li>
<li>
</li><li>    See ``AsTensor`` for more details.</li>
</ol></code></pre>


  </article>
  <div class="onebox-metadata">
    
    
  </div>
  <div style="clear: both"></div>
</aside>

<p>As you can see, it permutes the channels, So, same code can be used to reverse the order.</p>
<p>The reason that PyTorch is doing this is that, PyTorch uses <code>CHW</code> convention by default.</p>
<p>bests,<br>
Nik</p>

rayryeng: <aside class="quote no-group" data-username="Nikronic" data-post="2" data-topic="82038">
<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/nikronic/48/71873_2.png" class="avatar"> Nikronic:</div>
<blockquote>
<p><code>img = img.permute((2, 0, 1)).contiguous()</code></p>
</blockquote>
</aside>
<p>Thanks for this.  Just for the sake of containment if you want to reverse the order done by <code>ToTensor</code>, it would have to be <code>img = img.permute((1, 2, 0)).contiguous()</code>.  The <code>(2, 0, 1)</code> is the forward transformation to go from HWC to CHW.  To undo the operation, the tuple needs to be <code>(1, 2, 0)</code> instead.</p>
<p>Thanks again!</p>