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

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比上这个比例得到正交投影下的深度值。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

protobuf简单使用(二)

介绍 上一节中&#xff0c;我们介绍了protobuf&#xff0c;简单来说&#xff0c;它是一种消息数据格式&#xff0c;其作用类似于json&#xff0c;但是比json的使用效率要高。 除此以外&#xff0c;我们介绍了protobuf的简单使用&#xff0c;也就是如何可以像使用json一样&…

AI游戏初创公司“奇酷网络”,获得500万元天使投资

发布 | 大力财经 2024年新春伊始的2月25日&#xff0c;国内首家“AI游戏”应用公司“奇酷网络”正式对外宣布&#xff1a;以3,000万元人民币的估值&#xff0c;成功获得500万元人民币的融资&#xff1b;资金来源于一名百度高层和一位知名的天使投资人。 据悉&#xff0c;“奇…

进程 2月24日学习笔记

1.进程: 程序&#xff1a;存放在外存中的一段数据组成的文件 进程&#xff1a;是一个程序动态执行的过程,包括进程的创建、进程的调度、进程的消亡 2.进程相关命令: 1.top 动态查看当前系统中的所有进程信息&#xff08;根据CPU占用率排序&#xff09; PID:唯一识…

namecheap域名如何购买?通过支付宝(详细图文教程)

引言 在完成博客搭建的时候&#xff0c;我们可能需要一个好的域名&#xff0c;自己看起来才会舒服点&#xff0c;同时也可以通过google或者百度等方式搜索到自己博客。 经过实验发现&#xff0c;一个好的后缀名会增强google和百度的搜索seo&#xff0c;增加自己博客的流量。 …

平头哥IP核C906的JTAG调试器DIY教程(一)

背景 最近买了一块基于平头哥C906核&#xff0c;SOC为全志的D1s&#xff0c;的核心板&#xff0c;手工焊接在白嫖的底板上&#xff08;此处感谢百问网老师的友情支持&#xff0c;手动狗头&#xff09;。在焊接完成后&#xff0c;进行点亮跑程序的时候&#xff0c;发现没有优雅…

C++ //练习 8.13 重写本节的电话号码程序,从一个命名文件而非cin读取数据。

C Primer&#xff08;第5版&#xff09; 练习 8.13 练习 8.13 重写本节的电话号码程序&#xff0c;从一个命名文件而非cin读取数据。 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#xff09; 工具&#xff1a;vim 代码块 /***************************************…

关于设备连接有人云的使用及modbus rtu协议,服务器端TCP调试设置

有人云调试 调试过程问题1. 关于modbus rtu协议,实质上有三种modbus基本原理modbus 格式2. 关于modbus crc16通信校验3. 关于在ubuntu阿里云服务器端,监听网络数据之调试mNetAssist4. 使用有人FAE传给的设置软件问题???之前的一个项目,再拿出来回顾下。 调试过程 先 要在有…

web安全学习笔记【16】——信息打点(6)

信息打点-语言框架&开发组件&FastJson&Shiro&Log4j&SpringBoot等[1] #知识点&#xff1a; 1、业务资产-应用类型分类 2、Web单域名获取-接口查询 3、Web子域名获取-解析枚举 4、Web架构资产-平台指纹识别 ------------------------------------ 1、开源-C…

特征选择|一种提升预测模型性能的方法(原理及其优化实现,Matlab)

文章来源于我的个人公众号&#xff1a;KAU的云实验台&#xff0c;主要更新智能优化算法的原理、应用、改进 如今&#xff0c;生成的数据集呈指数级增长&#xff0c;这将产生具有大量特征和样本的数据集&#xff0c;而显然&#xff0c;某些特征是不相关/冗余的&#xff0c;它们…

奇异递归模板模式应用6-类模板enable_shared_from_this

异步编程中存在一种场景&#xff0c;需要在类中将该类的对象注册到某个回调类或函数中&#xff0c;不能简单地将this传递给回调类中&#xff0c;很可能因为回调时该对象不存在而导致野指针访问&#xff08;也有可能在析构函数解注册时被回调&#xff0c;造成对象不完整&#xf…

【C语言基础】:操作符详解(一)

文章目录 操作符详解1. 操作符的分类2. 二进制和进制转换2.1 什么是二进制、八进制、十进制、十六进制2.1.1 二进制和进制转换2.1.2 二进制转十进制2.2.3 二进制转八进制2.2.4 二进制转十六进制 3. 源码、反码、补码4. 移位操作符4.1 左移操作符4.2 右移操作符 5. 位操作符&…

IT廉连看——C语言——函数

IT廉连看——C语言——函数 一、函数是什么&#xff1f; 数学中我们常见到函数的概念。但是你了解C语言中的函数吗&#xff1f; 维基百科中对函数的定义&#xff1a;子程序 在计算机科学中&#xff0c;子程序&#xff08;英语&#xff1a;Subroutine, procedure, function, …

【Java】java异常处理机制(实验五)

目录 一、实验目的 二、实验内容 三、实验小结 一、实验目的 1、理解java的异常处理机制 2、掌握try catch结构和thow和thows关键字的用法 二、实验内容 1、编写一个程序&#xff0c;输入某个班某门课程成绩&#xff0c;统计及格人数、不及格人数及课程平均分。设计一个异…

H12-821_59

59.R1、R2、R3、R4运行IS-IS,它们接口的DIS Priority如图所示,假如设备同时启动,则()被选举为D1S.(请填写设备名称、例如R1) 答案&#xff1a;R4 注释&#xff1a; IS-IS中DIS的选举支持抢占。 假设题目说R4最后启动&#xff0c;问谁被选举为DIS&#xff0c;答案仍然是R4。

【嵌入式实践】【芝麻】【设计篇-1】从0到1给电动车添加指纹锁:项目设计思路

0. 前言 该项目是基于stm32F103和指纹模块做了一个通过指纹锁控制电动车的小工具。支持添加指纹、删除指纹&#xff0c;电动车进入P档等待时计时&#xff0c;计时超过5min则自动锁车&#xff0c;计时过程中按刹车可中断P档状态&#xff0c;同时中断锁车计时。改项目我称之为“芝…

NVIDIA Workbench 安装使用图文教程

NVIDIA Workbench 安装使用教程 文章目录 NVIDIA Workbench 安装使用教程1.安装1.1 下载软件1.2 安装软件 2.使用NVIDIA Workbench2.1 创建一个新项目 3.额外提示3.1 当我们没有停止直接关闭或者直接重启电脑后, 再打开我们已经创立的项目的时候可能会出现创建失败等错误信息.3…

Java核心-核心类与API(3)

话接上回&#xff0c;继续核心类与API的学习&#xff0c;这次介绍一下枚举类以及与系统、交互有关的类&#xff0c;需要了解并能使用即可。 一、枚举类 1、概述 枚举也称穷举&#xff0c;简单理解就是把所有可能一一列举出来&#xff08;穷尽所有可能&#xff09;。枚举是一…

申请攻读博士学位研究生相关模板资料(包括专家推荐信、学术简历、研究计划及范文、回复导师邮件)

申请攻读博士学位研究生相关模板资料&#xff08;包括专家推荐信、学术简历、研究计划及范文、回复导师邮件&#xff09; 博士是对攻读博士学位的研究生的称呼&#xff0c;同样也可用来称呼已获得博士学位的人员。 主要通过拥有博士点的普通高等学校和拥有博士研究生培养资格…

[SUCTF 2019]EasySQL1 题目分析与详解

一、题目介绍 1、题目来源&#xff1a; BUUCTF网站&#xff0c;网址&#xff1a;https://buuoj.cn/challenges 2、题目描述&#xff1a; 通过以上信息&#xff0c;拿到flag。 二、解题思路 首先打开靶机&#xff0c;尝试输入1查看回显&#xff0c;回显如图所示&#xff1a;…

图像读取裁剪与人脸识别

图像读取 Image read ⇒ \Rightarrow ⇒ torchvision.datasets from torchvision import datasets dataset datasets.ImageFolder(data_dir, transformtransforms.Resize((512, 512)))Return value illustration dataset[0][0]是PIL.Image objects&#xff0c;这利用IPyth…