【问题标题】:Getting world coordinates from OpenGL depth buffer从 OpenGL 深度缓冲区获取世界坐标
【发布时间】:2020-03-26 11:21:36
【问题描述】:

我正在使用 pyBullet,它是 bullet3 物理引擎的 python 包装器,我需要从虚拟相机创建点云。
该引擎使用基本的 OpenGL 渲染器,我能够从 OpenGL 深度缓冲区获取值

img = p.getCameraImage(imgW, imgH, renderer=p.ER_BULLET_HARDWARE_OPENGL)
rgbBuffer = img[2]
depthBuffer = img[3]

现在我有了带有深度值的 width*height 数组。我怎样才能从中获得世界坐标?我尝试使用点(宽度、高度、深度缓冲区(宽度、高度))保存 .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")

【问题讨论】:

  • 使用PyGLM。 (glm.unProject(...))
  • 不知何故我错过了,明天试试,然后我会更新/关闭这个问题,谢谢
  • 似乎 PyGLM unProject 工作,但我不确定我是否正确获取深度值,我更新了问题
  • 好的,所以我正确地获取了这些值,问题在于巨大的近/远值,看起来他们需要非常紧密地“拥抱”对象以获得正确的深度值
  • 我想做和你一样的事情,从 pybullet 合成相机获取点云。我不熟悉pcl 也不熟悉opengl。你能分享一个最小的工作示例吗?或者澄清一下你如何选择步长、模型是projGLM=pybullet.computeProjectionMatrixFOV(..)viewport=pybullet.computeViewMatrix(..)

标签: python c++ opengl depth-buffer


【解决方案1】:

这是我的解决方案。我们只需要知道视图矩阵和投影矩阵是如何工作的。 pybullet中有computeProjectionMatrixFOV和computeViewMatrix函数。 http://www.songho.ca/opengl/gl_projectionmatrix.htmlhttp://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]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-05
    相关资源
    最近更新 更多