由仿射变换矩阵生成pytorchθ

2024-05-18 23:26:31 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图用pytorch在3D体积上执行刚性+比例变换,但我似乎无法理解torch.nn.functional.affine_网格所需的θ是如何工作的

我有一个大小为(1,4,4)的变换矩阵,它是由平移*缩放*旋转矩阵相乘而生成的。例如,如果我在scipy.ndimage.affine_变换中使用此矩阵,则它不会出现任何问题。但是,使用torch.nn.functional.affine_网格时,相同的矩阵(裁剪为大小(1,3,4))完全失败

我已经设法理解了翻译是如何工作的(范围-1到1),并且我已经确认了翻译矩阵的工作原理,只需将值标准化到该范围。至于另外两个,我迷路了

我尝试单独使用一个基本的缩放矩阵(如下)作为最基本的比较,但Pytork中的结果与scipy中的结果不同

Scaling = 
[[0.75, 0, 0, 0],
[[0, 0.75, 0, 0],
[[0, 0, 0.75, 0],
[[0, 0, 0, 1]]

如何将(1,4,4)仿射矩阵转换为与torch.nn.functional.affine_网格相同的工作方式?或者,是否有基于变换参数(偏移、欧拉角、缩放)生成正确矩阵的方法


Tags: 网格体积矩阵nntorchpytorchscipy刚性
1条回答
网友
1楼 · 发布于 2024-05-18 23:26:31

对于将来遇到类似问题的任何人来说,scipy与pytorch仿射变换的问题在于,scipy在(0,0,0)周围应用变换,而pytorch在图像/体积的中间应用变换

例如,让我们以参数为例:

euler_angles = [ea0, ea1, ea2]
translation = [tr0, tr1, tr2]
scale = [sc0, sc1, sc2]

并创建以下转换矩阵:

# Rotation matrix
R_x(ea0, ea1, ea2) = np.array([[1, 0, 0, 0],
                              [0, math.cos(ea0), -math.sin(ea0), 0],
                              [0, math.sin(ea0), math.cos(ea0), 0],
                              [0, 0, 0, 1]])

R_y(ea0, ea1, ea2) = np.array([[math.cos(ea1), 0, math.sin(ea1), 0],
                               [0, 1, 0, 0],
                               [-math.sin(ea1), 0, math.cos(ea1)], 0],
                               [0, 0, 0, 1]])

R_z(ea0, ea1, ea2) = np.array([[math.cos(ea2), -math.sin(ea2), 0, 0],
                               [math.sin(ea2), math.cos(ea2), 0, 0],
                               [0, 0, 1, 0],
                               [0, 0, 0, 1]])

R = R_x.dot(R_y).dot(R_z)

# Translation matrix
T(tr0, tr1, tr2) = np.array([[1, 0, 0, -tr0],
                             [0, 1, 0, -tr1],
                             [0, 0, 1, -tr2],
                             [0, 0, 0, 1]])
# Scaling matrix
S(sc0, sc1, sc2) = np.array([[1/sc0, 0, 0, 0],
                             [0, 1/sc1, 0, 0],
                             [0, 0, 1/sc2, 0],
                             [0, 0, 0, 1]])

如果卷的大小为(100100100),则围绕卷中心的scipy变换需要先将卷中心移动到(0,0,0),然后在应用S、T和R后将其移回(50,50,50)。定义:

T_zero = np.array([[1, 0, 0, 50],
                   [0, 1, 0, 50],
                   [0, 0, 1, 50],
                   [0, 0, 0, 1]])

T_centre = np.array([[1, 0, 0, -50],
                     [0, 1, 0, -50],
                     [0, 0, 1, -50],
                     [0, 0, 0, 1]])

然后,围绕中心的scipy变换为:

transform_scipy_centre = T_zero.dot(T).dot(S).dot(R).T_centre

在Pytork中,参数有一些细微的差异

转换定义在-1和1之间。他们的顺序也不同。以相同(100100100)体积为例,pytorch中的平移参数如下所示:

# Note the order difference
translation_pytorch = =[tr0_p, tr1_p, tr2_p] = [tr0/50, tr2/50, tr1/50] 
T_p = T(tr0_p, tr1_p, tr2_p)

比例参数的顺序不同: 缩放比例=[sc0\u p,sc1\u p,sc2\u p]=[sc2,sc0,sc1]
S_p=S(sc0_p,sc1_p,sc2_p)

欧拉角是最大的差异。要获得等效变换,首先参数为负数,顺序不同:

# Note the order difference
euler_angles_pytorch = [ea0_p, ea1_p, ea2_p] = [-ea0, -ea2, -ea1]
R_x_p = R_x(ea0_p, ea1_p, ea2_p)
R_y_p = R_y(ea0_p, ea1_p, ea2_p)
R_z_p = R_z(ea0_p, ea1_p, ea2_p)

旋转矩阵的计算顺序也不同: #注意顺序的不同 R_p=R_x_p.点(R_z_p).点(R_y_p)

考虑到所有这些因素,scipy转换具有:

transform_scipy_centre = T_zero.dot(T).dot(S).dot(R).T_centre

与Pytork变换等效,具有:

transform_pytorch = T_p.dot(S_p).dot(R_p)

我希望这有帮助

相关问题 更多 >

    热门问题