(转)Cameras on OpenGL ES 2.x - The ModelViewProjection Matrix

本文深入探讨3D世界中的摄像机原理,包括凸透镜和凹透镜的区别,以及如何利用OpenGL ES 2.x创建摄像机。我们将讨论透视投影、正交投影等基本摄像机类型,以及矩阵和四元数在3D渲染中的应用。

转:http://blog.db-in.com/cameras-on-opengl-es-2-x/
介绍OpenGL es中的MVP矩阵比较好的文章,有空要把他翻译过来
在这篇文章里,我将讲一个在3D世界里非常重要的部分。就像你们了解的一样,在设备显示屏后面的世界试图去重建人眼中的美妙和复杂。为了实现它,我们使用了摄像头,它是人眼在现实世界中的模拟。我们使用数学公式去创建这个摄像头。
在这篇文章中,后面我将探讨这些摄像头和公式,凹凸镜头的区别,讲讲什么是投影,矩阵,四元数,以及非常有名的mvp矩阵。如果你有什么疑问,尽管提出,我非常乐意去帮你们解答。以下是本篇内容的目录列表,它将帮你在这篇文章中找到一些你想要的东西。
目录

概要
首先让我们看看摄像头的基础,他在真实世界中的工作原理,凹凸镜的区别,怎样缩放,平移,旋转的。了解了这些概念之后,让我们深入了解OpenGL,并了解所有这些概念如何适用到我们的应用程序。所以最后我们进行编码,我会提供他们依赖的公式以及对应的解释。
你是否记得我的OpenGL系列教程中,我说过,Khronos已经被委托了很多职责去专注3D世界中最重要的部分。(more precisely from the part1, if not, you can check it here)那么,从openGL ES 1.x到2.x,摄像头是Khronos委托的那些职责之一。现在我们要自己创建这些摄像头了。想知道吗?通过着色器行为,我们可以对应用程序进行令人惊奇的控制,此外我们可以自由的去搭建一个3D引擎。
使用OpenGL控制摄像头的话,我们只有2,3种可以使用的摄像头。但如果我们对摄像头进行编程时,我们可以创建各种各样的摄像头。在这篇文章里,我将讲讲几个基础的摄像头:正交摄像头和透视摄像头。
OK,Let’s start!

真实世界中的摄像头
人眼是一个凸透镜,它会聚集图像在视网膜上形成一个上下颠倒图像,通常相机的镜头是有多个凸透镜和凹透镜组成的,但最终的图像看起来更像一个凸透镜形成的,就像人的眼睛一样。
最终图像是由许多因素决定的,并不止镜头的类型,但在普通的世界里,下图展示了图片在经过各种透镜后的现实效果。
这里写图片描述
两种类型透镜都能生成一个与原图对应的图像,我的意思是,会有一个微小的扭曲角度,这取决于物体与镜头距离和视角。下图展示了摄像头中最重要的属性。
这里写图片描述
上图中的红色区域对摄像机来说是不可见的,所以在这些区域内任何片元都将被剪裁掉,“Depth of Field”是可见区域,所有在该区域内的片元都可见。通常,“Depth of Field”这个词也用来描述一个特殊的效果,即镜片模糊效果。当人眼具有使外部对象看起来模糊的焦点时,透镜模糊效果模拟焦点,使得焦点之外的对象看起来模糊。那么我为什么不把“Focus”这个属性放到上面的图片中内?因为在一些摄像机中,焦点是一个特殊的特征,基础的3D摄像头并没有实现焦点行为。另一个重要的属性是“视角(Angle of View)”它表示相机可见的水平角度。所有在这个视角之外的片元摄像机都不可见。有事“视角”也用来表示垂直区域,但通常我们更喜欢使用宽度和高度来定义最终图像的宽高比。
现代摄像机非常准确,可以使用这些属性和镜头类型组合产生很好的效果。现在让我们回到虚拟世界,看看我们如何在数学上转换这些属性和行为。在转移到3D摄像机前,我们要理解3D世界里的一些数学知识。
3D世界简史
3D的鼻祖是欧几里得。他生活在公元前323-283,在希腊的亚历山大。他创建了我们至今还在用的欧几里得空间和欧几里得定理。基本上,欧几里得空间由3个平面组成,分别是x,y和z。不难想象为什么欧几里得创造了这个理论,因为希腊人热爱建筑学,为了构造完美的结构,他们需要在3D虚拟世界中创建很多微积分,跟不用说他们对哲学和科学的激情了。
OK,他们做的跟摄像机有什么关系呢?很简单,基于他们的发明,我们开始使用4x4矩阵去处理坐标转换,并且用四元组去描述在四维空间中的一个点(XYZW)。其中W是一个齐次坐标的元素。这里我不打算讲它,只是让你知道,齐次坐标是August Ferdinand Möbius于1827年发明,用来表示笛卡尔坐标系中无限大空间的概念的。我们将在后面介绍Möbius的贡献。在这之前,用笛卡尔坐标系统去表示无限的空间比较复杂,虽然我们可以用一个复杂的虚数去表示它,但这样不是很方便去计算。所以为了解决这个问题,Möbius 增减了一个变量W,它是一个实数,可以让我们回到实数空间去。关键是,一个4x4的矩阵和4元组很吻合,因为我们可以用一个矩阵把欧几里得变换转换到3D世界中,所以我觉得同样用一个4x4矩阵去处理3D世界里的摄像机也是合理的

<think>好的,我现在需要帮助用户解决他们关于COLMAP导出的images.txt文件中数字对应关系的问题。用户给出了一行数据,里面包含了很多数字,他们想知道这些数字分别对应什么含义。 首先,我需要回忆一下COLMAP的images.txt文件的结构。根据之前的回答,images.txt的每一行代表一个图像的相机位姿信息,格式是IMAGE_ID, QW, QX, QY, QZ(四元数),TX, TY, TZ(平移向量),CAMERA_ID,然后是IMAGE_NAME。接下来可能还有特征点坐标和3D点关联的信息。 用户提供的例子是: 1 0.98787793114320688 -0.061849501410892918 0.13401713066753884 -0.048075368153362767 -0.31997720698821075 -0.088297387515579265 -0.66418903224863457 1 output_0001.jpg 289.1632080078125 4.4655094146728516 -1 228.1365966796875 5.0512723922729492 -1 ...(后面还有很多数字) 看起来用户的数据行中除了基本的相机参数外,后面还有大量数字。这可能是因为images.txt中除了相机位姿外,还包含特征点的坐标和对应的3D点ID。根据COLMAP的文档,images.txt的结构通常是: 每张图像有两行数据: 第一行:IMAGE_ID, QW, QX, QY, QZ, TX, TY, TZ, CAMERA_ID, IMAGE_NAME 第二行:POINT3D_ID, X, Y, POINT3D_ID, X, Y, ...(即每个特征点的坐标和对应的3D点ID) 但用户给出的例子中似乎所有数字都在同一行,这可能是因为实际文件中可能存在换行问题,或者用户复制时格式被破坏了。不过根据错误信息,用户可能是在处理过程中遇到了换行符的问题,这可能已经解决。 现在需要分解这行数据。首先,前几个数字应该是IMAGE_ID=1,接着是四元数QW=0.987..., QX=-0.061..., QY=0.134..., QZ=-0.048...,然后是TX=-0.319..., TY=-0.088..., TZ=-0.664...,CAMERA_ID=1,IMAGE_NAME=output_0001.jpg。接下来的数字应该是特征点数据,每三个数字一组,比如289.163, 4.465, -1,其中前两个是特征点的坐标(X,Y),第三个是对应的POINT3D_ID(这里-1表示没有对应的3D点)。 用户可能想知道这些数字的具体对应关系,特别是后面的数字如何解析。需要确认每个部分的分隔方式,以及如何区分相机参数和特征点数据。此外,用户可能对为什么后面有很多-1感兴趣,这可能表示某些特征点尚未匹配到3D点。 需要确保用户理解每一部分的含义,并可能指导他们如何解析这些数据,或者处理其中的异常情况,例如-1的处理。同时,用户可能希望知道如何提取特定信息,如相机位姿或特征点坐标,或者如何验证数据的正确性。 可能还需要检查用户提供的数据是否完整,例如特征点数据是否成组出现(每组三个数字)。如果后面的数字没有被正确分组,可能需要进一步确认文件的格式是否符合COLMAP的标准,或者是否存在解析错误。 总结来说,用户的主要问题在于解析images.txt中的各个字段,特别是后面特征点相关的数据。需要详细解释每个部分的含义,并可能提供解析示例或工具建议,帮助用户正确提取所需信息。</think>以下是COLMAP `images.txt` 文件中该行数据的详细对应关系解析: --- ### **基础相机参数部分** 1. `1` → **IMAGE_ID** (图像唯一标识符) 2. `0.98787793114320688` → **QW** (四元数实部) 3. `-0.061849501410892918` → **QX** (四元数虚部i) 4. `0.13401713066753884` → **QY** (四元数虚部j) 5. `-0.048075368153362767` → **QZ** (四元数虚部k) 6. `-0.31997720698821075` → **TX** (平移向量X) 7. `-0.088297387515579265` → **TY** (平移向量Y) 8. `-0.66418903224863457` → **TZ** (平移向量Z) 9. `1` → **CAMERA_ID** (关联`cameras.txt`中的相机内参) 10. `output_0001.jpg` → **IMAGE_NAME** (图像文件名) --- ### **特征点关联数据(后续部分)** 每组3个数字为一个特征点关联记录: ``` 289.1632080078125 4.4655094146728516 -1 228.1365966796875 5.0512723922729492 -1 ... ``` 1. **前两个数字** → 特征点在图像中的坐标 `(X, Y)` - 例如 `289.1632` (X坐标), `4.4655` (Y坐标) 2. **第三个数字** → 关联的3D点ID(来自`points3D.txt`) - `-1` 表示该特征点未匹配到任何3D点 - 非负数(如`123`)表示关联的3D点ID --- ### **完整解析示例** 以第一组特征点为例: ``` 289.1632080078125 (X) 4.4655094146728516 (Y) -1 (无对应3D点) ``` --- ### **常见问题排查** 1. **大量-1的含义** - 表示稀疏重建未完成三角化的特征点(仅在特征匹配阶段存在,未参与最终3D点云构建) 2. **如何提取有效轨迹** - 仅需关注前9个字段(IMAGE_ID到CAMERA_ID),忽略特征点部分 3. **坐标精度问题** - COLMAP输出的坐标通常保留15位小数,可通过脚本截断精度: ```python # 保留6位小数示例 formatted = [f"{x:.6f}" for x in [q_w, q_x, q_y, q_z, t_x, t_y, t_z]] ``` --- ### **可视化验证方法** ```bash # 使用COLMAP内置工具验证轨迹 colmap model_analyzer --path /path/to/reconstruction # 提取相机轨迹到TUM格式(用于评估) python -c "import numpy as np; from pyquaternion import Quaternion; \ data = np.loadtxt('images.txt', skiprows=4); \ for row in data: \ q = Quaternion(row[1], row[2], row[3], row[4]); \ t = row[5:8]; \ R = q.rotation_matrix; \ cam_pos = -np.dot(R.T, t); \ print(f'{row[0]} {" ".join(map(str, cam_pos))} 0 0 0 0 1')" ``` --- ### **相关问题** 1. 如何将四元数换为TUM轨迹文件所需的欧拉角? 2. 如何过滤掉`-1`标记的无效特征点数据? 3. 如何批量提取所有图像的相机位置生成轨迹点云? 4. 如何解决`images.txt`中四元数与OpenCV坐标系的换问题? 5. 如何用Python自动解析COLMAP的`images.txt`文件?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值