Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在python中将由Euler角度定义的旋转应用于3D图像_Python_Image Processing_3d_Image Rotation_Euler Angles - Fatal编程技术网

在python中将由Euler角度定义的旋转应用于3D图像

在python中将由Euler角度定义的旋转应用于3D图像,python,image-processing,3d,image-rotation,euler-angles,Python,Image Processing,3d,Image Rotation,Euler Angles,我正在处理3D图像,必须根据“zxz”约定中的欧拉角(φ、psi、θ)旋转它们(这些欧拉角是数据集的一部分,所以我必须使用该约定)。我发现函数scipy.ndimage.rotate在这方面似乎很有用 arrayR = scipy.ndimage.rotate(array , phi, axes=(0,1), reshape=False) arrayR = scipy.ndimage.rotate(arrayR, psi, axes=(1,2), reshape=False) arrayR =

我正在处理3D图像,必须根据“zxz”约定中的欧拉角(φ、psi、θ)旋转它们(这些欧拉角是数据集的一部分,所以我必须使用该约定)。我发现函数scipy.ndimage.rotate在这方面似乎很有用

arrayR = scipy.ndimage.rotate(array , phi, axes=(0,1), reshape=False)
arrayR = scipy.ndimage.rotate(arrayR, psi, axes=(1,2), reshape=False)
arrayR = scipy.ndimage.rotate(arrayR, the, axes=(0,1), reshape=False)
可悲的是,这并没有达到预期的效果。这就是为什么:

定义:

在z-x-z约定中,x-y-z帧旋转三次:第一次 绕z轴旋转一个角度φ;然后通过一个 角度psi;然后,以θ角对最新的z轴进行调整

但是,对于上述代码,旋转始终相对于原始轴。这就是为什么获得的旋转是不正确的。有人建议获得正确的旋转,如定义中所述

换句话说,在当前的“zxz”约定中,旋转是固有的(围绕旋转坐标系XYZ的轴旋转,与运动物体保持一致,在每次元素旋转后改变其方向)。如果我使用上面的代码,旋转是外在的(围绕原始坐标系的xyz轴旋转,假设该坐标系保持不变)。我需要一种在python中进行外部旋转的方法。

我通过这个链接找到了一个令人满意的解决方案:

该方法使用np.meshgrid、scipy.ndimage.map_坐标。上面的链接使用一些第三方库来生成旋转矩阵,但是我使用scipy.spatial.transform.rotation。此函数允许定义内部和外部旋转:请参见scipy.spatial.transform.Rotation.from_euler的说明

以下是我的功能:

import numpy as np
from scipy.spatial.transform import Rotation as R
from scipy.ndimage import map_coordinates

# Rotates 3D image around image center
# INPUTS
#   array: 3D numpy array
#   orient: list of Euler angles (phi,psi,the)
# OUTPUT
#   arrayR: rotated 3D numpy array
# by E. Moebel, 2020
def rotate_array(array, orient):
    phi = orient[0]
    psi = orient[1]
    the = orient[2]

    # create meshgrid
    dim = array.shape
    ax = np.arange(dim[0])
    ay = np.arange(dim[1])
    az = np.arange(dim[2])
    coords = np.meshgrid(ax, ay, az)

    # stack the meshgrid to position vectors, center them around 0 by substracting dim/2
    xyz = np.vstack([coords[0].reshape(-1) - float(dim[0]) / 2,  # x coordinate, centered
                     coords[1].reshape(-1) - float(dim[1]) / 2,  # y coordinate, centered
                     coords[2].reshape(-1) - float(dim[2]) / 2])  # z coordinate, centered

    # create transformation matrix
    r = R.from_euler('zxz', [phi, psi, the], degrees=True)
    mat = r.as_matrix()

    # apply transformation
    transformed_xyz = np.dot(mat, xyz)

    # extract coordinates
    x = transformed_xyz[0, :] + float(dim[0]) / 2
    y = transformed_xyz[1, :] + float(dim[1]) / 2
    z = transformed_xyz[2, :] + float(dim[2]) / 2

    x = x.reshape((dim[1],dim[0],dim[2]))
    y = y.reshape((dim[1],dim[0],dim[2]))
    z = z.reshape((dim[1],dim[0],dim[2])) # reason for strange ordering: see next line

    # the coordinate system seems to be strange, it has to be ordered like this
    new_xyz = [y, x, z]

    # sample
    arrayR = map_coordinates(array, new_xyz, order=1)
注: 您也可以将此函数用于固有旋转,只需将“from_euler”的第一个参数调整为您的euler约定。在本例中,您获得了与我的第一篇文章中相同的结果(使用scipy.ndimage.rotate)。但是,我注意到当前代码比使用scipy.ndimage.rotate(40^3卷为0.03s)快3倍(40^3卷为0.01s)


希望这能帮助别人

我通过这个链接找到了一个令人满意的解决方案:

该方法使用np.meshgrid、scipy.ndimage.map_坐标。上面的链接使用一些第三方库来生成旋转矩阵,但是我使用scipy.spatial.transform.rotation。此函数允许定义内部和外部旋转:请参见scipy.spatial.transform.Rotation.from_euler的说明

以下是我的功能:

import numpy as np
from scipy.spatial.transform import Rotation as R
from scipy.ndimage import map_coordinates

# Rotates 3D image around image center
# INPUTS
#   array: 3D numpy array
#   orient: list of Euler angles (phi,psi,the)
# OUTPUT
#   arrayR: rotated 3D numpy array
# by E. Moebel, 2020
def rotate_array(array, orient):
    phi = orient[0]
    psi = orient[1]
    the = orient[2]

    # create meshgrid
    dim = array.shape
    ax = np.arange(dim[0])
    ay = np.arange(dim[1])
    az = np.arange(dim[2])
    coords = np.meshgrid(ax, ay, az)

    # stack the meshgrid to position vectors, center them around 0 by substracting dim/2
    xyz = np.vstack([coords[0].reshape(-1) - float(dim[0]) / 2,  # x coordinate, centered
                     coords[1].reshape(-1) - float(dim[1]) / 2,  # y coordinate, centered
                     coords[2].reshape(-1) - float(dim[2]) / 2])  # z coordinate, centered

    # create transformation matrix
    r = R.from_euler('zxz', [phi, psi, the], degrees=True)
    mat = r.as_matrix()

    # apply transformation
    transformed_xyz = np.dot(mat, xyz)

    # extract coordinates
    x = transformed_xyz[0, :] + float(dim[0]) / 2
    y = transformed_xyz[1, :] + float(dim[1]) / 2
    z = transformed_xyz[2, :] + float(dim[2]) / 2

    x = x.reshape((dim[1],dim[0],dim[2]))
    y = y.reshape((dim[1],dim[0],dim[2]))
    z = z.reshape((dim[1],dim[0],dim[2])) # reason for strange ordering: see next line

    # the coordinate system seems to be strange, it has to be ordered like this
    new_xyz = [y, x, z]

    # sample
    arrayR = map_coordinates(array, new_xyz, order=1)
注: 您也可以将此函数用于固有旋转,只需将“from_euler”的第一个参数调整为您的euler约定。在本例中,您获得了与我的第一篇文章中相同的结果(使用scipy.ndimage.rotate)。但是,我注意到当前代码比使用scipy.ndimage.rotate(40^3卷为0.03s)快3倍(40^3卷为0.01s)

希望这能帮助别人