合成相机模型【图形学】

相机在计算机图形学中有两个方面的考虑:相机的位置和相机的形状。 要了解后者,我们需要了解相机的工作原理。

NSDT工具推荐: Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器 - REVIT导出3D模型插件 - 3D模型语义搜索引擎

1、针孔相机

这是针孔相机(拉丁语中的“camera obscura”,意思是“暗室”)的剖面侧视图。 z 轴是假想的,但图左侧的盒子是一个真实的盒子:六个边都是实心的。 盒子正面有一个小针孔,也就是图片上圆圈的位置。 原点放置在针孔处,y 轴垂直向上穿过盒子的前面,z 轴指向场景。 针孔的位置也称为焦点(focal point)。 盒子的深度为d,盒子的高度为h。 我们还可能关心盒子的宽度,但这在这张图片中不可见,因为我们已经消除了该尺寸。

来自外部的光线穿过该孔并落在图像平面上,即盒子的整个背面。 例如,如图所示,来自树顶的一束光线落在盒子的背面。 由于孔非常小,因此只有来自单束光线的光线才能落在相机背面的任何点上。 因此,在这个例子中,只有来自树顶的光才能落在那个位置。 这就是为什么针孔相机拍摄的照片如此清晰。 理论上,它们可以提供无限的清晰度,但实际上会出现其他问题(光线衍射和缺乏足够的光子)。 然而在计算机图形学中,我们只需要理论上的相机。

针孔相机很简单,而且效果很好。 它们是观看日食的标准设备。 我们使用透镜只是为了收集更多的光线。 完美的针孔相机实际上只允许场景中每个位置发出一束光线,这会产生非常暗的图像,或者需要非常敏感的胶片(或视网膜)。 由于收集足够光线的需求在计算机图形学中并不重要,因此 OpenGL 模型是针孔相机的模型。

注意事项:

  • 可以使用相似的三角形来计算图像(例如树)的投影,如下一节所述。
  • 透视的影响是显而易见的,例如图像中的物体随着距相机的距离越来越小。
  • 平行线似乎会聚在一个“消失点”(想象一下沿着铁轨向下看)。
  • 针孔相机的一个缺点是胶片上的图像是颠倒的。 你的单反相机可以“通过镜头”观看,但使用额外的镜头将图像正面翻转。我们很快就会看到如何解决这个问题。

2、通过相似三角形计算投影

假设我们要计算树顶部的投影。 设树顶的坐标为 (X,Y,Z), 我们想知道投影的坐标 (x, y, z) 。可以通过相似的三角形来做到这一点,使用下图中的两个黄色三角形:

大三角形的高和底边长是Y和Z,小三角形的高和底边长是 y和 z。 小三角形的底边是已知的,因为它是由我们的针孔相机的形状和大小决定的,在图中被标记为“d”。 由相似三角形我们知道:

公式右侧的所有内容都是已知的,因此我们只需知道针孔相机的深度和点的位置即可计算任何点的投影。

顺便说一下,我们进行最后一个代数步骤除以  Z/d ,是因为我们将在投影矩阵中使用它。

X的投影坐标的计算方法完全相同。

3、合成相机

针孔相机中的符号有一个麻烦,例如树对应的z值是负数。 此外,图像最终会颠倒。 在 CG 中,由于我们实际上只对投影的数学感兴趣,因此我们使用合成相机(synthetic camera),将成像面与场景放置在原点的同一侧。

在CG中,我们可以将成像面放在焦点的前面。 这意味着图像正面朝上。从数学上讲,我们将使原点成为焦点,相机指向负 z 轴。

成像面是截头锥体(frustum)的顶部。 请参阅下面的演示。截锥体也是我们的可视体块(view volume)。 可视体块之外的任何内容都会被裁剪掉,并且在渲染图像中不可见。

请注意,这也意味着 CG 系统无法看到无限远。 那是因为它需要计算相对深度,并且无法进行无限精细的区分。

我们使用投影矩阵计算投影。请注意,还可以选择进行平行投影而不是透视投影。 在平行投影中,从场景到图像的光线是平行绘制的,而不是会聚在焦点处。 平行投影在建筑绘图等中很有用。

4、视锥体演示

合成(透视)相机的视域是一个平截头体:截断的矩形金字塔。 请点击此链接查看演示,该演示演示了视锥体以及一些相关的参数和术语:

5、相机演示

当我们可以将视锥体的几何形状与场景的渲染结果进行比较时,就更容易理解相机参数的力量。 在这个演示中,我们看到一个带有泰迪熊和相机的场景以及渲染结果:

6、透视矩阵和透视除法

出于同样的原因,我们希望使用矩阵乘法执行所有仿射变换,我们希望使用矩阵乘法执行投影。

OpenGL 和 Three.js 中有两种可用的投影:正交投影和透视投影:

在正交投影(orthographic projection)中,视锥体是一个矩形框,我们只需挤压一个维度即可进行投影。 正如我们之前提到的,这种投影对于建筑绘图和确实没有任何透视的情况非常有用。 如果我们将投影方向(DOP)与Z轴对齐,这种投影相当于将所有点的Z坐标设置为零。 如果我们让场景坐标为 (X,Y,Z) 而投影坐标为 (x,y,z) ,那么下面就是正交投影如何表示为与投影矩阵的乘法:

在这种情况下,对所有点都是: x=X, y=Y, z=0

对于透视投影(perspective projection),如果我们建立一个框架,其中原点是投影中心(COP)并且成像面平行于 Z =0(XY平面),我们可以使用相似三角形计算来计算每个点的投影,将每个Y和 X除以Z/d。

透视投影的矩阵并不明显。 它涉及使用齐次坐标并保留部分计算未完成。

未完成的计算部分称为透视除法,思路是齐次坐标 (x,y,z,w) 与  (x/w,y/w,z/w,1) 相同,也就是说,我们将坐标值除以 w 。如果w=1,这是一个空操作,不会改变我们的顶点。 然而,如果w值为 Z/d ,这种透视除法完成了我们之前在类似三角形中所做的事情,即:

因此,透视矩阵是完成设置 w=Z/d的矩阵并保持其他坐标不变。 由于矩阵的最后一行计算 w,我们需要做的就是把 1/d放在最后一行的 Z 列中。 那么,透视投影矩阵就是以下矩阵:

让我们考虑一下这个矩阵如何变换任意点 (X,Y,Z)

在这种情况下, x=X,  y=Y, z=Z, w=Z/d ,要将结果转换为 w=1 的向量,我们进行透视除法步骤,即将所有分量除以 Z/d,得到:

这正是我们想要的,即原点在图像平面上距离 d 的投影。

7、Three.js 中的透视相机

如之前的视锥体和相机 API 演示中所示,在 Three.js 中,我们可以像这样设置透视相机:

var camera = new THREE.PerspectiveCamera(fov,aspect_ratio,near,far);

我们将此 API 视为设置相机形状(视锥体的几何形状)。

正如我们在上面看到的,当轴与 Z 轴对齐时,透视和正交投影起作用。 这实际上和OpenGL中的初始坐标系是一样的。 但是如果我们不希望我们的场景/相机以这种方式设置怎么办?

早期的演示还说明了我们如何定位和指向相机。 例如,fustrum 演示包含以下 setupCamera() 函数:

function setupCamera() {var cp = cameraParams;      // just a shorthand for this functionfrustumCamera = new THREE.PerspectiveCamera(cp.fov,cp.aspectRatio,cp.near,cp.far);// set locationfrustumCamera.position.set(cp.eyeX, cp.eyeY, cp.eyeZ);// Cameras inherit an "up" vector from Object3D.frustumCamera.up.set(cp.upX, cp.upY, cp.upZ);// The lookAt method computes the camera direction and orientation// from its position and up parameters, and the input arguments// specifying the location of the 'at' pointfrustumCamera.lookAt(cp.atX, cp.atY, cp.atZ);
}

上述函数设置相机投影几何的三个附加组件:

  • EYE是焦点(也称为“投影中心”或 COP)的位置,作为空间中的一个点。 另一个标准术语是 VRP:视参考点。
  • AT是我们希望相机面向的方向上某个点的位置。 它甚至不需要位于视锥体中。 它仅用于确定相机指向的位置。 相机指向方向的标准术语是 VPN:视平面法线(OpenGL 中的矢量)。 这一点实际上是一个非常方便的概念,因为它使我们可以轻松地将相机瞄准应投影到图片中心的某个位置。 例如,如果我们要拍摄一个人的照片,那么点可能是他们的鼻尖,或者他们的眼睛之间。
  • UP矢量表示投影到图像平面上的方向与监视器上的垂直方向相同(与画布的左边缘平行)。 请注意,它是一个向量,而不是一个点。 例如,它可以捕捉风景与肖像。 对此的标准术语是 VUP:向上查看。

换句话说,相机位于称为 EYE的点  (eyeX,eyeY,eyeZ),面向称为  AT 的点  (atX,atY,atZ),并沿由向上向量 (upX,upY,upZ)

在Three.js中,Camera只是Object3D的子类,因此可以使用 position.set()或我们之前了解的其他定位对象的方法设置其位置,并且也可以旋转。 目前我们还不需要缩放相机。

Object3D() 的所有实例还具有一个可以为相机设置的 up 属性,如上面的 setupCamera() 所示。

最后,有一个名为 lookAt() 的有用方法,它使对象指向由其参数指定的特定点。 此方法还使用向上向量来适当地定向对象。 在设置相机的位置和向上矢量之后,你应该最后使用此方法。

8、渲染

我们还需要做一些工作来创建画布并让 Three.js 使用相机在画布上渲染场景。

我们总是需要一个 THREE.Renderer 对象。 该对象有一个名为 render() 的方法,该方法采用场景和相机并使用相机渲染场景。 每当你调整场景或相机时,都需要重新调用此函数。 如果你有全局变量来保存相机和场景,可能只需定义一个更简单的包装函数来进行渲染:

function render() {renderer.render( scene, camera );
}

创建渲染器对象会导致创建默认尺寸为 300 x 150 的 HTML 画布对象,该尺寸非常小。 但是,画布并未添加到文档中; 你需要自己执行此操作。

首先,由于默认画布太小,我们将使用 CSS 来设置画布大小的策略。 在这里,我将使用 800 x 500,因此我将使用 800/500 作为相机的纵横比(视锥体的顶部)。你还可以考虑使用尺寸为 100% x 100% 的画布,覆盖整个浏览器。 如果这样做,请使用 canvasElt.clientWidth/canvasElt.clientHeight 作为相机的纵横比,其中 canvasElt 是下面定义的变量。

canvas {display: block;width: 800px;height: 500px;margin: 10px auto;
}

让我们将所有这些想法放在一起,这是 JavaScript:

var scene = new THREE.Scene();
var renderer = new THREE.WebGLRenderer();
var canvasElt = renderer.domElement;
document.body.appendChild(canvasElt);
renderer.setSize(canvasElt.clientWidth,canvasElt.clientHeight);
renderer.setClearColor( 0xdddddd, 1);

9、其他术语

以下术语通常用于相机等的不同类型的运动。

  • pan:平移,围绕垂直轴旋转固定相机
  • tilt:倾斜,围绕水平轴旋转固定相机
  • zoom:变焦,调整镜头放大或缩小(这调整视锥体)
  • roll:滚动,绕纵轴旋转相机或船
  • pitch:俯仰,与倾斜相同,但适用于船舶和飞机
  • yaw:偏航,与平移相同,但适用于船舶和飞机
  • strafe:扫掠,沿水平轴移动相机; 我相信这个术语被用在视频游戏中

原文链接:针孔相机与合成相机 - BimAnt

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【开源】基于JAVA的大学计算机课程管理平台

项目编号: S 028 ,文末获取源码。 \color{red}{项目编号:S028,文末获取源码。} 项目编号:S028,文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 实验课程档案模块2.2 实验资源模块2…

无限移动的风景 css3 动画 鼠标移入暂停

<style>*{margin:0;padding:0;/* box-sizing: border-box; */}ul{list-style: none;}#nav{width:900px;height:100px;border:2px solid rgb(70, 69, 69);margin:100px auto; overflow: hidden;}#nav ul{animation:moving 5s linear infinite;width:200%; /*怎么模拟动画…

C++继承(详解)

一、继承的概念 1.1、继承的概念 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段&#xff0c;它允许程序员在保持原有类特性的基础上进行扩展&#xff0c;增加功能&#xff0c;这样产生新的类&#xff0c;称派生类。继承呈现了面向对象程序设计的层次结…

SpringBoot2.x整合WebService实现远程接口调用

一、添加依赖 <!-- SpringBoot 2.4 以下版本--> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web-services</artifactId> </dependency><dependency><groupId>org.apach…

沿着马可·波罗的足迹,看数字云南

刚入行的时候&#xff0c;有位前辈跟我说过一句话&#xff1a;去现场“要像外国人一样去看”&#xff0c;重新审视那些自己可能早已“熟视无睹”的事物。 前不久&#xff0c;我跟随“看见数字云南——云南数字经济媒体探营活动”&#xff0c;奔赴昆明、大理、西双版纳等地&…

基于算能的国产AI边缘计算盒子8核心A53丨17.6Tops算力

边缘计算盒子 8核心A53丨17.6Tops算力 ● 可提供17.6TOPS&#xff08;INT8&#xff09;的峰值计算能力、2.2TFLOPS&#xff08;FP32&#xff09;的高精度算力&#xff0c;单芯片最高支持32路H.264 & H.265的实时解码能力。 ● 适配Caffe/TensorFlow/MxNet/PyTorch/ ONNX/…

使用Plex结合cpolar搭建本地私人媒体站并实现远程访问

文章目录 1.前言2. Plex网站搭建2.1 Plex下载和安装2.2 Plex网页测试2.3 cpolar的安装和注册 3. 本地网页发布3.1 Cpolar云端设置3.2 Cpolar本地设置 4. 公网访问测试5. 结语 1.前言 用手机或者平板电脑看视频&#xff0c;已经算是生活中稀松平常的场景了&#xff0c;特别是各…

Spring Initial 脚手架国内镜像地址

官方的脚手架下载太慢了&#xff0c;并且现在没有了Java8的选项&#xff0c;所以找到国内的脚手架镜像地址&#xff0c;推荐给大家。 首先说官方的脚手架 官方的脚手架地址为&#xff1a; https://start.spring.io/ 但是可以看到&#xff0c;并没有了Java8的选项。 所以推荐…

线程池(Linux +C/C++)

参考 手写线程池 - C语言版 | 爱编程的大丙 (subingwen.cn) 1.为什么需要线程池&#xff1f; 1&#xff09;线程问题&#xff1a; &#xff08;1&#xff09;如果只使用线程创建函数&#xff0c;在不断有新的任务进来的时候&#xff0c;需要不断的创建任务&#xff1b;任务在…

【已解决】为什么Word文档里有部分内容无法编辑?

小伙伴们是否遇到过这样的情况&#xff0c;打开Word文档进行编辑&#xff0c;发现部分内容可正常编辑&#xff0c;另外一部分内容却无法编辑。这是怎么回事&#xff0c;又要如何解决呢&#xff1f; 出现以上情况&#xff0c;一般是Word文档被设置了“限制保护”&#xff0c;使…

外包干了4年,技术退步太明显了。。。。。

先说一下自己的情况&#xff0c;本科生生&#xff0c;18年通过校招进入武汉某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年国庆&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测…

PLC通过485Modbus转Profinet网关与温控表通讯在发酵罐的应用

前提&#xff1a;在自动化控制系统中&#xff0c;PLC通常需要和各种设备进行数据通讯&#xff0c;其中就包括温控表。而这些设备之间的通讯常常需要通过485Modbus转Profinet网关&#xff08;XD-MDPN100&#xff09;来实现。 方案&#xff1a;在一些应用场合中&#xff0c;Profi…

【C语言】扫雷小游戏初学者版

成功的秘诀就是每天都比别人多努力一点。 今天给大家带来一款非常经典的小游戏——扫雷的实现和讲解 这里是目录 前言整体框架1.打印菜单2.创建二维数组3.初始化棋盘4.打印棋盘5.布置棋盘中的雷6.排查雷和统计雷总体代码test.cgame.cgame.h 进阶&#xff08;递归展开&#xff0…

OpenLayer库的学习入门总结

前言&#xff1a; 作者跟随视频学习ol库的调用与功能实现&#xff0c;进行初步总结与回顾。 声明&#xff1a;参考新中地的文档&#xff0c;进行作者日后复习再次学习的简化。 1、WebGIS简介 GIS的核心概念 GIS&#xff08;Geographic Information System&#xff09;是一…

项目demo —— GPT 聊天机器人

本文介绍我的开源项目 TelegramChatBot&#xff0c;这是一个基于 OpenAI GPT API 开发的 telegram 机器人&#xff0c;具有多模态交互能力&#xff0c;求 star&#xff01;感谢大家&#xff01;在 telegram jokerController_bot 立即体验&#xff01;欢迎对 GPT 应用开发或对 t…

[cocos creator]EditBox,editing-return事件,清空输入框

需求&#xff1a; 监听EditBox&#xff0c;editing-return 回车事件&#xff0c;在输入框内点击回车后&#xff0c;发送内容&#xff0c;并清空输入框 问题&#xff1a; 设置node.getComponent(EditBox).string ; 没有效果 解决办法&#xff1a; //设置string 为空 this.v…

Linux入门攻坚——7、磁盘管理——文件系统挂载管理及RAID、LVM

已经安装文件系统的分区需要经过挂载才能使用。 一切文件系统的使用都是从根开始&#xff0c;根是文件系统的起始点。 计算机启动过程&#xff1a;加电自检——bootloader——kernel——rootfs——/sbin/init kernel第一步要加载根系统。 将额外文件系统与根文件系统某现存的…

Selenium自动化测试:通过cookie绕过验证码的操作

验证码的处理 对于web应用&#xff0c;很多地方比如登录、发帖都需要输入验证码&#xff0c;类型也多种多样&#xff1b;登录/核心操作过程中&#xff0c;系统会产生随机的验证码图片&#xff0c;进行验证才能进行后续操作 ​解决验证码的方法如下&#xff1a; 1、开发做个万…

Ubuntu20.04使用SVN(Rabbitvcs)

原文&#xff1a;https://blog.csdn.net/u014552102/article/details/129914787 1.安装Rabbitvcs sudo apt-get install rabbitvcs-nautilus sudo reboot 安装完后&#xff0c;选中一个文件夹右键&#xff0c;即可看到相关操作&#xff0c;没有的可以重启一下。 2.添加这个p…

数字化转型失败率为什么这么高?

引言 数字化转型已成为当今商业环境中的重要议题。它指的是企业通过采用数字技术&#xff0c;对业务流程、文化和客户体验进行全面变革&#xff0c;以适应数字化时代的需求和趋势。 然而&#xff0c;尽管数字化转型的重要性日益凸显&#xff0c;但令人担忧的是&#xff0c;许多…