旋转矩阵转欧拉角, 及在3D人脸中的使用

被欧拉角折磨了几年了… 这次还是记一下吧

文章目录

  • 旋转的基础知识总结
  • 旋转矩阵转欧拉角
  • 3D 人脸最好使用的欧拉角为 ...
  • 通过相机位置算出旋转矩阵的验证

旋转的基础知识总结

一般表示旋转有以下几种方式

  1. 旋转矩阵 R(似乎对应唯一的旋转, 可以看这里的说明). 唯一很重要, 一般表示旋转都可以转到R, 然后变到其他(本博客主要说明变到欧拉角ZXY)
  2. 欧拉角 X, Y, Z (pitch, yaw, roll). 但是 它们的组合可以达到12种,因为还可以使用类似 X1 Z2 X3 这种(就是某个方向用两次, 因为每次都是相对旋转) 具体可看 wiki. 因此使用欧拉角还必须明确使用的角度和使用的顺序.
  3. 轴角. 不过多介绍 属于李代数so3. 这个也是经常用到的, 需要借用 罗德里格斯 转到 R
  4. 四元数. 目前自己是没用过
  5. 相机位置, head 朝向(一般假设[0, 1, 0]). 这个是有特殊应用场景的, 比如opengl 中的 lookat 函数. 简单介绍下如何算出Rc2w (相机到世界坐标系的旋转), x=R[:, 2]可以通过相机位置和坐标原点的向量获得, 然后y=R[:, 1] 在z和 head 所在平面上, 可利用这个信息算出 x = R[:, 0], 然年算出y. 代码如下
# 用 torch 实现的. 在ogl 中 z = cam_at 
def ogl_cam_R(z):
    y_t = z.new(3).zero_()
    #y_t.fill_(0)
    y_t[1]=1
    x = y_t.cross(z)
    y = z.cross(x)
    xyz = [ (e/e.norm()).view(-1, 1) for e in [x, y, z] ]
    R = torch.cat(xyz, 1)
    return R

旋转矩阵转欧拉角

前面说过 R 的形式 是由 你的欧拉角确定的, 要从 R 恢复欧拉角, 首先要知道你要确定你的欧拉角是怎样的定义.
接下来先做一个非常有必要的规定

  1. 旋转矩阵乘在顶点的左边即 t v = R ∗ v tv=R*v tv=Rv
  2. 给定欧拉角的顺序1->2>3 那么其组成的R 按照 R = R 3 R 2 R 1 R=R_3R_2R_1 R=R3R2R1

(其实我自己之所以感觉绕就是因为各种博客和paper 没有明确给出其内在的顺序, 或者是自己没看到)

可以有不同的定义方式如果你没有搞清楚内在的定义顺序你将很糊涂 比如

示例1: http://pages.mtu.edu/~dcclark/dice/Background/eulerangles2.pdf
旋转矩阵转欧拉角, 及在3D人脸中的使用_第1张图片
示例2: https://www1.udel.edu/biology/rosewc/kaap686/notes/matrices_rotations_2.pdf旋转矩阵转欧拉角, 及在3D人脸中的使用_第2张图片

示例3: https://en.wikipedia.org/wiki/Euler_angles
3
示例3定义的顺序我的定义相同
至于怎么从R转欧拉角, 当你定义好顺序之后, 看这些矩阵的表达式你将很容易恢复出那些角度来. 比如示例3中我写为 R z x y R_{zxy} Rzxy, 其要恢复x, y 如下

def get_yaw_pitch_from_Rzxy(self, R):
    view = R[:, 2]
    yaw = math.atan2(view[0], view[2])
    pitch = math.asin(-view[1])
    return yaw, pitch

3D 人脸最好使用的欧拉角为 …

先看完上一个小节, 然后本标题的 … 为 R z x y R_{zxy} Rzxy
为什么?

  1. 对于人脸一般最主要的就是 yaw, pitch,(yaw更重要) 做3D 和 2D 特征点的同学应该都知道, 因为3D特征点需要根据角度动态选择. 选用 R z x y R_{zxy} Rzxy 可以很快算出 这两个角.
  2. 核能知识点
    最先旋转的角在最后呈现的模型中越看不出来, 越是后面旋转的角在最后的模型中越能看出来.
    R z x y R_{zxy} Rzxy 的本质是按照roll -> pitch -> yaw 旋转, 也就是最后的 yaw 可以通过打开模型一眼看出来, 就是基本能知道yaw的正负和大小. 方便调试等.

通过相机位置算出旋转矩阵的验证

这个主要是为了记录一下自己总结的plt的使用, 可以忽略

import matplotlib.pyplot as plt
# 2018-3-4
# o p 可以快捷操作图片
# 终于找到退出程序的方法了
def on_release(event):
    if event.button == 3:  plt.close()
def on_press(event):
    if event.dblclick == True:  exit(0)

def create_fig():
    fig = plt.figure()
    fig.canvas.mpl_connect("button_press_event", on_press)
    fig.canvas.mpl_connect("button_release_event", on_release)
    return fig

# 给定Rw2c

cam_direct = Rw2c[:, 2]
R = ogl_cam_R(cam_direct)
fig = create_fig()
ax = plt.subplot(111, projection='3d')

bg = torch.zeros(1, 3)
# 前面的长一些, 方便能看到
for i in range(3):
    pts = torch.cat((bg, Rw2c[:, i].view(1, -1)*1.1), 0).numpy()
    ax.plot(pts[:, 0], pts[:, 1], pts[:, 2], c='g')

for i in range(3):
    pts = torch.cat((bg, R[:, i].view(1, -1)), 0).numpy()
    ax.plot(pts[:, 0], pts[:, 1], pts[:, 2], c='r')

ax.set_zlabel('Z')  # 坐标轴
ax.set_ylabel('Y')
ax.set_xlabel('X')
plt.show()

# 可以防止阻塞
#plt.draw()
#plt.pause(.001)

有帮助请点赞…

你可能感兴趣的:(旋转矩阵,欧拉角,视觉图形学)