如何在给定旋转矩阵的情况下围绕其中心旋转numpy 3D数组?

h9a6wy2h  于 11个月前  发布在  其他
关注(0)|答案(2)|浏览(125)

我有一个3Dnumpy数组shape=(50, 50, 50),我想绕中心旋转,使用旋转矩阵R
我正在尝试使用scipy.ndimage.affine_transform来实现这一点,但我愿意接受更好的建议。
这是显示问题的代码:

import random
import numpy as np
import scipy
from PIL import Image

R = np.array([
    [ 0.299297976, -0.817653322, -0.491796468],
    [-0.425077904, -0.575710904,  0.698473858],
    [-0.854242060,            0, -0.519875469],
])
print('Is R really orthogonal:', np.allclose(np.dot(R, R.T), np.identity(3)))  # True

# initialize some random data:
a = (50 + np.random.rand(50, 50, 50)*200).astype(np.uint8)
print(a.shape)  # (50, 50, 50)
Image.fromarray(a[:, :, 25]).show()

b = scipy.ndimage.affine_transform(a, R, offset=0)
Image.fromarray(b[:, :, 25]).show()

c = scipy.ndimage.affine_transform(a, R, offset=(50, 50, 50))
Image.fromarray(c[:, :, 25]).show()

字符串
x1c 0d1x的数据




令我意想不到的是:

  • 以偏移量0旋转似乎不会围绕中心旋转
  • 看最后一幅图像,这个矩阵所做的操作不仅仅是旋转,还有某种扭曲/剪切

我错过了什么?

编辑:@Nin17的答案是正确的,这是适应原始(3D)问题的版本:

import random
import numpy as np
import scipy
from PIL import Image

R = np.array([
    [ 0.299297976, -0.817653322, -0.491796468, 0.],
    [-0.425077904, -0.575710904,  0.698473858, 0.],
    [-0.854242060,           0., -0.519875469, 0.],
    [          0.,           0.,           0., 1.],
])

N = 50

shift = np.array(
    [
        [1, 0, 0, N / 2],
        [0, 1, 0, N / 2],
        [0, 0, 1, N / 2],
        [0, 0, 0,     1],
    ]
)
unshift = np.array(
    [
        [1, 0, 0, -N / 2],
        [0, 1, 0, -N / 2],
        [0, 0, 1, -N / 2],
        [0, 0, 0,      1],
    ]
)

print('Is R orthogonal:', np.allclose(np.dot(R, R.T), np.identity(4)))  # True

a = (50 + np.random.rand(N, N, N)*200).astype(np.uint8)
print(a.shape)  # (50, 50, 50)
Image.fromarray(a[:, :, N//2]).show()

b = scipy.ndimage.affine_transform(a, shift @ R @ unshift, offset=0)
Image.fromarray(b[:, :, N//2]).show()


rks48beu

rks48beu1#

affine_transform的文档中,它指出:
Given an output image pixel index vector o, the pixel value is determined from the input image at position np.dot(matrix, o) + offset.
因此,纯旋转矩阵将围绕索引为(0,0)的像素旋转数组(在2d中)。为了围绕图像的中心旋转,您可以在旋转之前和之后应用平移来移动图像坐标,使得中心在(0,0)执行旋转,然后将图像移回,在2d中这可能看起来像这样:

import numpy as np
from scipy.ndimage import affine_transform
import matplotlib.pyplot as plt

rng = np.random.default_rng()

theta = rng.random() * np.pi * 2
rotation2d = np.array(
    [
        [np.cos(theta), -np.sin(theta), 0.0],
        [np.sin(theta), np.cos(theta), 0.0],
        [0.0, 0.0, 1.0],
    ]
)

N, M = 50, 51

image = rng.random((N, M))

shift = np.array(
    [
        [1, 0, N / 2],
        [0, 1, M / 2],
        [0, 0, 1], # need to also apply shift on third axes for 3d array
    ]
)
unshift = np.array(
    [
        [1, 0, -N / 2],
        [0, 1, -M / 2],
        [0, 0, 1], # need to also apply shift on third axes for 3d array
    ]
)

plt.figure()
plt.imshow(image)

plt.figure()
plt.imshow(affine_transform(image, rotation2d))

plt.figure()
plt.imshow(affine_transform(image, shift @ rotation2d @ unshift))

字符串
输出量:


的数据



pdkcd3nj

pdkcd3nj2#

第一个问题是由@Nin17回答的,至于第二个问题:
看最后一幅图像,这个矩阵所做的操作不仅仅是旋转,还有某种扭曲/剪切
我不认为你看到的是剪切,而是输出图像的平面与立方体(你的输入图像)相交的效果。根据你的旋转矩阵,那个平面可能会切掉立方体的一个角。如果你定义旋转是围绕立方体的一个轴,你就不会再看到这个了。例如:

from scipy.spatial.transform import Rotation
R = Rotation.from_euler('z', 45, degrees=True).as_matrix()

字符串

相关问题