旋转变换(一)旋转矩阵

2023-11-19

转自:https://blog.csdn.net/csxiaoshui/article/details/65446125

1. 简介

计算机图形学中的应用非常广泛的变换是一种称为仿射变换的特殊变换,在仿射变换中的基本变换包括平移、旋转、缩放、剪切这几种。本文以及接下来的几篇文章重点介绍一下关于旋转的变换,包括二维旋转变换、三维旋转变换以及它的一些表达方式(旋转矩阵、四元数、欧拉角等)。

2. 绕原点二维旋转

首先要明确旋转在二维中是绕着某一个点进行旋转,三维中是绕着某一个轴进行旋转。二维旋转中最简单的场景是绕着坐标原点进行的旋转,如下图所示:

2DRotation

如图所示点v 绕 原点旋转θθ 角,得到点v’,假设 v点的坐标是(x, y) ,那么可以推导得到 v’点的坐标(x’, y’)(设原点到v的距离是r,原点到v点的向量与x轴的夹角是ϕϕ )
x=rcosϕy=rsinϕx=rcosϕy=rsinϕ
x′=rcos(θ+ϕ)y′=rsin(θ+ϕ)x′=rcos(θ+ϕ)y′=rsin(θ+ϕ)
通过三角函数展开得到
x′=rcosθcosϕ−rsinθsinϕx′=rcosθcosϕ−rsinθsinϕ
y′=rsinθcosϕ+rcosθsinϕy′=rsinθcosϕ+rcosθsinϕ
带入x和y表达式得到
x′=xcosθ−ysinθx′=xcosθ−ysinθ
y′=xsinθ+ycosθy′=xsinθ+ycosθ
写成矩阵的形式是:

[x′y′]=[cosθsinθ−sinθcosθ]∗[xy][x′y′]=[cosθ−sinθsinθcosθ]∗[xy]


尽管图示中仅仅表示的是旋转一个锐角θθ的情形,但是我们推导中使用的是三角函数的基本定义来计算坐标的,因此当旋转的角度是任意角度(例如大于180度,导致v’点进入到第四象限)结论仍然是成立的。

 

3. 绕任意点的二维旋转

绕原点的旋转是二维旋转最基本的情况,当我们需要进行绕任意点旋转时,我们可以把这种情况转换到绕原点的旋转,思路如下:
1. 首先将旋转点移动到原点处
2. 执行如2所描述的绕原点的旋转
3. 再将旋转点移回到原来的位置

2DArbitraryRotate

也就是说在处理绕任意点旋转的情况下需要执行两次平移的操作。假设平移的矩阵是T(x,y),也就是说我们需要得到的坐标 v’=T(x,y)*R*T(-x,-y)(我们使用的是列坐标描述点的坐标,因此是左乘,首先执行T(-x,-y))

在计算机图形学中,为了统一将平移、旋转、缩放等用矩阵表示,需要引入齐次坐标。(假设使用2x2的矩阵,是没有办法描述平移操作的,只有引入3x3矩阵形式,才能统一描述二维中的平移、旋转、缩放操作。同理必须使用4x4的矩阵才能统一描述三维的变换)。

对于二维平移,如下图所示,P点经过x和y方向的平移到P’点,可以得到:

2DTranslate

x′=x+txy′=y+tyx′=x+txy′=y+ty
由于引入了齐次坐标,在描述二维坐标的时候,使用(x,y,w)的方式(一般w=1),于是可以写成下面矩阵的形式

 

⎡⎣⎢x′y′1⎤⎦⎥=⎡⎣⎢100010txty1⎤⎦⎥∗⎡⎣⎢xy1⎤⎦⎥[x′y′1]=[10tx01ty001]∗[xy1]


按矩阵乘法展开,正好得到上面的表达式。也就是说平移矩阵是

⎡⎣⎢100010txty1⎤⎦⎥[10tx01ty001]


如果平移值是(-tx,-ty)那么很明显平移矩阵式

⎡⎣⎢100010−tx−ty1⎤⎦⎥[10−tx01−ty001]


我们可以把2中描述的旋转矩阵也扩展到3x3的方式,变为:

⎡⎣⎢x′y′1⎤⎦⎥=⎡⎣⎢cosθsinθ0−sinθcosθ0001⎤⎦⎥∗⎡⎣⎢xy1⎤⎦⎥[x′y′1]=[cosθ−sinθ0sinθcosθ0001]∗[xy1]


从平移和旋转的矩阵可以看出,3x3矩阵的前2x2部分是和旋转相关的,第三列与平移相关。有了上面的基础之后,我们很容易得出二维中绕任意点旋转的旋转矩阵了,只需要把三个矩阵乘起来即可:

 

 

M=⎡⎣⎢100010txty1⎤⎦⎥∗⎡⎣⎢cosθsinθ0−sinθcosθ0001⎤⎦⎥∗⎡⎣⎢100010−tx−ty1⎤⎦⎥=⎡⎣⎢cosθsinθ0−sinθcosθ0(1−cosθ)tx+ty∗sinθ(1−cosθ)ty−tx∗sinθ1⎤⎦⎥M=[10tx01ty001]∗[cosθ−sinθ0sinθcosθ0001]∗[10−tx01−ty001]=[cosθ−sinθ(1−cosθ)tx+ty∗sinθsinθcosθ(1−cosθ)ty−tx∗sinθ001]

 

4. 三维基本旋转

我们可以把一个旋转转换为绕基本坐标轴的旋转,因此有必要讨论一下绕三个坐标值x、y、z的旋转。
本文在讨论过程中使用的是类似于OpenGL中定义的右手坐标系,同时旋转角度的正负也遵循右手坐标系的约定。如下图所示

RightHanderRule

4.1 绕X轴的旋转

在三维场景中,当一个点P(x,y,z)绕x轴旋转θθ角得到点P’(x’,y’,z’)。由于是绕x轴进行的旋转,因此x坐标保持不变,y和z组成的yoz(o是坐标原点)平面上进行的是一个二维的旋转,可以参考上图(y轴类似于二维旋转中的x轴,z轴类似于二维旋转中的y轴),于是有:
x′=xx′=x
y′=ycosθ−zsinθy′=ycosθ−zsinθ
z′=ysinθ+zcosθz′=ysinθ+zcosθ
写成(4x4)矩阵的形式

⎡⎣⎢⎢⎢x′y′z′1⎤⎦⎥⎥⎥=⎡⎣⎢⎢⎢10000cosθsinθ00−sinθcosθ00001⎤⎦⎥⎥⎥∗⎡⎣⎢⎢⎢xyz1⎤⎦⎥⎥⎥[x′y′z′1]=[10000cosθ−sinθ00sinθcosθ00001]∗[xyz1]

 

4.2 绕Y轴旋转

绕Y轴的旋转和绕X轴的旋转类似,Y坐标保持不变,除Y轴之外,ZOX组成的平面进行一次二维的旋转(Z轴类似于二维旋转的X轴,X轴类似于二维旋转中的Y轴,注意这里是ZOX,而不是XOZ,观察上图中右手系的图片可以很容易了解到这一点),同样有:
x′=zsinθ+xcosθx′=zsinθ+xcosθ
y′=yy′=y
z′=zcosθ−xsinθz′=zcosθ−xsinθ
写成(4x4)矩阵的形式

⎡⎣⎢⎢⎢x′y′z′1⎤⎦⎥⎥⎥=⎡⎣⎢⎢⎢cosθ0−sinθ00100sinθ0cosθ00001⎤⎦⎥⎥⎥∗⎡⎣⎢⎢⎢xyz1⎤⎦⎥⎥⎥[x′y′z′1]=[cosθ0sinθ00100−sinθ0cosθ00001]∗[xyz1]

 

4.3 绕Z轴旋转

与上面类似,绕Z轴旋转,Z坐标保持不变,xoy组成的平面内正好进行一次二维旋转(和上面讨论二维旋转的情况完全一样)

⎡⎣⎢⎢⎢x′y′z′1⎤⎦⎥⎥⎥=⎡⎣⎢⎢⎢cosθsinθ00−sinθcosθ0000100001⎤⎦⎥⎥⎥∗⎡⎣⎢⎢⎢xyz1⎤⎦⎥⎥⎥[x′y′z′1]=[cosθ−sinθ00sinθcosθ0000100001]∗[xyz1]

 

4.4 小结

上面描述了三维变换中绕单一轴旋转的矩阵表达形式,绕三个轴旋转的矩阵很类似,其中绕y轴旋转的矩阵与绕x和z轴旋转的矩阵略有点不同(主要是三个轴向顺序和书写矩阵的方式不一致导致的,绕三个不同坐标旋转轴以及其他二个坐标轴组成平面的顺序是: XYZ(绕x轴) YZX(绕y轴) ZXY(绕z轴),其中绕y轴旋转,其他两个轴是ZX,这和我们书写矩阵按

⎡⎣⎢⎢⎢xyz1⎤⎦⎥⎥⎥[xyz1]


的方式不一致,而导致看起来绕Y轴旋转的矩阵似乎是和其他两个矩阵不一致。如果我们颠倒写法,将公式写成

⎡⎣⎢⎢⎢z′y′x′1⎤⎦⎥⎥⎥=⎡⎣⎢⎢⎢cosθ0sinθ00100−sinθ0cosθ00001⎤⎦⎥⎥⎥∗⎡⎣⎢⎢⎢zyx1⎤⎦⎥⎥⎥[z′y′x′1]=[cosθ0−sinθ00100sinθ0cosθ00001]∗[zyx1]


的方式,那么这三个旋转矩阵看起来在形式上就统一了,都是

[cosθsinθ−sinθcosθ][cosθ−sinθsinθcosθ]


这种表现形式了(左上角都是−sinθ−sinθ)

 

5. 绕任意轴的三维旋转

绕任意轴的三维旋转可以使用类似于绕任意点的二维旋转一样,将旋转分解为一些列基本的旋转。绕任意轴旋转如下图所示:

RotateArbitrary

P点绕向量u旋转θθ角,得到点Q,已知P点的坐标和向量u,如何求Q点的坐标。
我们可以把向量u进行一些旋转,让它与z轴重合,之后旋转P到Q就作了一次绕Z轴的三维基本旋转,之后我们再执行反向的旋转,将向量u变回到它原来的方向,也就是说需要进行的操作如下:
1. 将旋转轴u绕x轴旋转至xoz平面
2. 将旋转轴u绕y轴旋转至于z轴重合
3. 绕z轴旋转θθ角
4. 执行步骤2的逆过程
5. 执行步骤1的逆过程
原始的旋转轴u如下图所示:

OriginVector_u
第1、2、3步骤如下图所示:
Step2
Step3
Step4

步骤1将向量u旋转至xoz平面的操作是一个绕x轴的旋转操作,步骤2将向量u旋转到与z轴重合,第1、2步骤的示意图如下:

RotateToZ
作点P在yoz平面的投影点q,q的坐标是(0, b, c),原点o与q点的连线oq和z轴的夹角就是u绕x轴旋转的角度。通过这次旋转使得u向量旋转到xoz平面(图中的or向量)【步骤1】
过r点作z轴的垂线,or与z轴的夹角为ββ, 这个角度就是绕Y轴旋转的角度,通过这次旋转使得u向量旋转到与z轴重合【步骤2】

步骤1中绕x轴旋转的是一次基本的绕x轴的三维旋转,按照之前的讨论,旋转矩阵是:

⎡⎣⎢⎢⎢10000cosθsinθ00−sinθcosθ00001⎤⎦⎥⎥⎥[10000cosθ−sinθ00sinθcosθ00001]


这里的θθ就是图中所示的αα角 (注意αα角度是绕x旋转的正的角度)
从图中我们还可以得到:

cosα=c(b2+c2)−−−−−−−√cosα=c(b2+c2)

 

sinα=b(b2+c2)−−−−−−−√sinα=b(b2+c2)


于是旋转矩阵(记作 Rx(α)Rx(α))为:

⎡⎣⎢⎢⎢⎢⎢⎢⎢10000c(b2+c2)√b(b2+c2)√00−b(b2+c2)√c(b2+c2)√00001⎤⎦⎥⎥⎥⎥⎥⎥⎥[10000c(b2+c2)−b(b2+c2)00b(b2+c2)c(b2+c2)00001]


在完成步骤1之后,向量u被变换到了r的位置,我们继续步骤2的操作,绕y轴旋转负的ββ角(注意:这里的ββ是负的),经过这次变换之后向量u与z轴完全重合,由于这一步也是执行的一次绕Y轴的基本旋转,旋转矩阵(记作 Ry(−β)Ry(−β))为:

⎡⎣⎢⎢⎢cosθ0−sinθ00100sinθ0cosθ00001⎤⎦⎥⎥⎥[cosθ0sinθ00100−sinθ0cosθ00001]


使用−β−β替换表达式中的θθ,此外根据图中描述,我们可以计算得到:

cosβ=(b2+c2)−−−−−−−√(a2+b2+c2)−−−−−−−−−−−√cosβ=(b2+c2)(a2+b2+c2)

 

sinβ=a(a2+b2+c2)−−−−−−−−−−−√sinβ=a(a2+b2+c2)


带入上面的表达式,于是旋转矩阵(记作 Ry(−β)Ry(−β))为:

⎡⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢(b2+c2)√(a2+b2+c2)√0a(a2+b2+c2)√00100−a(a2+b2+c2)√0(b2+c2)√(a2+b2+c2)√00001⎤⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥[(b2+c2)(a2+b2+c2)0−a(a2+b2+c2)00100a(a2+b2+c2)0(b2+c2)(a2+b2+c2)00001]

 

在完成前面两个步骤之后,u方向和z轴完全重合,因此执行旋转θθ角,执行的是一次绕z轴的基本三维旋转(记作 R(θ)R(θ),根据之前的讨论,我们可以得到:

⎡⎣⎢⎢⎢cosθsinθ00−sinθcosθ0000100001⎤⎦⎥⎥⎥[cosθ−sinθ00sinθcosθ0000100001]


最后两步骤是前面1和2的逆操作,也就是绕Y轴旋转ββ 和绕X轴旋转−α−α,这两个矩阵分别记作 Ry(β)Ry(β) 和 Rx(−α)Rx(−α),得到它们的方式很简单,只需要将上面步骤1和步骤2中的角度修改成相反数即可,也就是:

 

 

Ry(β)=⎡⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢(b2+c2)√(a2+b2+c2)√0−a(a2+b2+c2)√00100a(a2+b2+c2)√0(b2+c2)√(a2+b2+c2)√00001⎤⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥Ry(β)=[(b2+c2)(a2+b2+c2)0a(a2+b2+c2)00100−a(a2+b2+c2)0(b2+c2)(a2+b2+c2)00001]

 

Rx(−α)=⎡⎣⎢⎢⎢⎢⎢⎢⎢10000c(b2+c2)√−b(b2+c2)√00b(b2+c2)√c(b2+c2)√00001⎤⎦⎥⎥⎥⎥⎥⎥⎥Rx(−α)=[10000c(b2+c2)b(b2+c2)00−b(b2+c2)c(b2+c2)00001]

 

最终得到 绕任意轴u旋转的旋转矩阵是【因为使用的列向量,因此执行的是左乘(从右往左)】:

 

MR=Rx(−α)Ry(β)Rz(θ)Ry(−β)Rx(α)=MR=Rx(−α)Ry(β)Rz(θ)Ry(−β)Rx(α)=


roateMatrix
(注:式中的(u,v,w)对应上文中向量(a,b,c),公式我自己笔算过,为了减少编辑公式的时间(使用LaTex编辑太繁琐,因此找了一张公式的图片贴在此处)

 

如果向量是经过单位化的(单位向量),那么有a2+b2+c2=1a2+b2+c2=1,可以简化上述的公式,得到:

NormalizedRotate

--------------------- 本文来自 csxiaoshui 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/csxiaoshui/article/details/65446125?utm_source=copy

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

旋转变换(一)旋转矩阵 的相关文章

  • 《Web应用安全权威指南》学习笔记

    第1章 什么是Web应用的安全隐患 第2章 搭建试验环境 邮件发送服务器Postfix POP3服务器Dovecot SSH服务器OpenSSH Web应用调试工具Fiddler 第3章 Web安全基础 HTTP回话管理 同源策略 Cook
  • k8s安全04--kube-apiserver 安全配置

    k8s安全04 kube apiserver 安全配置 1 介紹 2 安全配置 2 1 配置 insecure port 2 2 RBAC 2 3 Service Accounts 2 4 Researching Pod Security
  • Nginx 无法转发本地端口

    问题描述 本文主要分析解决 centos 下 nginx 配置端口转发后不生效 通过 nginx 配置 server 转发后 无法达到预期的转发目的 并出现502错误的问题 假设虚拟机 ip 为 192 168 0 8 并且在虚拟机内部署一
  • ISO七层模型

    物理层 O S I 模型的最低层或第一层 该层包括物理连网媒介 如电缆连线连接器 物理层的协议产生并检测电压以便发送和接收携带数据的信号 在你的桌面P C 上插入网络接口卡 你就建立了计算机连网的基础 换言之 你提供了一个物理层 尽管物理层
  • uni-app项目在微信开发者工具打开时报错[ app.json 文件内容错误] app.json: 在项目根目录未找到 app.json

    uni app项目在微信开发者工具打开时控制台报错 app json 文件内容错误 app json 在项目根目录未找到 app json env Windows mp 1 06 2303220 lib 2 32 0 解决方案 以下是一个u

随机推荐

  • 前端基础之ES6

    1 前后端对比 2 ES6 ECMAScript6 0 以下简称ES6 ECMAScript是一种由Ecma国际通过ECMA 262标准化的脚本 是JavaScript语言的下一代标准 2015年6月正式发布 从ES6开始的版本号采用年号
  • S-DES加密

    S DES加密 Simplified Data Encryption Standard S DES 是一个供教学的非安全的加密算法 它与DES的特性和结构类似 但参数小 明文分组为8位 主密钥分组为10位 采用两轮迭代 S DES加密过程包
  • 第十一讲、FPGA开发中xilinx vivado 平台时序分析系列课程-边沿对齐input delay ddr双沿采样时序约束与收敛

    我们在使用一些以太网PHY和FPGA接口是RGMII接口是DDR双沿结构 还有ADC芯片也也是DDR双沿采样接口 以及CMOS视频传感器也有很多DDR双沿源同步接口 我们这里以IMX222视频传感器的的DDR为例约束input ddr 接口
  • FPGA提示产生latch的报错

    在fpga的设计中有时会遇到 latch 的报错 1 latch是什么 Latch 就是锁存器 是一种在异步电路系统中 对输入信号电平敏感的单元 用来存储信息 锁存器在数据锁存使能时 数据被锁存 输入信号不起作用 这违背了组合逻辑中输出随输
  • selenium元素定位方法 id,name,class

    1 导入selenium from selenium import webdriver from time import sleep 2 打开浏览器 最大化 driver webdriver Chrome driver maximize w
  • Java 学习路线大全,再也不用迷路啦(持续更新)

    路线特点 最新 完整一条龙 从入门到入土 表示推荐学习 给出目标 学习建议 关键知识点 最优资源以及各类资源推荐 视频 书籍 文档 项目 工具等 划分阶段 更有计划 且在最后给出持续学习的方向 探索 Java 程序员发展的无限可能 前言 首
  • SQLSERVER排查CPU占用高的情况

    一般排查都是用下面的脚本 一般会用到三个视图 sys sysprocesses dm exec sessions dm exec requests sys sysprocesses 系统表是一个很重要的系统视图 主要用来定位与解决Sql S
  • 存储类型auto,static,extern,register的区别 <转>

    变量和函数的属性包括数据类型和数据的存储类别 存储类别指数据在内存中存储方式 静态和动态 包含auto static register extern四种 内存中 具体点来说内存分为三块 静态区 堆区 栈区 外部变量和全局变量存放在静态区 局
  • 半监督学习——数据精馏(论文阅读)

    论文地址 https arxiv org pdf 1712 04440 pdf 1 论文与摘要 Data Distillation Towards Omni Supervised Learning 摘要 作者提出一种特殊的半监督学习方法 取
  • android 最新动态,浅谈Android动态页面(一)

    这是一个很微妙的东西 可能平时经常用到 但是没注意 我想对这个内容进行一个总结并提出一些看法 谈的是动态页面 不是动态布局 一 什么是动态页面 什么是动态页面 我认为是一种在开发时的设计思想 最终展示的页面会随着数据的改变而改变 或者说会根
  • OpenCV中如何读取URL图像文件

    点击上方 小白学视觉 选择加 星标 或 置顶 重磅干货 第一时间送达 由来 最近知识星球收到的提问 觉得是一个很有趣的问题 就通过搜集整理归纳了一番 主要思想是通过URL解析来生成数据 转为图像 Mat对象 但是在Python语言与C 语言
  • Java基础学习总结(1)——equals方法

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 一 equals方法介绍 1 1 通过下面的例子掌握equals的用法 1 package cn galc test 2 3 public class TestEquals
  • 简单spring cloud服务升级实现

    1 升级原则 隔离性 v1升级到v2时 相互独立 互不不干扰 稳定性 服务不停止 完成升级 接口保持畅通 2 具体实现 2 1 eureka项目 搭建eureka 网上很多 就省略了 2 2 feign接口项目 2 2 1 依赖
  • React Hooks

    React Hooks 为什么使用 React Hook useState hook useReducer hook useEffect hook useRef hook useLayoutEffect hook useImperative
  • GPIO口的八种工作状态

    一直对GPIO的工作状态不是很熟悉 导致在设置IO状态时 经常会设置成推挽上拉 或者推挽下拉 开漏上拉等问题 虽然看起来没有影响MCU工作 但感觉这是一种无知的表现 现在总结下GPIO口的八种工作状态 其中四种输入状态 四种输出状态 一 输
  • (STM32笔记2)基于hc05的蓝牙实验

    实验任务 开机检测 HC05 蓝牙模块是否存在 如果检测不成功 则报错 检测成功之后 显示模块的主从状态 并显示模块是否处于连接状态 DS0 闪烁 提示程序运行正常 按 KEY0 按键 可以开启 关闭自动发送数据 通过蓝牙模块发送 按 KE
  • 简单工厂模式

    简单工厂模式 一 概念 从设计模式的类型上来说 简单工厂模式是属于创建型模式 又叫做静态工厂方法 StaticFactory Method 模式 但不属于23种GOF设计模式之一 简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例 简
  • ASIC中带有MUX的时钟路径时序约束

    链接 https pan baidu com s 1BrAsabLYLGbvdXJB2LQwiA 提取码 mgrn
  • 回溯法详解

    一 回溯法 深度优先搜素 1 简单概述 回溯法思路的简单描述是 把问题的解空间转化成了图或者树的结构表示 然后使用深度优先搜索策略进行遍历 遍历的过程中记录和寻找所有可行解或者最优解 基本思想类同于 图的深度优先搜索 二叉树的后序遍历 分支
  • 旋转变换(一)旋转矩阵

    转自 https blog csdn net csxiaoshui article details 65446125 1 简介 计算机图形学中的应用非常广泛的变换是一种称为仿射变换的特殊变换 在仿射变换中的基本变换包括平移 旋转 缩放 剪切