Mayavi:绕y轴旋转

Mayavi: rotate around y axis

我正在使用 mayavi 的 triangular_mesh 方法绘制 3D 网格。数据描述了一个面朝下的 3D 人体轮廓 space(因此 cmap 可用于表示与相机的距离)。

这是用于生成绘图的代码(面和顶点来自外部对象,这里显示的太多了):

from mayavi import mlab

import math
import numpy as np
import sys
import os


fig = mlab.figure(fgcolor=(0, 0, 0), bgcolor=(1, 1, 1), size=(1920, 980))

a = np.array(this_mesh.vertices - refC.conj().transpose())  # this_mesh is an object created from external data files 

this_mesh.faces = this_mesh.faces.astype(int) -1  # mesh data is generated by matlab, which is 1-indexed

m = mlab.triangular_mesh(x, y, z, this_mesh.faces, opacity=0.75)

mlab.axes(extent=[-1100, 1100, -1100, 1100, -1100, 1100])

在不移动相机的情况下,剪影面朝下。为了正面查看模型,我正在改变相机的方位角和仰角以自上而下查看图表。这显示了预期的轮廓。

mlab.view(azimuth=0, elevation=180)
mlab.show()

我的下一个任务是创建一系列图像,其中相机围绕情节平移,从面向右侧的剪影开始,到面向左侧结束。

复杂的是,为了获得深度信息的颜色图,我已经移动了视图的方位角和仰角(如上面的代码所示)。 Mayavi 比 matplotlib 有更多移动相机的选项,但它似乎没有办法绕 Y 轴旋转,所以我猜我需要对方位角和仰角执行一些复杂的计算才能实现结果相同 - 但我不知道从哪里开始(我是 3D 工作的新手 space,我的大脑还没有那样想)。

谁能给我指出正确的方向?

这里需要一些数学知识。好的,这里是如何在代码方面做到这一点,它不是最好的代码,但我想让它不言自明。我使用 Rodrigues 公式在 3d 中进行旋转来实现这一点,az_new 和 el_new 是您的新视角。更改 theta 的值以在您的参考系中获得不同的视角,我在下面的代码中使用了 45 度:

import numpy as np
import math

def rotation_matrix(axis, theta):
    """
    Return the rotation matrix associated with counterclockwise rotation about
    the given axis by theta radians.
    """
    axis = np.asarray(axis)
    theta = np.asarray(theta)
    axis = axis/math.sqrt(np.dot(axis, axis))
    a = math.cos(theta/2.0)
    b, c, d = -axis*math.sin(theta/2.0)
    aa, bb, cc, dd = a*a, b*b, c*c, d*d
    bc, ad, ac, ab, bd, cd = b*c, a*d, a*c, a*b, b*d, c*d
    return np.array([[aa+bb-cc-dd, 2*(bc+ad), 2*(bd-ac)],
                     [2*(bc-ad), aa+cc-bb-dd, 2*(cd+ab)],
                     [2*(bd+ac), 2*(cd-ab), aa+dd-bb-cc]])


az = 90
el = -75

x = np.cos(np.deg2rad(el))*np.cos(np.deg2rad(az))
y = np.cos(np.deg2rad(el))*np.sin(np.deg2rad(az))
z = np.sin(np.deg2rad(el))

# So your viewing vector in x,y coordinates on unit sphere
v = [x,y,z]

# Since you want to rotate about the y axis from this viewing angle, we just increase the
# elevation angle by 90 degrees to obtain our axis of rotation

az2 = az
el2 = el+90

x = np.cos(np.deg2rad(el2))*np.cos(np.deg2rad(az2))
y = np.cos(np.deg2rad(el2))*np.sin(np.deg2rad(az2))
z = np.sin(np.deg2rad(el2))

axis = [x,y,z]

# Now to rotate about the y axis from this viewing angle we use the rodrigues formula
# We compute our new viewing vector, lets say we rotate by 45 degrees
theta = 45
newv = np.dot(rotation_matrix(axis,np.deg2rad(theta)), v)

#Get azimuth and elevation for new viewing vector
az_new = np.rad2deg(np.arctan(newv[1]/newv[0]))
el_new = np.rad2deg(np.arcsin(newv[2]))

原来有一些解决方法。

您可以在独立于摄像机的轴上旋转演员。 (这会使可视化与数据标签不一致,但由于我实际上隐藏了图形的轴,因此在这种情况下无关紧要。)

您只需:

m.actor.actor.rotate_y(desired_angle)

...您可以开始了。