pythonJax小记(五):python: 使用Jax深度图像(正交投影和透视投影之间的转换)(持续更新,评论区可以补充)

news2024/9/22 6:40:20

python: 使用Jax深度图像(正交投影和透视投影之间的转换)

  • 前言
  • 问题描述
    • 1. 透视投影
    • 2. 正交投影
  • 直接上代码
  • 解释
    • 1. `compute_projection_parameters` 函数
      • a. 参数解释
      • b. 函数计算
    • 2. `ortho_to_persp` 函数
      • a. 计算投影参数:
      • b. 生成像素坐标网格:
      • c. 计算透视深度值:
    • 3. `persp_to_ortho` 函数
      • a. 计算投影参数:
      • b. 生成像素坐标网格:
      • c. 计算正交深度值:


前言

自用,刚开始接触可能顺序会比较乱。

问题描述

目前我知道的(欢迎评论区补充)照相机生成的深度图像有两种方法(如下图):
在这里插入图片描述

在透视投影中,物体的大小和形状会根据其距离观察者的远近而发生变化,这是因为透视投影模拟了人眼或相机镜头观察世界的方式,远处的物体看起来更小,近处的物体看起来更大。而在正交投影中,物体的大小和形状与其距离无关,提供了一种更抽象但尺寸精确的视图。


现在假设照相机正在观察一个又大平面又平整的物体:

1. 透视投影

在透视投影中,物体的大小会随着距离相机的远近而变化,即距离相机越远,物体在图像上看起来越小。这种投影方式能够模拟人眼观察世界的方式,因此在大多数三维图形应用中,透视投影是用来创建更加真实感的视觉效果。

在这里插入图片描述
虚线部分是照相机到照射物体的距离,从左到右依次叫做depth1pdepth2pdepth3pdepth4pdepth5p;它们之间的关系应该是:

depth1p = depth5p > depth2p = depth4p > depth3p

2. 正交投影

在正交投影中,所有的投影线都是平行的。这意味着无论物体距离相机有多远,它的大小在投影图上都保持不变。正交投影常用于工程图纸和某些类型的艺术作品,因为它不会因为透视而扭曲物体的比例。

在这里插入图片描述

虚线部分是照相机到照射物体的距离,从左到右依次叫做depth1odepth2odepth3odepth4odepth5o;它们之间的关系应该是:

depth1o = depth2o = depth3o = depth4o = depth5o = depth3p(透视投影中最中心点的距离)


我想做的是depth1p <——>depth1odepth2p <——>depth2odepth3p <——>depth3o(数值相等不变)depth4p <——>depth4odepth5p <——>depth5o之间的互相转化。

直接上代码

from jax import random
import jax.numpy as jnp
from jax import jit
 
def compute_projection_parameters(fov, resolution):
    """计算透视投影所需的参数"""
    h, w = resolution
    f = 0.5 * w / jnp.tan(fov * 0.5)  # 假设fov是水平的
    # f = 0.5 * h / jnp.tan(fov * 0.5)  # 假设fov是竖直的
    cx, cy = w * 0.5, h * 0.5
    return f, cx, cy
 
@jit
def ortho_to_persp(depth_ortho, fov, resolution):
    """正交投影深度图转换为透视投影深度图"""
    f, cx, cy = compute_projection_parameters(fov, resolution)
    y, x = jnp.indices(depth_ortho.shape)
    z = depth_ortho
    x_persp = (x - cx) * z / f
    y_persp = (y - cy) * z / f
    depth_persp = jnp.sqrt(x_persp**2 + y_persp**2 + z**2)
    return depth_persp
 
@jit
def persp_to_ortho(depth_persp, fov, resolution):     
    """透视投影深度图转换为正交投影深度图"""    
    f, cx, cy = compute_projection_parameters(fov, resolution)     
    y, x = jnp.indices(depth_persp.shape)     
    # 逆向透视效果调整深度值    
    z = depth_persp     
    # 假设所有点在深度图中直接面向相机,计算透视图中的实际深度    
    depth_ortho = z / jnp.sqrt(((x - cx) / f)**2 + ((y - cy) / f)**2 + 1)     
    return depth_ortho
 
# 创建随机键
key = random.PRNGKey(0)
 
# 示例参数
fov = jnp.radians(58.0)  # 58度的视场
resolution = (555, 555)  # 深度图的分辨率
 
# 使用JAX的随机数生成函数来创建假设的深度图
depth_ortho = random.uniform(key, resolution)
depth_persp = random.uniform(key, resolution)
 
# 执行转换
depth_persp_converted = ortho_to_persp(depth_ortho, fov, resolution)
depth_ortho_converted = persp_to_ortho(depth_persp, fov, resolution)
 
print("depth_ortho[277][277]:")
print(depth_ortho[277][277])
print("depth_ortho:")
print(depth_ortho)
print("depth_persp_converted[277][277]:")
print(depth_persp_converted[277][277])
print("depth_persp_converted:")
print(depth_persp_converted)
 
print("depth_persp[277][277]:")
print(depth_persp[277][277])
print("depth_persp:")
print(depth_persp)
print("depth_ortho_converted[277][277]:")
print(depth_ortho_converted[277][277])
print("depth_ortho_converted:")
print(depth_ortho_converted)

输出:

depth_ortho[277][277]:
0.17295325
depth_ortho:
[[0.63084936 0.12969959 0.13633609 ... 0.5946181  0.59479845 0.4128834 ]
[0.29537833 0.3383578  0.5370909  ... 0.53237784 0.90082276 0.5761422 ]
[0.32716596 0.12419498 0.6801119  ... 0.55152595 0.48904026 0.8486302 ]
...
[0.30268252 0.2692206  0.73559785 ... 0.210132   0.06937218 0.61453307]
[0.30586207 0.18751395 0.5052029  ... 0.364128   0.3952657  0.09071398]
[0.64812434 0.6937938  0.5302503  ... 0.21545482 0.274127   0.7742363 ]]
depth_persp_converted[277][277]:
0.17295341
depth_persp_converted:
[[0.8015802  0.16468817 0.17299668 ... 0.7539958  0.75473905 0.5242654 ]
[0.37506145 0.4293407  0.68104595 ... 0.6746088  1.142268   0.73106426]
[0.41514048 0.15748264 0.8618096  ... 0.6983931  0.61969155 1.0760863 ]
...
[0.38381162 0.34114605 0.93148196 ... 0.26590642 0.08784546 0.7787128 ]
[0.388108   0.23777282 0.6401722  ... 0.46109253 0.5008643  0.11502781]
[0.82296646 0.88035184 0.6723719  ... 0.2730161  0.34760055 0.98242503]]
depth_persp[277][277]:
0.17295325
depth_persp:
[[0.63084936 0.12969959 0.13633609 ... 0.5946181  0.59479845 0.4128834 ]
[0.29537833 0.3383578  0.5370909  ... 0.53237784 0.90082276 0.5761422 ]
[0.32716596 0.12419498 0.6801119  ... 0.55152595 0.48904026 0.8486302 ]
...
[0.30268252 0.2692206  0.73559785 ... 0.210132   0.06937218 0.61453307]
[0.30586207 0.18751395 0.5052029  ... 0.364128   0.3952657  0.09071398]
[0.64812434 0.6937938  0.5302503  ... 0.21545482 0.274127   0.7742363 ]]
depth_ortho_converted[277][277]:
0.17295307
depth_ortho_converted:
[[0.49648297 0.10214445 0.10744441 ... 0.46892923 0.4687517  0.32516485]
[0.23262416 0.26665536 0.4235641  ... 0.42013407 0.7104127  0.45405012]
[0.25783455 0.09794345 0.53672194 ... 0.4355439  0.3859345  0.6692523 ]
...
[0.23870227 0.21245952 0.58090675 ... 0.1660564  0.05478369 0.4849681 ]
[0.24104528 0.14787847 0.39868954 ... 0.2875544  0.31193072 0.07153945]
[0.510428   0.5467698  0.41816944 ... 0.17002945 0.21618383 0.6101655 ]]

解释

1. compute_projection_parameters 函数

compute_projection_parameters函数的目的是根据给定的视场角(Field of View, FOV)和图像分辨率来计算透视投影所需的参数。这些参数主要是焦距(f)和图像的中心点坐标(cx,cy)。这些参数对于将三维空间中的点投影到二维图像平面上,以及进行透视投影与正交投影之间的转换非常重要。

a. 参数解释

  • fov:视场角,表示相机视角的宽度。在三维图形和计算机视觉中,FOV是一个关键参数,因为它定义了可见场景的范围。视场角越大,相机能够看到的场景就越宽广。

  • resolution:图像分辨率,通常以像素为单位表示图像的宽度和高度。在这个上下文中,分辨率告诉我们图像平面的尺寸,这对于计算图像中点的位置非常重要。

b. 函数计算

焦距(f) 的计算基于视场角(FOV)和图像宽度。焦距是一个表示相机与图像平面之间距离的参数,它影响着场景在图像平面上的投影方式。在这个函数中,焦距是通过下面的公式计算的:
f = 0.5 × w i d t h / t a n ( F O V / 2 ) f = 0.5 × width / tan(FOV/2) f=0.5×width/tan(FOV/2)
这个公式利用了简单的三角形几何关系,其中假设图像平面的宽度直接对应于视场角的跨度。通过这个公式,我们可以根据视场角和图像宽度计算出焦距。

图像中心点坐标(cx,cy) 的计算很直接:它们是图像宽度和高度的一半。图像中心点是图像平面上的一个关键参考点,因为它通常被用作投影和反投影过程中的原点。

2. ortho_to_persp 函数

ortho_to_persp函数的目的是将正交投影的深度图转换为透视投影的深度图。这个转换过程需要根据视场角(FOV)、图像分辨率以及焦距(f)和图像中心(cx, cy)这些计算出的投影参数来完成。

a. 计算投影参数:

首先,利用compute_projection_parameters函数根据FOV和图像分辨率计算出焦距(f)和图像中心(cx, cy)。

b. 生成像素坐标网格:

使用jnp.indices生成一个与输入深度图相同尺寸的像素坐标网格。这个网格包含了每个像素点的行(y)和列(x)坐标。

c. 计算透视深度值:

  • 通过(x - cx)和(y - cy)计算每个像素点相对于图像中心的偏移。
  • 使用偏移值和深度值(z)以及焦距(f)来调整每个像素的深度值。这里,深度值(z)乘以偏移量除以焦距,计算出在透视视图下像素的“新”位置。
  • 最后,利用jnp.sqrt(x_persp**2 + y_persp**2 + z**2)计算每个像素点在透视投影中的实际深度值。这个步骤通过考虑像素在透视投影中的三维空间位置(考虑深度z)来调整深度图,使得远处的物体看起来更小,近处的物体看起来更大。

3. persp_to_ortho 函数

persp_to_ortho函数的目的是将透视投影的深度图转换为正交投影的深度图。这个过程需要逆转透视投影中深度与像素位置关系的影响,恢复到一个正交视图中,其中物体的大小不会因为它们距离相机的远近而改变。

a. 计算投影参数:

首先,利用compute_projection_parameters函数根据FOV和图像分辨率计算出焦距(f)和图像中心(cx, cy)。

b. 生成像素坐标网格:

使用jnp.indices生成一个与输入深度图相同尺寸的像素坐标网格。这个网格包含了每个像素点的行(y)和列(x)坐标。

c. 计算正交深度值:

在公式depth_ortho = z / jnp.sqrt(((x - cx) / f)**2 + ((y - cy) / f)**2 + 1)中:

  • (x - cx)(y - cy)计算的是像素点相对于图像中心的位置差异。
  • / f是根据焦距来缩放这些差异,使其与实际的视角对应起来。
  • ((x - cx) / f)**2 + ((y - cy) / f)**2计算的是像素点从图像中心到该点的距离的平方,这个距离是在图像平面上的。
  • +1实际上是在计算直角三角形的斜边长度时必须添加的项。想象一个直角三角形,其中(x - cx) / f(y - cy) / f代表两个直角边上的长度,而我们想要找的是斜边的长度,即从相机到像素点的实际距离。在这种情况下,+1代表了这个直角三角形斜边计算中的垂直边(即相机到图像平面的距离),它是一个常数,因为在透视投影中,所有的像素点都是从相同的焦点投影到图像平面上的。+1在这里同时确保了对于所有像素,即使在图像中心(x=cx,y=cy)也能正确处理深度值。
  • 最后用已知的深度z比上这个比例得到正交投影下的深度值。

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

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

相关文章

《Python 语音转换简易速速上手小册》第10章 未来趋势和发展方向(2024 最新版)

文章目录 10.1 语音技术的未来展望10.1.1 基础知识10.1.2 主要案例:语音驱动的虚拟助理案例介绍案例 Demo案例分析10.1.3 扩展案例 1:情感敏感的客服机器人案例介绍案例 Demo案例分析10.1.4 扩展案例 2:多模态智能会议系统案例介绍案例 Demo

Linux-用户和权限(黑马学习笔记)

认识root用户 root用户&#xff08;超级管理员&#xff09; 无论是Windows、MacOS、Linux均采用多用户的管理模式进行权限管理。 ● 在Linux系统中&#xff0c;拥有最大权限的账户名为&#xff1a;root&#xff08;超级管理员&#xff09; ● 而在前期&#xff0c;我们一直…

SpringBoot 3 新特性

目录 1. GraalVM2. 支持虚拟线程3. HTTP Interface 1. GraalVM 使用GraalVM将SpringBoot应用程序编译成本地可执行的镜像文件&#xff0c;可以显著提升启动速度、峰值性能以及减少内存应用。传统的应用都是编译成字节码&#xff0c;然后通过JVM解释并最终编译成机器码来运行&a…

报错:org.springframework.jdbc.BadSqlGrammarException:

//报错 2024-02-24 19:44:10.814 ERROR 6184 --- [nio-9090-exec-5] c.e.exception.GlobalExceptionHandler : 异常信息&#xff1a; org.springframework.jdbc.BadSqlGrammarException: GPT&#xff1a; 根据异常信息&#xff0c;这是一个Spring框架抛出的BadSqlGrammar…

金航标电子位于广西柳州鹿寨县天线生产基地于大年正月初九开工了

金航标电子位于广西柳州鹿寨县天线生产基地于大年正月初九开工了&#xff01;&#xff01;&#xff01;金航标kinghelm&#xff08;www.kinghelm.com.cn&#xff09;总部位于中国深圳市&#xff0c;兼顾技术、成本、管理、效率和可持续发展。东莞塘厦实验室全电波暗室、网络分析…

NXP实战笔记(九):S32K3xx基于RTD-SDK在S32DS上配置 CRCIRQPower

目录 1、CRC概述 1.1、CRC配置 1.2、代码示例 2、INTCTRL 3、Power 1、CRC概述 硬件CRC产生16或者32bit的&#xff0c;S32K3提供了可编程多项式与其他参数需求。 CRC图示如下 1.1、CRC配置 暂时DMA不怎么会用&#xff0c;所以没有启用DMA CRC的选择 这点需要十分注意&…

芯科科技与Arduino携手推动Matter普及化

双方的合作可助力开发人员在两分钟内将新开发板配置入网 致力于以安全、智能无线连接技术&#xff0c;建立更互联世界的全球领导厂商Silicon Labs&#xff08;亦称“芯科科技”&#xff0c;NASDAQ&#xff1a;SLAB&#xff09;日前宣布&#xff0c;公司与开源硬件和软件领域的…

使用Lombok @Data 出现java: 找不到符号 的问题

第一种&#xff1a;pom依赖最好如下方式 <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>RELEASE</version><scope>compile</scope> </dependency>第二种&#xff1…

Unity Shader ASE基础效果思路与代码(二):边缘光、扰动火焰

Unity Shader ASE基础效果思路与代码(二)&#xff1a;边缘光、扰动火焰 文章目录 Unity Shader ASE基础效果思路与代码(二)&#xff1a;边缘光、扰动火焰边缘光效果展示&#xff1a;代码与思路&#xff1a; 扰动火焰效果展示&#xff1a;代码与思路&#xff1a; 边缘光 效果展…

力扣随笔之颜色分类(中等75)

思路&#xff1a;定义两个指针划分left&#xff0c;right划分三个区域left左边是红色区域&#xff0c;right右边是蓝色区域&#xff0c;left和right之间是白色区域&#xff1b;定义一个遍历指针遍历整个数组&#xff0c;遇到红色与left所指位置数字交换&#xff0c;并将left自加…

【雷达指标】MTI/MTD性能

目录 一、MTI/MTD性能的指标描述1.1 杂波衰减和对消比1.2 改善因子1.3 杂波中的可见度 二、MATLAB仿真参考文献 雷达通常使用MTI/MTD来进行杂波抑制&#xff0c;采用杂波衰减、对消比、改善因子、杂波中的可见度来描述其性能。 一、MTI/MTD性能的指标描述 1.1 杂波衰减和对消比…

C#学习总结

1、访问权限 方法默认访问修饰符&#xff1a;private 类默认访问修饰符&#xff1a;internal 类的成员默认访问修饰符&#xff1a;private 2、UserControl的使用 首先添加用户控件 使用时一种是通过代码添加&#xff0c;一种是通过拖动组件到xaml中

前端导出下载文件后提示无法打开文件

问题 项目中的导出文件功能&#xff0c;导出下载后的文件打开提示如下&#xff1a; 原因 对返回的响应数据进行打印&#xff0c;发现响应数据为字符串格式&#xff0c;前期规划的后端返回数据应该 blob 对象的。后经排查后发现是请求头缺少了响应数据格式的配置&#xff0c;应…

数据同步MySQL -> Elasticsearch

大家好我是苏麟,今天聊聊数据同步 . 数据同步 一般情况下&#xff0c;如果做查询搜索功能&#xff0c;使用 ES 来模糊搜索&#xff0c;但是数据是存放在数据库 MySQL 里的&#xff0c;所以说我们需要把 MySQL 中的数据和 ES 进行同步&#xff0c;保证数据一致(以 MySQL 为主)…

力扣645. 错误的集合(排序,哈希表)

Problem: 645. 错误的集合 文章目录 题目描述思路复杂度Code 题目描述 思路 1.排序 1.对nums数组按从小到大的顺序排序; 2.遍历数组时若判断两个相邻的元素则找到重复元素&#xff1b; 3.记录一个整形变量prev一次置换当前位置元素并与其作差&#xff0c;若差等于2着说明缺失的…

【vue】如何打开别人编译后的vue项目

文件结构如下&#xff0c;编译后的文件放在dist中。 dist的文件结构大约如下&#xff0c;文件名称随项目 1.新建app.js文件 const express require(express);const app express();const port 8080;app.use(express.static(dist));app.listen(port, () > console.log); …

Bluesky数据采集框架-1

Bluesky是一个用于实验控制和科学数据和元数据采集的库。它强调以下特点&#xff1a; 1、实时&#xff0c;流式数据&#xff1a;可用于嵌入可视化和处理。 2、丰富元数据&#xff1a;获取和组织来方便复制性和可检索性。 3、实验通用性&#xff1a;对完全不同的硬件无缝地重…

c#高级——插件开发

案例&#xff1a;WinForm计算器插件开发 1.建立插件库&#xff0c;设置各种自己所需的插件组件 如下图所示&#xff1a;进行了计算器的加减法插件计算组件 Calculator_DLL为总插件父类 Calculator_DLL_ADD 为插件子类的控件对象 Calculator_DLL_Sub Calculator_DLL_Factory 为…

JavaSec 基础之 XXE

文章目录 XMLReaderSAXReaderSAXBuilderDocumentBuilderUnmarshaller**SAXParserFactory**XMLReaderFactoryDigester总结 XMLReader public String XMLReader(RequestBody String content) {try {XMLReader xmlReader XMLReaderFactory.createXMLReader();// 修复&#xff1a…

ESP8266智能家居(4)——开发APP基础篇

1.前期准备 安装好Android studio 开发环境 准备一台完好的安卓手机 手机要处于开发者模式 设置 --->关于手机---> 一直点击版本号 &#xff08;不同手机进入开发者模式的步骤可能不太一样&#xff09; 进入开发者模式后&#xff0c;找到辅助功能&#xff0c;打开开…