Opengl 在pyBullet中模拟具有变形的摄影机
我正试图根据校准真实相机获得的内在和外在参数,在pyBullet中配置相机 我所拥有的 摄像机是用OpenCV校准的,给了我一个摄像机矩阵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_
|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],
]