# How to rotate 90 and 270 degrees of 5D tensor

According to https://github.com/pytorch/pytorch/pull/7873, the flip function have been merged in pytorch. I am using version 0.41 and it works for 5D tensor. My 5D tensor is `BxCxDxHxW`. For flipping, I just use

``````images=images.flip(4) # flip along 4th dim
images=image.flip(3) # flip along 3rd dim
``````

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?

Thanks!

I guess you could achieve it with `transpose`:

``````x = torch.zeros(1, 1, 1, 4, 4)
x[:, :, :, 3] = 1.
x90 = x.transpose(3, 4)
``````

Would that work for you?

4 Likes

Great, it works. How about rotation 270 degree?

This should work for 270 degrees. Sorry for missing it in the first reply:

``````x270 = x.transpose(3, 4).flip(4)
``````
2 Likes

@ptrblck 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â€™.

1 Like

@ptrblck For a 4D tensor, how to rotate 90, 180 and 270 degrees? Thanks in advance.

Is these right?
x90=x.transpose(2,3)
x180=x.flip(3)
x270=x.transpose(2,3).flip(2)

There are some minor issue. I think this would work for you

``````
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)
``````
2 Likes

That works for me, thank you.

Hi, @ptrblck do you know to rotate any degrees, such as 36 and 72?

Iâ€™m not sure, but I think transforms.LinearTransformation 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.

Sure, could you mind providing the example? Thank you in advance.

Sorry for the late answer. Apparently I was mistaken and `LinearTransformation` will probably not work in this case.

If you are dealing with image data, the easiest approach would be to use transforms.functional.rotate.

However, this wonâ€™t work on arbitrary tensors.
Therefore, Iâ€™ve created a small (quick and dirty) example using a rotation matrix to rotate your tensor.
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.
In the second part Iâ€™ve basically used the first code and used some matmuls to speed it up.
Note that I havenâ€™t tested all edge cases, so please ping me, if you encounter any issues.

``````# 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 >= 0 and y>=0 and x<im.size(2) and y<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 < 0] = 0.
src_ind[:, 0][src_ind[:, 0] >= im.size(2)] = float(im.size(2)) - 1
src_ind[:, 1][src_ind[:, 1] >= 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)
``````
1 Like

I was wondering if rotation can be achieved using tensor.permute()

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.

I was wondering if permute also rearrange tensors (makes no sense to me, cos then it would be replacing .view())

I think this may be correct.

``````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)
``````

I have tried.

3 Likes

And I got the following error,

``````xv, yv = torch.meshgrid(torch.arange(im.size(2)), torch.arange(im.size(3)))
TypeError: meshgrid() takes 1 positional argument but 2 were given
``````

xv, yv = torch.meshgrid(torch.arange(im.size(2)), torch.arange(im.size(3)))

should be,

xv, yv = torch.meshgrid([torch.arange(im.size(2)), torch.arange(im.size(3))])

Sorry for the confusion.
Iâ€™ve used the `1.0` preview and didnâ€™t realize the arguments of `torch.meshgrid` were changed.

I think amazing_coderâ€™s code is right.

x[â€¦, 3] = torch.tensor([1,2,3,4])

x90 = x.transpose(2, 3)

than x90 is
tensor([[[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[1., 2., 3., 4.]]]])

Itâ€™s not right way about rotate 90 degree. This should have a flip.

Another upvote for @amazing_coderâ€™s code.
@ptrblckâ€™s code 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).

Here, just to generalize the solution.

``````# 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)
``````

Note that d1,d2 are 0-indexed.

4 Likes

Hi,

How I can upgrade pytorch. I work cpu-based and the version of my pytorch is 0.4.0.
I tried this command:
conda install pytorch-cpu torchvision-cpu -c pytorch
and now flip is known but the version is not upgraded. But I do not know exactly what I did

Thanks