合成相机模型【图形学】

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

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.mzph.cn/news/192382.shtml

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

相关文章

如何在Rocky Linux中安装nmon

一、环境基础 [rootlocalhost nmon16d]# cat /etc/redhat-release Rocky Linux release 9.2 (Blue Onyx) [rootlocalhost nmon16d]# uname -r 5.14.0-284.11.1.el9_2.x86_64 [rootlocalhost nmon16d]# 二、安装步骤 在Rocky Linux和AlmaLinux等基于RHEL 的发行版上&#xff…

前后端数据传输格式(上)

作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO 联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬 作为后端,写…

C#,数值计算——插值和外推,三次样条插值(Spline_interp)的计算方法与源程序

1 文本格式 using System; namespace Legalsoft.Truffer { /// <summary> /// 三次样条插值 /// Cubic Spline Interpolation /// Cubic spline interpolation object. Construct with x and y vectors, and /// (optionally) values of the first…

算法学习系列(三):汉诺塔

目录&#xff1a; 引言一、问题描述二、问题求解三、测试四、附录&#xff08;所有代码&#xff09; 引言 这个汉诺塔问题就是一个典型的递归问题&#xff0c;这篇博客也算是上一篇的一个扩展吧&#xff0c;都是递归问题&#xff0c;这个问题太大&#xff0c;而且牵扯到的问题…

深度学习——第03章 Python程序设计语言(3.1 Python语言基础)

无论是在机器学习还是深度学习中&#xff0c;Python已经成为主导性的编程语言。而且&#xff0c;现在许多主流的深度学习框架&#xff0c;例如PyTorch、TensorFlow也都是基于Python。本课程主要是围绕“理论实战”同时进行&#xff0c;所以本章将重点介绍深度学习中Python的必备…

Python遥感开发之快速判断TIF数据为空

Python遥感开发之快速判断TIF数据为空 前言&#xff1a;介绍一下如何使用python下的gdal读取tif数据的时候&#xff0c;快速判断该tif数据是否为空&#xff0c;如果为空的话就把当前的tif删掉。 如图所示&#xff0c;通过arcgis查看箭头指向的为空值。 仅通过文件的大小无法判…

人工智能中的模型评估

1 概述 1.1 定义 人工智能&#xff08;AI&#xff09;模型评估是一个关键的过程&#xff0c;用于确定模型在特定任务上的性能和有效性。这个过程涉及使用各种技术和指标来衡量模型的准确度、可靠性、泛化能力以及其他重要特性。在不同的应用场景中&#xff0c;模型评估的具体…

Qt Creator 11.0.3同时使用Qt6.5和Qt5.14.2

Qt Creator 11.0.3同时使用Qt6.5和Qt5.14.2 概要方法1.打开Qt Creator中的Kit&#xff0c;这里我直接附上几张截图&#xff0c;不同的版本打开位置可能有所不同&#xff0c;总之最终目的是要打开构建套件&#xff08;Kit&#xff09;2.可以看到构建套件里面有包含了“构建套件K…

深度学习记录--计算图(前向后向传播)

什么是计算图&#xff1f; 从一个例子入手&#xff1a; 将函数J的计算用流程图表示出来&#xff0c;这样的流程图被称为计算图 简单来说&#xff0c;计算图是用来显示每个变量间的关系的一种图 两种传播方式 计算图有两种传播方式&#xff1a;前向传播 和 后向传播 什么是前…

使用dirmap命令行时报错,提示缺少gevent模块

记得以前是可以的&#xff0c;可能是时间长了重装了系统&#xff0c;引起的。 修复方法。升级pip&#xff0c;然后重新下载安装gevent模块。 具体&#xff1a; python -m pip install --upgrade pip 使用下面命令解决下载慢的问题。 pip config set global.index-url http…

【WPF.NET开发】WPF.NET桌面应用开发概述

本文内容 为何从 .NET Framework 升级使用 WPF 进行编程标记和代码隐藏输入和命令控件布局数据绑定图形和动画文本和版式自定义 WPF 应用 Windows Presentation Foundation (WPF) 是一个与分辨率无关的 UI 框架&#xff0c;使用基于矢量的呈现引擎&#xff0c;构建用于利用现…

图片处理OpenCV IMDecode模式说明【生产问题处理】

OpenCV IMDecode模式说明【生产问题处理】 1 前言 今天售后同事反馈说客户使用我们的图片处理&#xff0c;将PNG图片处理为JPG图片之后&#xff0c;变为了白板。 我们图片处理使用的是openCV来进行处理 2 分析 2.1 图片是否损坏&#xff1a;非标准PNG头部 于是&#xff0c;马…

SHAP(六):使用 XGBoost 和 HyperOpt 进行信用卡欺诈检测

SHAP&#xff08;六&#xff09;&#xff1a;使用 XGBoost 和 HyperOpt 进行信用卡欺诈检测 本笔记本介绍了 XGBoost Classifier 在金融行业中的实现&#xff0c;特别是在信用卡欺诈检测方面。 构建 XGBoost 分类器后&#xff0c;它将使用 HyperOpt 库&#xff08;sklearn 的 …

【U8+】用友U8删除固定资产卡片,提示:当前卡片不是本月录入的卡片,不能删除。

【问题描述】 用友U8软件&#xff0c;参照已有账套新建账套的时候&#xff0c;选择结转期初余额。 例如&#xff1a;参照已有账套的2022年新建2023年的账套。 结转期初的时候勾选了固定资产模块&#xff0c; 建立成功后登录23年新的账套后&#xff0c;删除固定资产卡片&#xf…

基于Eclipse+SDK+ADT+DDMS的安卓开发环境完整搭建过程

基于EclipseSDKADTDDMS的安卓开发环境完整搭建过程 1 基本概念2 SDK安装3 Eclipse安装4 ADT插件安装4.1 在线安装&#xff08;太慢不建议选择&#xff09;4.2 离线安装&#xff08;建议选择&#xff09; 5 配置SDK6 集成安装7 创建安卓虚拟设备8 创建并启动安卓虚拟机8 关于DDM…

nextjs入门

创建项目 npx create-next-app 项目名 体验文件路由 nextjs提供了文件路由的功能, 根据文件系统的目录结构, 可以识别为对应的页面路由 创建页面 首先, 在src下创建pages目录, 然后创建一个about文件(对应about页面)和main/index.js文件(对应首页) pages/main/index con…

c语言:整数与浮点数在内存中的存储方式

整数在内存中的存储&#xff1a; 在计算机内存中&#xff0c;整数通常以二进制形式存储。计算机使用一定数量的比特&#xff08;bit&#xff09;来表示整数&#xff0c;比如32位或64位。在存储整数时&#xff0c;计算机使用补码形式来表示负数&#xff0c;而使用原码形式来表示…

【计算机网络学习之路】URL概念及组成

目录 一. URL是什么 二. URL的组成 三. encode和decode 前言 本系列文章是计算机网络学习的笔记&#xff0c;欢迎大佬们阅读&#xff0c;纠错&#xff0c;分享相关知识。希望可以与你共同进步。 本篇讲解使用浏览器不可或缺的部分——URL 一. URL是什么 域名及DNS 我们在…

43 - 什么是数据的强、弱一致性?

说到一致性&#xff0c;其实在系统的很多地方都存在数据一致性的相关问题。除了在并发编程中保证共享变量数据的一致性之外&#xff0c;还有数据库的 ACID 中的 C&#xff08;Consistency 一致性&#xff09;、分布式系统的 CAP 理论中的 C&#xff08;Consistency 一致性&…

Android studio Load error:undefined path variables

android stuido 报错 Load error&#xff1a;undefined path variables Gson is undefined 处理方法&#xff1a; 点击进行Sync Project with Gradle Files