Opengl投影变换理解

article/2025/10/1 15:41:04

坐标到达观察空间之后,我们需要将其投影到裁剪坐标。裁剪坐标会被处理至-1.0到1.0的范围内,并判断哪些顶点将会出现在屏幕上。
而[-1.0,1.0]构成的正方体又叫规则观察体(Canonical View Volume, CVV)

一、流程

计算机显示器是一个 2D 表面。OpenGL 渲染的 3D 场景必须作为 2D 图像投影到计算机屏幕上。
1、定义投影矩阵,指定了一个范围的坐标,以此来模拟相机的可视范围
2、投影矩阵接着会将在这个指定的范围内的坐标变换为标准化设备坐标的范围(-1.0, 1.0)。所有在范围外的坐标不会被映射到在-1.0到1.0的范围之间,所以会被裁剪掉。以此模拟相机的可视范围。
2、裁剪完后,进行透视除法,将4D裁剪空间坐标变换为3D标准化设备坐标。

二、正交投影

1、创建一个正射投影矩阵需要指定可见平截头体的宽、高和长度。在使用正射投影矩阵变换至裁剪空间之后处于这个平截头体内的所有坐标将不会被裁剪掉。
如下所示,左边为平截头体,右边为CVV,注意:在这里插入图片描述
2、正交投影的变换矩阵可以理解为先将平截头体的中心平移到坐标系原点,再进行缩放
在这里插入图片描述

如上图所示,右边为平移,左边为缩放。注意图片中平移矩阵的第三行,来自闫大神的GAMES101(未考虑实际坐标,第三行带负号),Opengl实际上为第一张图,即z坐标为-n~-f,因此不带负号。包括下面透视投影第一种方式也作了相应改变。
2、正交投影没有远近之分,所以w为1,透视除法不改变方向,不翻转坐标系,直接对应理想的图像坐标系

三、透视投影

透视投影有两种理解方式:一、看成透视到正交,再正交投影变换;二、针孔模型的透视投影

第一种方式

如下所示,先将透视投影指定的平截头体变形成正交投影中的平截头体
在这里插入图片描述
可以看到,透视投影把所有通过原点(眼睛)的直线映射到平行于z轴的直线上,而并不移动z=n平面中直线上点的位置,如下所示。
在这里插入图片描述
变换过程中需要铭记两点:1、变换前后近平面的点始终在近平面上;2、变形前后远平面的点始终在远平面上;如下所示。
在这里插入图片描述
根据第1、2点,且正交投影中平截头体的一条平行线在近平面、远平面的交点的x、y坐标相等,有

在这里插入图片描述
近平面的交点(x’,y’,z’)和远平面的蓝点(点(x,y,z)变形之后)的x、y坐标相等,由相似三角形得到:
在这里插入图片描述
由齐次坐标表示这一过程:
在这里插入图片描述

乘以-z是因为透视除法要将裁剪空间的右手坐标系变为NDC空间的左手坐标系,同时保留深度信息,所以将w设为-z。可以得到透视到正交的变换矩阵,
在这里插入图片描述
在这里插入图片描述
第三行的求解借助了变换过程中的上述两点,由近平面的点不变可以得到,近平面的z坐标为-n
在这里插入图片描述

可以看到,第三行不含x、y,因此必是(0,0,A,B)

同理,由远平面的点始终在远平面得到,远平面的z坐标为-f
在这里插入图片描述
在这里插入图片描述
因此变换矩阵为
在这里插入图片描述
完整投影矩阵如下
在这里插入图片描述

第二种方式

根据针孔相机的成像原理,将透视投影的平截头体变换到CVV

在这里插入图片描述
在OpenGL中,观察空间中的3D点被投影到近平面(投影平面)上。投影过程如下所示。
在这里插入图片描述
(Xe,Ye,Ze)为观察空间中的3D点坐标,(Xp,Yp,Zp)为投影点的坐标。由相似三角形得到,
在这里插入图片描述

(Xc,Yc,Zc,Wc)为裁剪空间的齐次坐标,Wc设为-z的原因上面已有说明。
在这里插入图片描述
将Xp和Yp以线性关系映射到NDC的Xn和Yn,[l,r]=>[-1,1]和[b,y]=>[-1,1]
由线性归一化的等比例性质,有
在这里插入图片描述
在这里插入图片描述
将Xp和Yp代入上述方程
在这里插入图片描述
从上述方程中,可以得到投影矩阵的第一、二行
在这里插入图片描述
NDC空间是由裁剪空间经过透视除法得到的,所以有
在这里插入图片描述
而在观察空间中,We=1,所以
在这里插入图片描述
Ze:[-n,-f];Zn:[-1,1];-n -> -1;-f -> 1,所以有
在这里插入图片描述
求解得到
在这里插入图片描述
完整投影矩阵如下:
在这里插入图片描述

四、OpenGL和OpenCV结合

首先,需要明白OpenGl的透视投影模型和普通相机的小孔投影模型是类似的,其投影矩阵对应于相机的内参矩阵K,观察矩阵对应于相机的外参矩阵[R|T]。但是,我们之前求得的K和[R|T]还不能直接使用,原因有二,其一,OpenGL投影模型使用的坐标系与OpenCV的不同;其二,OpenGL为了进行Clipping,其投影矩阵需要将点投影到NDC空间中。
OpenGL的相机坐标系相当于OpenCV的相机坐标系绕着X轴旋转了180度,因此只需要左乘一个旋转矩阵即可,如下:
[ 1, 0, 0,
0, 1, 0,
0, 0, -1 ]
而对于投影矩阵,不仅要有与内参矩阵K相同的透视效果,还得把点投影到NDC中
内参矩阵K形式如下:
在这里插入图片描述
fx、fy代表像距(fx、fy一般相等,以下为方便与远平面f区分,用focal表示),cx、cy表示理想的图像坐标系原点在像素坐标系下的坐标
注意,在计算机视觉中,一般把f称为焦距,其实是不准确的,在摄影测量学中更准确的表达是像距(主距),即焦点到像平面的距离。焦距实际上是光学中心到焦点的距离。
然后,观察空间的三维点是投影到像平面的,需要注意近平面、远平面和像平面的区分。在OpenGL中,近、远平面到原点的距离是由用户指定,默认近平面就是像平面,到原点的距离是n。而提供了内参矩阵后,像平面到原点的距离为focal,根据到原点的距离从近到远排序:近平面<像平面<远平面。
所以,针对透视投影的第二种方式,因为投影矩阵的第一、二行是先由观察空间的三维点和投影点的相似三角形得到Xp和Xe的对应关系,再由线性归一化的等比例性质得到Xn和Xp的对应关系,推导出来的,而此时投影点的z坐标不再是-n,而是-focal(像距),因此
在这里插入图片描述
投影矩阵的第三行是由Zn、Zc、Ze的边界值的对应关系得到的,与像平面无关,所以不需要改变
最终的投影矩阵只需要将第一、二行中的n换成focal即可
在这里插入图片描述

参考

[1]OpenGL Projection Matrix
[2]深入探索透视投影变换
[3]坐标系统
[4]OpenGL与OpenCV实现增强现实
[5]GAMES101
[6]Fundamentals of Computer Graphics (4th Edition)
[7]焦平面、像平面、主距、焦距辨析

PS:目前还不会用LaTeX,公式之类的只能手写,过一段时间学会了再来更新(如果还记得的话)


http://chatgpt.dhexx.cn/article/vfcPp8V7.shtml

相关文章

图形学-(视图变换,投影变换)

1.视图变换 在 3 维物体变到二维平面的过程中&#xff0c;我们需要规定好相机的位置。对于相机所做的变换就是视图变换 &#xff08;Viewing/Camera transformation&#xff09;。 我们需要对相机位置进行定义&#xff0c;对于一个相机我们要规定下面三个属性&#xff1a; 相…

4.3 投影变换

投影变换的目的就是定义一个视景体,使得视景体外多余的部分裁剪掉,最终图像只是视景体内的有关部分。 投影也是使用矩阵来实现的。计算一个用于实现透视投影或者平行投影的矩阵,并把它与当前的投影矩阵(一般是单位矩阵)相乘。 OpenGL支持两种类型的投影变换,即透视投影…

读书笔记-opencv-投影变换

读书笔记-opencv-投影变换 原理解析 ​ 透视变换是将图片投影到一个新的视平面&#xff0c;也称作投影映射&#xff0e;它是二维&#xff08;x,y&#xff09;到三维(X,Y,Z)&#xff0c;再到另一个二维(x′,y′)空间的映射&#xff0e;相对于仿射变换&#xff0c;它提供了更大…

计算机图形学 | 投影变换

计算机图形学 | 投影变换 计算机图形学 | 投影变换7.1 有趣的投影投影的概念平行投影正投影斜投影 透视投影 7.2 规范化的投影变换观察的要素观察空间规范化的投影变换 华中科技大学《计算机图形学》课程 MOOC地址&#xff1a;计算机图形学&#xff08;HUST&#xff09; 计算…

使用 OpenCV 进行图像投影变换

投影变换&#xff08;仿射变换&#xff09; 在数学中&#xff0c;线性变换是将一个向量空间映射到另一个向量空间的函数&#xff0c;通常由矩阵实现。如果映射保留向量加法和标量乘法&#xff0c;则映射被认为是线性变换。 要将线性变换应用于向量&#xff08;即&#xff0c;一…

Opencv之投影变换

学习资料参考&#xff1a; 张平.《OpenCV算法精解&#xff1a;基于Python与C》.[Z].北京.电子工业出版社.2017. 原理 平面的物体若在三维空间发生了旋转&#xff0c;那么这就是投影变换。平面的物体可以借助二维投影变换进行三维变换模型化得到修正。 处理函数 c中的getPersp…

ArcMap 投影变换

在投影变换之前&#xff0c;首先需要理清出我们拿到的工程数据到底是哪一个投影坐标系&#xff0c;只有清楚是哪一个坐标系才能给我们矢量化出来的数据进行定义投影&#xff08;如果是当地的投影坐标系&#xff0c;可以查看自定义投影坐标系文章&#xff0c;新建出当地的投影坐…

OpenCV : 投影变换

投影变换 物体在三维空间发生了旋转,叫做投影变换.由于可能出现阴影或遮挡,所以变换后较难复原.如果物体时平面的,就可以通过投影变换物体三维变换进行模型化,这叫做专用的二维投影变换. 矩阵表示: [ x ~ y ~ z ~ ] [ a 11 a 12 a 13 a 21 a 22 a 23 a 31 a 32 a 33 ] [ x …

Halcon 第七章『图像的几何变换』◆第2节:投影变换

一、介绍 投影变换也叫透射变换、投影映射。透射变换是将图像投影到一个新的视平面&#xff0c;是一种二维坐标到三维坐标的变换。 透射变换是仿射变换的延续&#xff0c;也可以说仿射变换是透射变换的一种特殊形式。其特殊性在于变换后图像的形状仍然维持原状。投影变换包括的…

投影变换原理和用法

一、定义&#xff1a;投影变换也叫透射变换、投影映射。透射变换是将图像投影到一个新的视平面&#xff0c;是一种二维坐标到三维坐标的变换。 透射变换是仿射变换的延续&#xff0c;也可以说仿射变换是透射变换的一种特殊形式。其特殊性在于变换后图像的形状仍然维持原状。投影…

基于libVLC的视频播放器之四:直接使用libVLC

一.效果 播放本地文件 播放网络url:rtsp://3.84.6.190/vod/mp4:BigBuckBunny_115k.mov 二.实现 既然有VLC-Qt,为什么还要直接调用libVLC呢,因为直接调用会加深对整个播放流程的理解,方便后面修改VLC-Qt源码。

MFC调用vlc动态库libvlc.dll实现简单播放器 中文路径处理

一、简单说明 本文讲解利用MFC调用vlc&#xff08;2.0.0&#xff09;的动态库实现简单的播放器&#xff0c;实现播放、暂停、停止、音量控制、进度控制&#xff0c;支持中文路径等。 VLC 中文路径转码问题<转> 最近用MFC编写调用libVLC的程序时碰到中文路径不能打开的问题…

VLC-Android编译

1.环境 硬核条件----------linux(这里用ubuntu代替)15.5.1 build-15018445 PS&#xff1a;这里安装好虚拟机以后&#xff0c;尽可能分配大内存(8GB起步)&#xff0c;如果电脑本地不允许开这么大的内存给虚拟机&#xff0c;则本博文后面的内容可能帮助不大。 安装好虚拟机后&am…

VLC介绍以及库的使用

VLC原指VideoLAN客户端(VideoLANClient)&#xff0c;是一款开源的、跨平台的、可扩展的、多媒体播放器、流媒体服务器及框架&#xff0c;可播放大多数多媒体文件&#xff0c;以及DVD、音频CD、VCD及各类流媒体协议&#xff0c;现更名为VLC media player&#xff0c;最新版本为2…

LibVLC —— 常用函数解析

函数 ● LIBVLC_API libvlc_instance_t *libvlc_new( int argc , const char *const *argv ); 功能&#xff1a;创建libvlc_instance_t对象。 用法&#xff1a; libvlc_instance_t *VlcInstance libvlc_new(0, nullptr);参数&#xff1a;                具体…

【玩转VLC】--- 基于libvlc写个最简单的播放器

通过【玩转VLC】--- ubuntu下编译vlc 我们已经把vlc编译哦了。生成了一系列的bin和libvlc.so. 接下来我们就用编译好的libvlc.so搞一个最简单的播放器。 我认为vlc的伟大之处有一点就是他并没有把整个播放器写成一个硬生生的bin。而是独立出来个libvlc库&#xff0c;其他的玩…

最简单的基于libVLC的例子:最简单的基于libVLC的推流器

最简单的基于libVLC的例子文章列表&#xff1a; 最简单的基于libVLC的例子&#xff1a;最简单的基于libVLC的视频播放器 最简单的基于libVLC的例子&#xff1a;最简单的基于libVLC的视频播放器&#xff08;图形界面版&#xff09; 最简单的基于libVLC的例子&#xff1a;最简…

C++调用libVLC播放视频

1、下载libVLC的sdk Index of /pub/videolan/vlc/ 注意下载.7z结尾的 2、Visual Studio建立C的windows控制台项目 3、文件准备 &#xff08;1&#xff09;sdk文件夹解压缩到项目文件夹下 &#xff08;2&#xff09;在Debug下方压缩包内的几个文件 、 4、配置项目属性 注意…

最简单的基于libVLC的例子:最简单的基于libVLC的视频播放器(图形界面版)

最简单的基于libVLC的例子文章列表&#xff1a; 最简单的基于libVLC的例子&#xff1a;最简单的基于libVLC的视频播放器 最简单的基于libVLC的例子&#xff1a;最简单的基于libVLC的视频播放器&#xff08;图形界面版&#xff09; 最简单的基于libVLC的例子&#xff1a;最简…

基于libVLC的视频播放器之二:使用VLC-Qt播放RTSP流

此篇是 使用VLC浏览器插件播放RTSP流的姊妹篇。 一.直接使用libVLC libVLC是VLC media player多媒体框架的核心引擎和接口&#xff0c;开发者使用它能轻松的创建大量具有VLC特性的应用。 最简单的基于libVLC的例子&#xff1a;最简单的基于libVLC的视频播放器详细介绍了libVL…