python - 使用 pyreder/pyglet/openGL 将 3d 顶点映射到像素
问题描述
我正在使用图像实现 3d 点估计的新算法,现在我正在尝试在 3d 虚拟模型上对其进行测试,然后再转向真实对象。
算法输入是最后一次转换为视口大小之前的像素,因此要在渲染图像上测试算法,我需要知道形状中像素的反向转换([0,witdh],[0,height])。
我正在使用 pyrender 库中的透视投影来渲染 3d 网格的 2d 图像,据我所知,这个库使用 OpenGL 方法进行渲染。
示例:我有一个尺寸=(3,1,5), center=(0,0,0) 的盒子网格,并且我有投影和视图矩阵
View Matrix= [[ 0.96592583, -0.0669873 , 0.25 , 3. ],
[ 0. , 0.96592583, 0.25881905, 4. ],
[-0.25881905, -0.25 , 0.9330127 , 10. ],
[ 0. , 0. , 0. , 1. ]]
Projection Matrix= [[ 2.4142135, 0. , 0. , 0. ],
[ 0. , 2.41421356, 0. , 0. ],
[ 0. , 0. , -1.0010005 , -0.10005003],
[ 0. , 0. , -1. , 0. ]]
这是我将 3d 点/顶点映射到像素的计算:
def map_to_pixel(point3d,w,h,projection,view):
p=projection@view@point3d # openGL perspective projection
p=p/p[3] # divide by the w element
p[0]=w/2*p[0]+w/2 # transformation from [-1,1] -> [0,width]
p[1]=h/2*p[1]+h/2 # transformation from [-1,1] -> [0,height]
return p
当 viewport_sizes=(width,height)=(512,512)
结果=
[150.86775635, 4.28475523, 1.00894365, 1. ]
= (151,4)
当 pyrender 对该顶点的实际结果是像素时 ~ (90,342)
如果有人知道 pyrender/OpenGL 幕后的实际过程,或者知道如何正确映射像素,那将非常有帮助。
顺便说一句:当库使用左上映射时,我知道我的函数使用左下映射,但它仍然给出了意外的输出。
解决方案
我弄清楚了计算是如何进行的,我不知道为什么,但是库 pyrender(使用 OpenGL 方法)使用我设置为输入的视图矩阵的逆矩阵。
设置像素的确切功能是:
from numpy.linalg import inv
def map_to_pixel(point3d,w,h,projection,view):
p=projection@inv(view)@point3d.T
p=p/p[3]
p[0]=(w/2*p[0]+w/2) #tranformation from [-1,1] ->[0,width]
p[1]=h-(h/2*p[1]+h/2) #tranformation from [-1,1] ->[0,height] (top-left image)
return p
我已经通过这个函数测试了渲染的图像,所有的顶点都完美地映射到了像素中。
推荐阅读
- php - 传递给 Illuminate\Routing\Middleware\ThrottleRequests::addHeaders() 的参数 1 必须是
- java - Java 8 正则表达式:模式中的捕获组不匹配,但整个模式匹配
- emacs - Emacs:从文件重新加载所有缓冲区
- python - numpy 数组切片索引
- ruby-on-rails - 部署后查找应用路径
- vb.net - 带有 VarChar 对象的 OracleParameter 参数构造函数
- x86 - 如何在 Intel i7 处理器中单独禁用 L2 缓存?
- python - Python如何查看列/行格式的数据
- swift - Swift Package Manager - 对活动分支的依赖不会拉新提交
- r - 当某些值故意未知时,如何在逻辑回归中编码预测变量