Opengl 在pyBullet中模拟具有变形的摄影机

Opengl 在pyBullet中模拟具有变形的摄影机,opengl,camera,camera-calibration,pybullet,Opengl,Camera,Camera Calibration,Pybullet,我正试图根据校准真实相机获得的内在和外在参数,在pyBullet中配置相机 我所拥有的 摄像机是用OpenCV校准的,给了我一个摄像机矩阵 |f_x 0 c_x| | 0 f_y c_y| | 0 0 1 | 和失真系数的向量 (k_1, k_2, p_1, p_2, k_3) (我还有相机的姿势,但这与实际问题无关,所以我把它放在这里。) 我已经做了什么 不幸的是,pyBullet的computeProjectionMatrix功能有点有限。它假设f_x=f_y和c_x,c_

我正试图根据校准真实相机获得的内在和外在参数,在pyBullet中配置相机

我所拥有的 摄像机是用OpenCV校准的,给了我一个摄像机矩阵

|f_x  0  c_x|
| 0  f_y c_y|
| 0   0   1 |
和失真系数的向量

(k_1, k_2, p_1, p_2, k_3)
(我还有相机的姿势,但这与实际问题无关,所以我把它放在这里。)

我已经做了什么 不幸的是,pyBullet的
computeProjectionMatrix
功能有点有限。它假设
f_x=f_y
c_x,c_y
正好位于图像的中心,这两种情况对我的相机都不适用。因此,我自己计算投影矩阵如下(基于):

其中,
w,h
是图像的宽度和高度,
A=(近+远)/(近-远)
B=2*near*far/(近-远)
near
far
定义了包括在图像中的z轴范围(请参见
pybullet.computeProjectionMatrix

还缺少什么(我的实际问题) 上面已经给了我更好的效果,但是渲染的图像仍然与真实图像不完全匹配。我怀疑其中一个原因可能是没有考虑到失真

最后来问我的问题:

如何使用校准真实摄像机得到的参数实现模拟摄像机的失真?


有没有办法把它整合到投影矩阵中?如果没有,还有其他方法吗?

正如评论中指出的那样,非线性失真无法集成到矩阵中。我现在要做的是首先渲染图像而不失真,然后在第二步中使用中的代码扭曲生成的图像

由于失真,图像缩小了一点,因此当保持图像大小固定时,图像边缘会有一些空白区域。为了补偿这一点,我以略大于所需的大小渲染图像,然后在扭曲后进行裁剪。请注意,增大尺寸时,需要相应调整中心点
(c_x,c_y)

要使用一些伪代码进行说明:

所需图像大小=(宽度、高度)
#在每个尺寸上添加10%的填充
填充=所需图像大小*0.1
渲染图像大小=所需图像大小+2*填充
#相应地移动中心点(其他摄像机参数不变)
c_x+=填充[0]
c_y+=填充[1]
#使用问题中描述的投影矩阵渲染图像
图像=在不失真的情况下渲染(投影矩阵、相机姿态)
图像=扭曲图像(图像)
#拆下衬垫
image=image[padding[0]:-padding[0],padding[1]:-padding[1]]
这使得图像与真实相机的图像非常匹配


可以找到完整的实现。

物理系统(Bullet)与渲染属性(相机失真)有什么关系?物理系统只是确定对象在虚拟空间中的位置。“除了物理模拟之外,Pybill还支持渲染,具有CPU渲染器和OpenGL可视化,并支持虚拟现实耳机。”@Nicolas Pybill还提供渲染功能。我用的是pyBullet的
getCameraImage
函数,它将这里提到的投影矩阵作为输入。通常,非线性失真不能用矩阵来完成。啊,对了,我没有考虑非线性。我现在解决了这个问题,首先渲染图像而不失真,然后扭曲结果。我稍后会在回答中写下来。
projection_matrix = [
    [2/w * f_x,  0,  (w - 2c_x)/w,  0],
    [0,  2/h * f_y,  (2c_y - h)/h,  0],
    [0, 0, A, B],
    [0, 0, -1, 0],
]