How to rotate a cube with simple rotation matrix

eranb: <p>I have a rotation matrix:<br>
rotation_A = torch.tensor([[[ 0.7198, -0.6428, -0.2620],<br>
[ 0.5266,  0.7516, -0.3973],<br>
[ 0.4523,  0.1480,  0.8795]]])</p>
<p>and I want to rotate a cube with a size of torch.Size([74, 626, 766]).</p>
<p>How can I do that with PyTorch? or simple python?</p>

KFrank: <p>Hi Eran!</p>
<aside class="quote no-group" data-username="eranb" data-post="1" data-topic="84738" data-full="true">
<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/eranb/48/20672_2.png" class="avatar"> eranb:</div>
<blockquote>
<p>I want to rotate a cube with a size of torch.Size([74, 626, 766]).</p>
</blockquote>
</aside>
<p>If by “cube” you mean that you interpret your 74x626x766 tensor<br>
as a three-dimensional “image,” where each element of the tensor<br>
is a “voxel,” then it is not especially simple to rotate it, and I am not<br>
aware of anything built in to pytorch that will do it for you.</p>
<p>To rotate an image (three-dimensional or not), you have to do the<br>
actual rotation, interpolate pixels (voxels), pad or crop, etc.</p>
<p>If your “cube” is something different than I outlined above, could<br>
you describe your use case in more detail?</p>
<p>Best.</p>
<p>K. Frank</p>

eranb: <p>Hi KFrank and thank you for replay,</p>
<p>I have a CT image (slice, height, width) and I want to rotate it (my major is to create data augmentation after I sum up all the slices every time).</p>
<p>I used this code (I saw it on this forum) :</p>
<p>rotation_A = torch.tensor([[[ 0.7198, 0, 0],<br>
[ 0.5266,  0.7516, 0],<br>
[ 0,  0, 1]]])</p>
<p>input_tensor = cube_TF.squeeze(0).float()<br>
rotation_A = rotation_A.squeeze()<br>
def get_3d_locations(d, h, w, device_):<br>
locations_x = torch.linspace(0, w - 1, w).view(1, 1, 1, w).to(device_).expand(1, d, h, w)<br>
locations_y = torch.linspace(0, h - 1, h).view(1, 1, h, 1).to(device_).expand(1, d, h, w)<br>
locations_z = torch.linspace(0, d - 1, d).view(1, d, 1, 1).to(device_).expand(1, d, h, w)<br>
# stack locations<br>
locations_3d = torch.stack([locations_x, locations_y, locations_z], dim=4).view(-1, 3, 1)<br>
return locations_3d</p>
<p>s = torch.from_numpy(s).float()<br>
device_ = input_tensor.device<br>
<em>, d, h, w = input_tensor.shape<br>
input_tensor = input_tensor.unsqueeze(0)<br>
# get x,y,z indices of target 3d data<br>
locations_3d = get_3d_locations(d, h, w, device</em>)<br>
# rotate target positions to the source coordinate</p>
<p>rotated_3d_positions = torch.bmm(s.view(1, 3, 3).expand(d * h * w, 3, 3), locations_3d).view(1, d, h,w, 3)<br>
rot_locs = torch.split(rotated_3d_positions, split_size_or_sections=1, dim=4)<br>
normalised_locs_x = (2.0 * rot_locs[0] - (w - 1)) / (w - 1)<br>
normalised_locs_y = (2.0 * rot_locs[1] - (h - 1)) / (h - 1)<br>
normalised_locs_z = (2.0 * rot_locs[2] - (d - 1)) / (d - 1)<br>
grid = torch.stack([normalised_locs_x, normalised_locs_y, normalised_locs_z], dim=4).view(1, d, h, w, 3)<br>
# here we use the destination voxel-positions and sample the input 3d data trilinearly<br>
rotated_signal = torch.nn.functional.grid_sample(input=input_tensor, grid=grid, mode=‘nearest’)<br>
rotated_signal = rotated_signal.squeeze(0)</p>
<p>The problem with this code it’s not create new grid so a lot of my image is turning to black (like disappeared). I think it’s not padding and I don’t know how to do that.</p>