坐标变换及视图变换和透视变换(相机透视模型)

news2025/4/9 21:10:03

文章目录

      • 2D transformation
        • Scale
        • Reflection
        • Shear(切变)
        • Rotation around origin
        • Translation
        • Reverse
        • 变换顺序
        • 复杂变换的分解
      • 齐次坐标(Homogenous Coordinates)
      • 3D transformation
        • Scale&Translation
        • Rotation
      • Viewing / Camera transformation
      • Projection transformation
      • 视口变换
      • 相机内参和相机外参
      • 参考链接

2D transformation

Scale
  • Uniform

image-20240610131838782

  • Non-Uniform

image-20240610131903605

Reflection

image-20240610132151747

Shear(切变)

image-20240610132849601

Rotation around origin

假设旋转矩阵的4个未知数,取特殊点列方程可推导

image-20240610133654334

如果旋转 − θ -\theta θ角度,那么经过推导很容易得出旋转矩阵为原来旋转 θ \theta θ角度的矩阵的转置

image-20240612162331025

又考虑到实际上如果一个图形旋转 θ \theta θ角度再旋转 − θ -\theta θ角度会变回原来的形状,也就是 R − θ R θ X = E X R_{-\theta}R_\theta X=EX RθRθX=EX,即 R − θ R θ = E R_{-\theta}R_\theta=E RθRθ=E​两个矩阵是互逆的。

image-20240612162716886

补充:如果一个矩阵的逆等于它的转置,那么这个矩阵是正交矩阵

以上变换都属于线性变换,都可以写成矩阵相乘的形式:

image-20240610133923619

Translation

需要注意平移(Translation)变换不属于Linear Transformation:

image-20240610134631675

但以上变换可以统称为仿射变换(Affine Transformations)

image-20240610135400637

Reverse

做逆变换相当于把变换后的图形又变回去,假如对 X X X做了变换 M M M,变为 X ′ = M X X'=MX X=MX,再对 X ′ X' X做逆变换 M − 1 M^{-1} M1 M − 1 M X = X M^{-1}MX=X M1MX=X,即变回 X X X

image-20240610141644378

变换顺序

由于矩阵乘法是不可交换的,所以变换的顺序是很重要的,不同的变换顺序得到的结果也不一样,顺序是先线性变换后平移

image-20240610142339298

复杂变换的分解

image-20240610143021276

齐次坐标(Homogenous Coordinates)

将一个 n n n维空间中的点或向量,表示为 n + 1 n+1 n+1维空间中的向量,能够达到合并矩阵运算中乘法和加法操作的目的,简化计算

image-20240610140106905

这样可以定义至少3种有效操作:

image-20240610140352028

Point+Point由于没有什么实质性意义,所以给出一个定义, ( x y w ) \begin{pmatrix}x \\ y \\ w\end{pmatrix} xyw 这个点实际上定义为 ( x / w y / w 1 ) \begin{pmatrix}x/w \\ y/w \\ 1\end{pmatrix} x/wy/w1 这个点,那么这时,两个点相加就被赋予了两个点中点这一意义

那么通过使用齐次坐标,可以将仿射变换改写为:

image-20240610140944932

缩放、旋转、平移可以表示成:

image-20240610141034088

3D transformation

和2D变换中的相似,齐次坐标在3维空间中变成了4维,仿射变换矩阵如下:

image-20240612163848238

注意是先应用线性变换,再应用平移变换!

Scale&Translation

image-20240612164016369

Rotation

三维空间中的旋转和2维相似,绕某个轴旋转就固定哪个轴的坐标不变,其他两个轴应用2维旋转矩阵即可,但我们发现绕y轴旋转的矩阵中 sin ⁡ α \sin α sinα的符号有点不同,这是因为图中y的方向是 z × x z×x z×x得到的,如果y轴是向下的,即由 x × z x×z x×z得到,那么 sin ⁡ α \sin α sinα会刚好相反

image-20240612164412560

留下几个知识点:欧拉角四元数罗德里格兹旋转公式

旋转矩阵不适合做插值,而四元数是可以的

image-20240612172907881

Viewing / Camera transformation

考虑我们现实场景重拍摄一张图片的步骤:

  • 找一个好地方并摆出姿势(model transformation)
  • 找一个好的拍摄角度并放置相机(view transformation)
  • 在相机上投影出相片(projection transformation)

这三部就是图形学中的MVP变换

我们首先考虑视角变换,也即相机变换。通常,相机可以通过三个方向向量来确定一个唯一的视图/相机位置(可以注意到 g ^ \hat g g^ t ^ \hat t t^总是垂直的):

  • Position e ⃗ \vec e e (决定相机的物理位置)
  • Gaze direction g ^ \hat g g^ (决定俯视仰视平视方向)
  • Up direction t ^ \hat t t^ (相机的角度,决定拍出的图像是什么角度,相机旋转,则拍出的照片也会旋转)

由于如果我们保持相机和物体的相对位置不变,同时移动二者,可能会得到相同的拍摄图像,因此不妨将相机固定到一个位置,即:

  • 原点
  • up at Y Y Y
  • gaze at − Z -Z Z

对于这样的位置,可以采取如下仿射变换

  • e e e平移到原点
  • g g g旋转到 − Z -Z Z
  • t t t旋转到 Y Y Y
  • ( g × t ) (g×t) (g×t)旋转到 X X X

这个变换实际上也就是世界坐标系转换到相机坐标系的过程。

但实际上,上面这些变换是不好表示的,由于前面提到旋转矩阵是正交的,所以我们可以考虑上述旋转变换的逆变换

image-20240612193435943

这样我们对所有的物体都事先运用这种变换就相当于我们的相机在一个固定位置去拍摄,并且相机位置是原点。这种变换也被称为ModelView Transformation。这实际上是世界坐标系相机坐标系的一个变换。

Projection transformation

投影变换就是从3D物体投影到2D图像的变换,可以分为:

  • 正交投影(Orthographic Projection)
  • 透视投影(Perspective Projection)

二者本质的区别是是否具有近大远小的性质,透视投影具有近大远小的性质而正交投影没有。透视投影中,原本平行的线投影后可能不再平行。如下图所示,正交投影相当于把相机拉到无限远的位置。下图中,Near clip plane是近平面,也相当于相机的成像平面。

image-20250223190053089

正交投影

当按照前面的方式进行视图变换后,正交投影其实就相当于丢弃掉Z轴坐标,然后将物体的中心平移到相机位置,并且将物体缩放到一个小的矩型中(归一化)。如下图,但这里还有一个问题是物体的正反我们无法分辨。

image-20250223191731040

在实际操作中,我们通常是将一个长方体通过平移和缩放映射一个中心位于原点,边长为1的一个立方体中:

image-20250223192051848

变换矩阵就是(先平移后缩放):

image-20250223192537273

在这个过程中,实际上物体是被拉伸了,后面会提到在做完MVP变换后还要进行视口变换

透视投影

首先需要明确齐次坐标中的一个知识点:就是 ( x , y , z , 1 ) (x,y,z,1) (x,y,z,1) ( k x , k y , k z , k ) (kx,ky,kz,k) (kx,ky,kz,k)表示的是同一个点。

透视投影实际上可以拆分为两步:

  • 将远平面到近平面内的frustum(截锥体)挤压变换成一个长方体。变换需要满足:近平面的所有点坐标不变。远平面只有xy变换而z不变。该变换表示为 M p e r s o − > o r t h o M_{perso->ortho} Mperso>ortho。注意近平面和远平面的中心连线是和z轴平行的。相机位置在中心连线上。
  • 对长方体进行正交投影。

image-20250223195710817

实际上,远平面(右)要挤压成与近平面(左)一样的大小,实际上是一个相似变换。

image-20250223200429050

利用相似变换的性质,可以求出 ( x , y , z ) (x,y,z) (x,y,z) ( x ′ , y ′ , z ′ ) (x',y',z') (x,y,z)的变换。
y ′ = n z y x ′ = n z x y^{\prime}=\frac{n}{z} y \quad x^{\prime}=\frac{n}{z} x y=znyx=znx
对于截锥体内的所有平面,xy变换都满足上述关系,但z的关系目前还不知道,只知道远平面和近平面的z不变。表示成齐次坐标为:

image-20250223200933762

M p e r s o − > o r t h o M_{perso->ortho} Mperso>ortho的目标就是:

image-20250223201044878

至此我们可以推导出 M p e r s o − > o r t h o M_{perso->ortho} Mperso>ortho矩阵的一部分:

image-20250223201130878

至于第三行,我们利用近平面的任意一点和远平面的任意一点z都不会改变可以推导出第三行,最终的 M p e r s o − > o r t h o M_{perso->ortho} Mperso>ortho矩阵就是:
M p e r s o − > o r t h o = ( n 0 0 0 0 n 0 0 0 0 n + f − n f 0 0 1 0 ) M_{perso->ortho}=\begin{pmatrix} n & 0 & 0 & 0\\ 0 & n & 0 & 0 \\ 0 & 0 & n+f & -nf\\ 0 & 0 & 1 & 0 \end{pmatrix} Mperso>ortho= n0000n0000n+f100nf0
n n n是近平面的z值, f f f是远平面的z值。

然后就是用正交变换矩阵再去做一次变换即得到最终的投影变换矩阵。
M persp  = M ortho  M persp  →  ortho  M_{\text {persp }}=M_{\text {ortho }} M_{\text {persp } \rightarrow \text { ortho }} Mpersp =Mortho Mpersp  ortho 
这也是相机坐标系图像坐标系的过程。

透视投影中还涉及到两个概念,视锥的长宽比(aspect ratio)垂直可视角度(vertical field-of-view,fovY)。实际含义可以从下图看出:

image-20250224165545646

我们假设前面经过矩型块是对称的,即 l = − r ( x 方向 ) , b = − t ( y 方向 ) l=-r(x 方向),b=-t(y方向) l=r(x方向),b=t(y方向)。那么可以从 t , r t,r t,r推出两个概念的表达式:
tan ⁡ f o v Y 2 = t ∣ n ∣  aspect  = r t \begin{aligned} \tan \frac{f o v Y}{2} & =\frac{t}{|n|} \\ \text { aspect } & =\frac{r}{t} \end{aligned} tan2fovY aspect =nt=tr
image-20250224165606254

视口变换

在MVP变换过后,我们的目标就是将前述的小立方块投影到一个图片上,这实际上也是图像坐标系到像素坐标系的变换。

首先我们假设像素坐标系是如下形式:坐标原点在左下角,每个像素是有单位宽度和高度的小颜色块,像素内部每一点颜色都一样,像素坐标系放的是像素的索引。如下图。

image-20250224170145528

设定y轴方向的长度为高度(height),x轴方向的长度是宽度(width),整个屏幕的范围就是上图灰色区域。

视口变换的目标是:

  • 保持相机坐标系的z不变
  • xy平面要从原来小立方体 [ − 1 , 1 ] 2 [-1,1]^2 [1,1]2的范围变换到 [ 0 , w i d t h ] × [ 0 , h e i g h t ] [0,width]\times[0,height] [0,width]×[0,height]的范围

变换矩阵很容易写出,就是缩放+平移操作。视口变换矩阵 M v i e w p o r t M_{viewport} Mviewport
M viewport  = (  width  2 0 0  width  2 0  height  2 0  height  2 0 0 1 0 0 0 0 1 ) M_{\text {viewport }}=\left(\begin{array}{cccc} \frac{\text { width }}{2} & 0 & 0 & \frac{\text { width }}{2} \\ 0 & \frac{\text { height }}{2} & 0 & \frac{\text { height }}{2} \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{array}\right) Mviewport = 2 width 00002 height 0000102 width 2 height 01
经过视口变换后,下一步就是光栅化(Rasterization)的过程。

相机内参和相机外参

外参就是上面从世界坐标系到相机坐标系的变换矩阵,可以简单理解为相机的位置、角度。

内参是上面另外两个变换矩阵的叠加,简单理解就是相机的内部特性,如焦距,畸变系数等。

参考链接

[1] https://www.bilibili.com/video/BV1X7411F744?spm_id_from=333.788.videopod.episodes&vd_source=bac8ddf04ec0b6386d58110f67353bc7&p=4

[2] https://www.bilibili.com/video/BV1r8411f72j/?spm_id_from=333.337.search-card.all.click&vd_source=bac8ddf04ec0b6386d58110f67353bc7

[3] https://zhuanlan.zhihu.com/p/692565077

还有一些不太理解的地方以及一些概念以后再更新。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2307644.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue 表单优化:下拉框值改变前的确认提示与还原逻辑实现

在开发表单类功能时,我们经常需要对用户的重要操作进行确认提示,以避免误操作导致的数据丢失或错误。本文将通过一个实际案例,介绍如何在 Vue 中实现下拉框值改变前的确认提示,并在用户取消操作时还原原始值。 场景描述 在项目中…

使用mermaid查看cursor程序生成的流程图

一、得到cursor生成的流程图文本 cursor写的程序正常运行后,在对话框输入框中输入诸如“请生成扫雷的代码流程图”,然后cursor就把流程图给生成了,但是看到的还是文本的样子,保留这部分内容待用 二、注册一个Mermaid绘图账号 …

(八)趣学设计模式 之 装饰器模式!

目录 一、 啥是装饰器模式?二、 为什么要用装饰器模式?三、 装饰器模式的实现方式四、 装饰器模式的优缺点五、 装饰器模式的应用场景六、 装饰器模式 vs 代理模式七、 总结 🌟我的其他文章也讲解的比较有趣😁,如果喜欢…

JVM线程分析详解

java线程状态: 初始(NEW):新创建了一个线程对象,但还没有调用start()方法。运行(RUNNABLE):Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”。 线程对象创建…

毕业项目推荐:基于yolov8/yolo11的野生菌菇检测识别系统(python+卷积神经网络)

文章目录 概要一、整体资源介绍技术要点功能展示:功能1 支持单张图片识别功能2 支持遍历文件夹识别功能3 支持识别视频文件功能4 支持摄像头识别功能5 支持结果文件导出(xls格式)功能6 支持切换检测到的目标查看 二、数据集三、算法介绍1. YO…

DeepSeek 助力 Vue3 开发:打造丝滑的页眉(Header)

前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏关注哦 💕 目录 Deep…

PHP应用程序设计:一个实际的例子(3)

使应用程序适用于网络 如果你正好计划用P H P开发你自己的服务程序(或者其他一些相似的东西),请重新思考一下。你可能已经对这些思想有些迷惑了:实现一个聊天服务程序意味着实现一个网络服务程序。这是我们实际上介绍给大家的东西…

RabbitMQ 的介绍与使用

一. 简介 1> 什么是MQ 消息队列(Message Queue,简称MQ),从字面意思上看,本质是个队列,FIFO先入先出,只不过队列中存放的内容是message而已。 其主要用途:不同进程Process/线程T…

OpenCV给图像添加噪声

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 如果你已经有了一张干净的图像,并希望通过编程方式向其添加噪声,可以使用 OpenCV 来实现这一点。以下是一个简单的例子&a…

Elasticsearch:使用阿里云 AI 服务进行嵌入和重新排名

作者:来自 Elastic Toms Mura 将阿里云 AI 服务功能与 Elastic 结合使用。 更多阅读,请参阅 “Elasticsearch:使用阿里 infererence API 及 semantic text 进行向量搜索”。 在本文中,我们将介绍如何将阿里云 AI 功能与 Elastics…

管理后台环境配置

后端配置及启动 a. 软件安装 1. Java sdk 1.8 2. maven 3.6 3. intellij IDEA 2024 4. Visual C Redistributable 5. mongodb 7.0 6. mysql 8.0 双击安装:mysql-installer-community-8.0.41.0.msi 版本选择:Full,包括服务器和客户端 …

数字IC低功耗后端设计实现之power gating和isolation技术

考虑低功耗设计需求,下图中间那个功能模块是需要做power domain的,即这个模块需要插MTCMOS。需要开启时,外面的VDD会和这个模块的LOCAL VDD形成通路,否则就是断开即power off状态。 这些低功耗设计实现经验,你真的懂了…

【网络编程】几个常用命令:ping / netstat / xargs / pidof / watch

ping:检测网络联通 1. ping 的基本功能2. ping 的工作原理3. ping 的常见用法4. ping 的输出解释5. ping 的应用场景6. 注意事项 netstat:查看网络状态 1. netstat 的基本功能2. 常见用法3. 示例4. 输出字段解释5. netstat 的替代工具6. 注意事项 xargs&…

sqlilab 46 关(布尔、时间盲注)

sqlilabs 46关(布尔、时间盲注) 46关有变化了,需要我们输入sort,那我们就从sort1开始 递增测试: 发现测试到sort4就出现报错: 我们查看源码: 从图中可看出:用户输入的sort值被用于查…

《Effective Objective-C》阅读笔记(下)

目录 内存管理 理解引用计数 引用计数工作原理 自动释放池 保留环 以ARC简化引用计数 使用ARC时必须遵循的方法命名规则 变量的内存管理语义 ARC如何清理实例变量 在dealloc方法中只释放引用并解除监听 编写“异常安全代码”时留意内存管理问题 以弱引用避免保留环 …

穷举vs暴搜vs深搜vs回溯vs剪枝(典型算法思想)—— OJ例题算法解析思路

回溯算法的模版 void backtrack(vector<int>& path, vector<int>& choice, ...) {// 满⾜结束条件if (/* 满⾜结束条件 */) {// 将路径添加到结果集中res.push_back(path);return;}// 遍历所有选择for (int i 0; i < choices.size(); i) {// 做出选择…

【Java项目】基于Spring Boot的校园博客系统

【Java项目】基于Spring Boot的校园博客系统 技术简介&#xff1a;采用Java技术、Spring Boot框架、MySQL数据库等实现。 系统简介&#xff1a;校园博客系统是一个典型的管理系统&#xff0c;主要功能包括管理员&#xff1a;首页、个人中心、博主管理、文章分类管理、文章信息…

计算机毕业设计SpringBoot+Vue.js图书进销存管理系统(源码+文档+PPT+讲解)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

算法-数据结构(图)-迪杰斯特拉最短逻辑算法( Dijkstra)

迪杰斯特拉算法&#xff08;Dijkstras Algorithm&#xff09; 是一种用于计算单源最短路径的经典算法&#xff0c;由荷兰计算机科学家 艾兹赫尔迪杰斯特拉&#xff08;Edsger W. Dijkstra&#xff09; 于1956年提出。它的主要目标是找到从图中的某个源节点到所有其他节点的最短…

C语言【进阶篇】之指针——涵盖基础、数组与高级概念

目录 &#x1f680;前言&#x1f914;指针是什么&#x1f31f;指针基础&#x1f4af;内存与地址&#x1f4af;指针变量&#x1f4af; 指针类型&#x1f4af;const 修饰指针&#x1f4af;指针运算&#x1f4af;野指针和 assert 断言 &#x1f4bb;数组与指针&#x1f4af;数组名…