透视变换矩阵详解

article/2025/10/3 21:00:04
原文: OpenGLProjection Matrix (songho.ca)

看这篇文章主要是因为对learnopengl深度测试这一章的些许疑惑,

为什么在片段着色器中,存储的每一个fragment的深度值并不是线性分布?体现在想要显示出场景里面所有物体的深度值,深度值是能在片段着色器的内建变量gl_FragCoord变量中查到,这个变量中存储的是z-buffer中该片段对应的坐标值(0-1.0)(当然是通过顶点插值出来的,这一部分OPENGL自动完成),那么它为什么是非线性的呢?主要是因为透视投影导致。下面这篇文章就能回答问题。

可以观察透视投影矩阵第四行是00-10,这其实就是在给透视除法做准备,经过透视矩阵或者说裁剪矩阵之后,透视坐标w会被赋予特殊的意义(-z,z是view空间内的该点z坐标);

这是实际上通过投影变换之后ze到zn的变换,可以看出来这个映射是非线性的。

另外注意投影矩阵会改变空间的旋向性:空间从右手坐标系变换到了左手坐标系。这意味着,离摄像机越远,z值将越大。

也就是坐标系会变成

从view坐标到NDC空间,其实是透视投影矩阵projection+ 透视除法,只用projection矩阵之后其实是在裁剪空间,这个时候的w分量是-z,在这一步可以进行裁剪,将xc,yc,zc与w进行比较,在这之外的点全部去除,并且构造新的点。这就完成了裁剪。

除以w,即透视除法,也就到了NDC空间。

关于深度测试:gl_FragCoord给的是0-1之间的值,是将NDC中的深度值,映射到了0-1.0之间(线性的),那么要还原这个值,就需要先还原到NDC空间

float z = depth * 2.0 - 1.0;

然后通过投影矩阵的逆变换还原

注意这个式子跟我之前推出来的不一样,差个负号,这是因为:要注意!从view坐标到NDC坐标会发生空间旋性变化,从右手系到了左手系,里面原本越大的深度值,换过去会变成一个越小的负数,所以应该乘一个负号,变成正值,这样就可以比较大小了。

正文开始

概述

计算机显示器是二维表面。OpenGL渲染的3D场景必须作为2D图像投影到计算机屏幕上。GL_PROJECTION矩阵用于此投影变换。首先,它将所有顶点数据从view坐标转换为裁剪坐标。然后,这些裁剪坐标也通过除以裁剪坐标的w分量而变换为归一化设备坐标(NDC)。

因此,我们必须记住,裁剪(截头体剔除)和NDC转换都集成到GL_PROJECTION矩阵中。以下部分描述了如何从6个参数构建投影矩阵;左、右、下、上、近和远边界值。

注意,截头体剔除(剪裁)是在剪裁坐标中执行的,就在除以wc之前。通过与wc的比较,测试了剪辑坐标xc、yc和zc。如果任何剪裁坐标小于-wc或大于wc,则顶点将被丢弃。

然后,OpenGL将重建发生剪切的多边形的边缘。

透视投影矩阵:

在透视投影中,截头棱锥体(view坐标)中的3D点被映射到立方体(NDC);

x坐标从[l,r]到[-1,1]的范围,y坐标从[b,t]到[-1,1],z坐标从[-n,-f]到[-1,1]。

注意,view坐标在右手坐标系中定义,但NDC使用左手坐标系。也就是说,原点的相机在view空间中沿-Z轴观看,但在NDC中沿+Z轴观看。由于glFrustum()只接受near和far的正值,因此我们需要在GL_PROJECTION矩阵的构造过程中对它们求反。

在OpenGL中,眼睛空间中的3D点被投影到近平面(投影平面)上。下图显示了眼睛空间中的点(xe,ye,ze)如何投影到近平面上的(xp,yp,zp)。

从截头体的俯视图来看,眼睛空间的x坐标xe被映射到xp,这是通过使用相似三角形的比率来计算的;

从截头体的侧视图来看,yp也以类似的方式计算;

注意xp和yp都依赖于ze;它们与-ze成反比。换句话说,它们都被-ze除。这是构建GL_PROJECTION矩阵的第一条线索。在通过乘以GL_PROJECTION矩阵变换view坐标之后,裁剪坐标仍然是齐次坐标(http://www.songho.ca/math/homogeneous/homogeneous.html)。它最终成为归一化设备坐标(NDC)是通过除以裁剪坐标的w分量。(请参阅有关OpenGL转换的详细信息。http://www.songho.ca/opengl/gl_transform.html)

因此,我们可以将裁剪坐标的w分量设置为-ze。并且,GL_PROJECTION矩阵的第4行变为(0,0,-1,0)。

接下来,我们用线性关系将xp和yp映射到NDC的xn和yn;[l,r]⇒ [-1,1]和[b,t]⇒ [-1, 1].

然后,我们将xp和yp代入上述方程。

注意,我们使每个方程的两个项都可以被-ze整除,以进行透视除法(xc/wc,yc/wc)。我们之前将wc设置为-ze,括号内的部分变为裁剪坐标的xc和yc。从这些方程中,我们可以找到GL_PROJECTION矩阵的第一行和第二行。

现在,我们只需要求解GL_PROJECTION矩阵的第三行。发现zn与其他的有点不同,因为view空间中的ze总是投影到近平面上的-n。但我们需要用于剪切和深度测试的唯一z值。此外,我们应该能够取消投影(逆变换)它。由于我们知道z不依赖于x或y值,我们借用w分量来找到zn和ze之间的关系。因此,我们可以这样指定GL_PROJECTION矩阵的第三行。

在view空间中,We等于1。因此,方程式变为:

为了找到系数A和B,我们使用(ze,zn)关系;(-n,-1)和(-f,1),并将它们放入上述方程中。

为了求解A和B的方程,重写B的方程(1);

将方程(1’)代入方程(2)中的B,然后求解A;

将A代入方程(1),求出B;

我们找到了A和B。因此,ze和zn之间的关系变为;

最后,我们找到了GL_PROJECTION矩阵的所有条目。完整的投影矩阵为:

此投影矩阵用于一般平截头体。如果观看体积viewing volume是对称的,也就是r = -l, t = -b,则可以简化为:

在我们继续之前,请再次查看ze和zn之间的关系,方程式(3)。你注意到它是一个有理函数,是ze和zn之间的非线性关系。这意味着近平面的精度非常高,但远平面的精度很低。如果范围[-n,-f]越来越大,则会导致深度精度问题(z-fighting);远平面附近的ze的微小变化不影响zn值。n和f之间的距离应尽可能短,以最小化深度缓冲精度问题。


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

相关文章

【图像处理】透视变换 Perspective Transformation

透视变换(Perspective Transformation)是将图片投影到一个新的视平面(Viewing Plane),也称作投影映射(Projective Mapping)。通用的变换公式为: u,v是原始图片左边,对应得到变换后的图片坐标x,y,其中。变换矩阵可以拆成4部分,表示…

Opencv中的透视变换

唐宇迪视频学习笔记 def four_point_transform(image, pts):# 获取输入坐标点rect order_points(pts)(tl, tr, br, bl) rect# 计算输入的w和h值widthA np.sqrt(((br[0] - bl[0]) ** 2) ((br[1] - bl[1]) ** 2))widthB np.sqrt(((tr[0] - tl[0]) ** 2) ((tr[1] - tl[1])…

OpenCV中的透视变换介绍

点击上方“小白学视觉”,选择加"星标"或“置顶” 重磅干货,第一时间送达本文转自:opencv学堂 透视变换原理 透视变换是将图像从一个视平面投影到另外一个视平面的过程,所以透视变换也被称为投影映射(Project…

仿射变换和透视变换

透视变换 1. 欧式变换2. 相似变换3. 仿射变换4. 射影变换/透视变换概念OpenCV 实现 3D 空间存在集中变换方式。 1. 欧式变换 欧式变换保持了向量的长度和夹角,相当于我们把一个刚体原封不动地进行了移动或旋转,不改变它自身的样子,其矩阵表…

基于OpenCV的图像透视变换详解(从理论到实现再到实践)

一、仿射变换与透视变换 一直无法理解两种仿射变换与透视变换的区别,因此详细学习了两种变换的具体细节,重新书写了公式,并给出自己的一些看法。 1.仿射变换 可以认为,仿射变换是透视变换的一种特例。 仿射变换是一种二维坐标到二…

透视变换(perspective transformation)

透视变换(Perspective Transformation)是将图片投影到一个新的视平面(Viewing Plane),也称作投影映射(Projective Mapping)。如下图所示 透视变换 透视变换的原理和公式推导见如下博客 【图像处理】透视变换 Perspective Transformation 【OpenCV】透视变换 Perspe…

OpenCV 透视变换

OpenCV 透视变换 1. 简介2. 仿射变换2.1. 平移2.2. 旋转2.3. 放缩2.4. 错切2.5. 仿射变换 3. 透视变换 1. 简介 汽车的360度全景影像,从拍照视角变成鸟瞰图 这种变换常常用到透视变换 在了解透视变换前,需要了解一下其他的变换,包括 平移&am…

深入探索透视投影变换

深入探索透视投影变换 最近更新:2013年11月22日 -Twinsen编写 -本人水平有限,疏忽错误在所难免,还请各位数学高手、编程高手不吝赐教 -email: popyynetease.com -B站专栏: https://b23.tv/oWsl6PD 透视投影是3D固定流水线的重要组…

图像透视变换原理及实现

上篇博客讲解了图像的仿射变换原理及实现,这篇博客讲讲透视变换的原理和实现,透视变换也叫投影变换,仿射变换是透视变换的特例。主要是透视变换能保持“直线性”,即原图像里面的直线,经透视变换后仍为直线。下面给出数…

(十四)透视变换

透视变换(Perspective Transformation) 一 图像变换与平面坐标系的关系 1、旋转: 2、平移: 3、刚体变换 4、仿射变换 5、投影变换(单应性变换) 6 总结一下: 1、刚体变换:平移旋转,只改变物体…

图像畸变矫正——透视变换

图像畸变矫正——透视变换 由于相机制造精度以及组装工艺的偏差引入的畸变,或者由于照片拍摄时的角度、旋转、缩放等问题, 可能会导致原始图像的失真,如果要修复这些失真,我们可以通过透视变换,对图像进行畸变矫正。 …

透视变换原理实例代码详解

导读 在上篇文章中,我们介绍了仿射变换,我们只需要通过一个两行三列的变换矩阵M就能够对图像实现平移、缩放、翻转、旋转操作。我们发现这些变换其实都属于平面变换,如果我们想要进行空间变换呢? 将上图的扑克牌单独提取出来&am…

[解疑]图像、矩阵的二维空间变换

本文经过参考多个文章整理而成,感谢各位博主的无私分享。 综述 图像(2维平面)到图像(2维平面)的四种变换包括:等距变换,相似变换,仿射变换,投影变换。对图像的几何变换…

数字图像处理(入门篇)十四 透视变换

目录 一 透视变换 二 实践 (1)代码 (2)结果图 一 透视变换 现实生活中的空间是三维的,图像中的物体存在近大远小的特征,这种畸变仿射变换不能矫正。因此,我们需要使用到三维空间的变化&…

【图像理论】透视变换

透视变换: 定义:本质是将图像投影到一个新的视平面。仿射变换可以理解为透视变换的特殊形式。利用透视中心、像点、目标点三点共线的条件,按透视旋转定律使承影面(透视面)绕迹线(透视轴)旋转某…

Python图像处理之透视变换

1 引言 如果你想对图像进行校准,那么透视变换是非常有效的变换手段。透视变换的定义为将图像投影到一个新的视平面,通常也被称之为投影映射。 2 公式 一般来说,通用的图像变换公式如下所示: 上述公式中,u,v代表原…

维特比算法 python_维特比算法理解与实现(Python)

前言 写这篇文章就是想以通俗易懂的方式解析维特比算法,最后给出Python代码的实现。下面的公式和原理均出自《统计学习方法》。 算法的原理 算法的原理1.PNG 算法的原理2.PNG 上面写了一大堆,意思就是:每个时刻选择出概率最大的路径&#xf…

viterbi-algorithm 维特比算法的例子解析

维特比算法的目的: 寻找最可能的隐藏状态序列(Finding most probable sequence of hidden states) 关于原理的讲解可以参考下面两篇文章,讲的比较清楚 小白给小白详解维特比算法1. 小白给小白详解维特比算法2. 本文通过分析维特比算法的例子&#xff0c…

维特比算法代码

维特比算法实现python语言版 本文主要写一个关于维特比算法的代码,具体理论请参考一文搞懂HMM(隐马尔可夫模型): HMM(隐马尔可夫模型)是用来描述隐含未知参数的统计模型,举一个经典的例子&…

维特比算法学习

参考文章1: 简直不要太通俗易懂,这篇文章,很值得看 参考文章2: 解释一些概念性的问题,我把他的一些内容写下来 维特比(Viterbi)算法的核心是动态规划。 对于 HMM 而言,其中一个重要的任务就是要找出最有…