我正在使用pyBullet,这是bullet3物理引擎的python包装器,我需要从虚拟相机创建点云。
该引擎使用基本的OpenGL渲染器,我能够从OpenGL深度缓冲区中获取值
img = p.getCameraImage(imgW, imgH, renderer=p.ER_BULLET_HARDWARE_OPENGL)
rgbBuffer = img[2]
depthBuffer = img[3]
现在,我有了带有深度值的width * height数组。如何从中获取世界坐标?我试图用点(宽度,高度,depthBuffer(宽度,高度))保存.ply点云,但这不会创建看起来像场景中对象的点云。
我还试图用近距离平面校正深度:
depthImg = float(depthBuffer[h, w])
far = 1000.
near = 0.01
depth = far * near / (far - (far - near) * depthImg)
但是这样做的结果也是一些怪异的点云。如何从深度缓冲区中的数据创建逼真的点云?甚至有可能吗?
我在c ++中做了类似的事情,但在那里我使用了glm :: unproject
for (size_t i = 0; i < height; i = i = i+density) {
for (size_t j = 0; j < width; j = j = j+density) {
glm::vec3 win(i, j, depth);
glm::vec4 position(glm::unProject(win, identity, projection, viewport), 0.0);
编辑:
基于Rabbid76的答案,我使用了有效的PyGLM,现在我可以获取XYZ世界坐标来创建点云,但是点云中的深度值看起来失真了,我是否可以正确地从深度缓冲区获取深度?
for h in range(0, imgH, stepX):
for w in range(0, imgW, stepY):
depthImg = float(np.array(depthBuffer)[h, w])
far = 1000.
near = 0.01
depth = far * near / (far - (far - near) * depthImg)
win = glm.vec3(h, w, depthBuffer[h][w])
position = glm.unProject(win, model, projGLM, viewport)
f.write(str(position[0]) + " " + str(position[1]) + " " + str(depth) + "\n")
答案 0 :(得分:1)
这是我的解决方案。我们只需要知道视图矩阵和投影矩阵是如何工作的。 pybullet中有computeProjectionMatrixFOV和computeViewMatrix函数。 http://www.songho.ca/opengl/gl_projectionmatrix.html和http://ksimek.github.io/2012/08/22/extrinsic/ 一句话,point_in_world = inv(projection_matrix * viewMatrix)* NDC_pos
glm.unProject是另一个解决方案
stepX = 10
stepY = 10
pointCloud = np.empty([np.int(img_height/stepY), np.int(img_width/stepX), 4])
projectionMatrix = np.asarray(projection_matrix).reshape([4,4],order='F')
viewMatrix = np.asarray(view_matrix).reshape([4,4],order='F')
tran_pix_world = np.linalg.inv(np.matmul(projectionMatrix, viewMatrix))
for h in range(0, img_height, stepY):
for w in range(0, img_width, stepX):
x = (2*w - img_width)/img_width
y = -(2*h - img_height)/img_height # be careful! deepth and its corresponding position
z = 2*depth_np_arr[h,w] - 1
pixPos = np.asarray([x, y, z, 1])
position = np.matmul(tran_pix_world, pixPos)
pointCloud[np.int(h/stepY),np.int(w/stepX),:] = position / position[3]