How to rotate 90 and 270 degrees of 5D tensor

John1231983: <p>According to <a href="https://github.com/pytorch/pytorch/pull/7873" rel="nofollow noopener">https://github.com/pytorch/pytorch/pull/7873</a>, the flip function have been merged in pytorch. I am using version 0.41 and it works for 5D tensor. My 5D tensor is <code>BxCxDxHxW</code>. For flipping, I just use</p>
<pre><code class="lang-auto">images=images.flip(4) # flip along 4th dim
images=image.flip(3) # flip along 3rd dim
</code></pre>
<p>However, the above functions are equivalent to the vertical and horizontal axis. How could I rotate the tensor 90 degrees or 270 degrees along 3rd or 4th dim?</p>
<p>Thanks!</p>

ptrblck: <p>I guess you could achieve it with <code>transpose</code>:</p>
<pre><code class="lang-python">x = torch.zeros(1, 1, 1, 4, 4)
x[:, :, :, 3] = 1.
x90 = x.transpose(3, 4)
</code></pre>
<p>Would that work for you?</p>

John1231983: <p>Great, it works. How about rotation 270 degree?</p>

ptrblck: <p>This should work for 270 degrees. Sorry for missing it in the first reply:</p>
<pre><code class="lang-python">x270 = x.transpose(3, 4).flip(4)
</code></pre>

kelam_goutam: <p><a class="mention" href="/u/ptrblck">@ptrblck</a> I am currently using torch 0.4 and tried to run your snippet. I get an attribute error saying ‘Tensor’ object has no attribute ‘flip’.</p>

John1231983: <p>Upgrade it to 0.4.10…</p>

Happsky: <p><a class="mention" href="/u/ptrblck">@ptrblck</a> For a 4D tensor, how to rotate 90, 180 and 270 degrees? Thanks in advance.</p>
<p>Is these right?<br>
x90=x.transpose(2,3)<br>
x180=x.flip(3)<br>
x270=x.transpose(2,3).flip(2)</p>

ptrblck: <p>There are some minor issue. I think this would work for you <img src="https://discuss.pytorch.org/images/emoji/apple/wink.png?v=6" title=":wink:" class="emoji" alt=":wink:"></p>
<pre><code class="lang-python">
x = torch.zeros(1, 1, 4, 4)
x[:, :, 3] = 1.

x90 = x.transpose(2, 3)
x180 = x.flip(2)
x270 = x.transpose(2, 3).flip(3)

print(x)
print(x90)
print(x180)
print(x270)
</code></pre>

Happsky: <p>That works for me, thank you.</p>

Happsky: <p>Hi, <a class="mention" href="/u/ptrblck">@ptrblck</a> do you know to rotate any degrees, such as 36 and 72?</p>

ptrblck: <p>I’m not sure, but I think <a href="https://pytorch.org/docs/stable/torchvision/transforms.html#torchvision.transforms.LinearTransformation">transforms.LinearTransformation</a> would be a good approach. You would need to create the transformation matrix offline and apply it on the tensor. I’m currently not on my computer, otherwise I would create a small example. Let me know if that’s desirable and I could write it a bit later.</p>

Happsky: <p>Sure, could you mind providing the example? Thank you in advance.</p>

ptrblck: <p>Sorry for the late answer. Apparently I was mistaken and <code>LinearTransformation</code> will probably not work in this case.</p>
<p>If you are dealing with image data, the easiest approach would be to use <a href="https://pytorch.org/docs/stable/torchvision/transforms.html#torchvision.transforms.functional.rotate">transforms.functional.rotate</a>.</p>
<p>However, this won’t work on arbitrary tensors.<br>
Therefore, I’ve created a small (quick and dirty) example using a rotation matrix to rotate your tensor.<br>
The first part uses nested for loops to perform the rotation and will most likely be slow. It’s just for the sake of debugging and I think the code is a bit easier to understand.<br>
In the second part I’ve basically used the first code and used some matmuls to speed it up.<br>
Note that I haven’t tested all edge cases, so please ping me, if you encounter any issues.</p>
<pre><code class="lang-python"># Create dummy image
im = torch.zeros(1, 1, 10, 10)
im[:, :, :, 2] = 1.

# Set angle
angle = torch.tensor([72 * np.pi / 180.])

# Calculate rotation for each target pixel
x_mid = (im.size(2) + 1) / 2.
y_mid = (im.size(3) + 1) / 2.
im_rot = torch.zeros_like(im)
for r in range(im.size(2)):
    for c in range(im.size(3)):
        x = (r - x_mid) * torch.cos(angle) + (c - y_mid) * torch.sin(angle)
        y = -1.0 * (r - x_mid) * torch.sin(angle) + (c - y_mid) * torch.cos(angle)
        x = torch.round(x) + x_mid
        y = torch.round(y) + y_mid
        
        if (x &gt;= 0 and y&gt;=0 and x&lt;im.size(2) and y&lt;im.size(3)):
            im_rot[:, :, r, c] = im[:, :, x.long(), y.long()]


# Calculate rotation with inverse rotation matrix
rot_matrix = torch.tensor([[torch.cos(angle), torch.sin(angle)],
                            [-1.0*torch.sin(angle), torch.cos(angle)]])

# Use meshgrid for pixel coords
xv, yv = torch.meshgrid(torch.arange(im.size(2)), torch.arange(im.size(3)))
xv = xv.contiguous()
yv = yv.contiguous()
src_ind = torch.cat((
    (xv.float() - x_mid).view(-1, 1),
    (yv.float() - y_mid).view(-1, 1)),
    dim=1
)
    
# Calculate indices using rotation matrix
src_ind = torch.matmul(src_ind, rot_matrix.t())
src_ind = torch.round(src_ind)

src_ind += torch.tensor([[x_mid, y_mid]])

# Set out of bounds indices to limits
src_ind[src_ind &lt; 0] = 0.
src_ind[:, 0][src_ind[:, 0] &gt;= im.size(2)] = float(im.size(2)) - 1
src_ind[:, 1][src_ind[:, 1] &gt;= im.size(3)] = float(im.size(3)) - 1
 
im_rot2 = torch.zeros_like(im)
src_ind = src_ind.long()
im_rot2[:, :, xv.view(-1), yv.view(-1)] = im[:, :, src_ind[:, 0], src_ind[:, 1]]
im_rot2 = im_rot2.view(1, 1, 10, 10)
print(im_rot)
print(im_rot2)
</code></pre>

JuanFMontesinos: <p>I was wondering if rotation can be achieved using tensor.permute()</p>
<p>Thinking in dimensions permute performs a rotation. For example if we go from a matrix [channels,H,W]  1x5x10 to a matrix 5x10x1 we are doing nothing but a rotation.</p>
<p>I was wondering if permute also rearrange tensors (makes no sense to me, cos then it would be replacing .view())</p>

amazing_coder: <p>I think this may be correct.</p>
<pre><code class="lang-auto">import torch
import numpy as np
x= torch.tensor(np.arange(8)).view(2,2,2)
x90 = x.transpose(0, 1).flip(0)
x180 = x.flip(0).flip(1)
x270 = x.transpose(0, 1).flip(1)
</code></pre>
<p>I have tried.</p>

Happsky: <p><a class="mention" href="/u/ptrblck">@ptrblck</a> sorry for late reply.<br>
And I got the following error,</p>
<pre><code class="lang-auto">xv, yv = torch.meshgrid(torch.arange(im.size(2)), torch.arange(im.size(3)))
TypeError: meshgrid() takes 1 positional argument but 2 were given
</code></pre>
<p>And I find the answer,</p>
<blockquote>
<p>xv, yv = torch.meshgrid(torch.arange(im.size(2)), torch.arange(im.size(3)))</p>
</blockquote>
<p>should be,</p>
<blockquote>
<p>xv, yv = torch.meshgrid([torch.arange(im.size(2)), torch.arange(im.size(3))])</p>
</blockquote>

ptrblck: <p>Sorry for the confusion.<br>
I’ve used the <code>1.0</code> preview and didn’t realize the arguments of <code>torch.meshgrid</code> were changed.<br>
Glad you figured it out!</p>

MakeDirtyCode: <p>I think <a href="https://discuss.pytorch.org/u/amazing_coder">amazing_coder</a>’s code is right.</p>
<p>x[…, 3] = torch.tensor([1,2,3,4])</p>
<p>In this case, think about your code.<br>
x90 = x.transpose(2, 3)</p>
<p>than x90 is<br>
tensor([[[[0., 0., 0., 0.],<br>
[0., 0., 0., 0.],<br>
[0., 0., 0., 0.],<br>
[1., 2., 3., 4.]]]])</p>
<p>It’s not right way about rotate 90 degree. This should have a flip.</p>

ntomita: <p>Another upvote for <a class="mention" href="/u/amazing_coder">@amazing_coder</a>’s code.<br>
<a class="mention" href="/u/ptrblck">@ptrblck</a>’s <a href="https://discuss.pytorch.org/t/how-to-rotate-90-and-270-degrees-of-5d-tensor/22476/8?u=ntomita">code</a> looks like working but it actually flips along another axis. Suppose you have a cat image, and you apply a horizontal flip and call it a 180 degree rotation, that’s not accurate, right? The same happens with tensor.transpose. That’s why you need another flip to correct the orientation (e.g., a vertical flip for the cat case).</p>
<p>Here, just to generalize the solution.</p>
<pre><code class="lang-auto"># x is a tensor, and d1, d2 are the dimensions of your interest, then
x90 = x.transpose(d1, d2).flip(d1)
x180 = x.flip(d1).flip(d2)
x270 = x.transpose(d1, d2).flip(d2)
</code></pre>
<p>Note that d1,d2 are 0-indexed.</p>

zahra: <p>Hi,</p>
<p>How I can upgrade pytorch. I work cpu-based and the version of my pytorch is 0.4.0.<br>
I tried this command:<br>
conda install pytorch-cpu torchvision-cpu -c pytorch<br>
and now flip is known but the version is not upgraded. But I do not know exactly what I did <img src="https://discuss.pytorch.org/images/emoji/apple/smile.png?v=9" title=":smile:" class="emoji" alt=":smile:"></p>
<p>Thanks</p>