【问题标题】:how to color point cloud from image pixels?如何从图像像素中为点云着色?
【发布时间】:2015-06-07 02:21:34
【问题描述】:

我正在使用谷歌探戈平板电脑来获取点云数据和 RGB 相机图像。我想创建房间的 3D 扫描。为此,我需要将 2D 图像像素映射到点云点。我将使用大量点云和相应的图像来执行此操作。因此我需要编写一个代码脚本,它有两个输入 1. 点云和 2. 从同一点沿同一方向拍摄的图像,脚本应该输出彩色点云。我应该如何处理这个以及哪些平台将非常易于使用?

【问题讨论】:

    标签: point-cloud-library point-clouds google-project-tango


    【解决方案1】:

    这是将 3D 点 v 映射到相机图像中的 2D 像素空间的数学运算(假设 v 已经包含了外部相机位置和方向,请参阅底部的注释*):

    // Project to tangent space.
    vec2 imageCoords = v.xy/v.z;
    
    // Apply radial distortion.
    float r2 = dot(imageCoords, imageCoords);
    float r4 = r2*r2;
    float r6 = r2*r4;
    imageCoords *= 1.0 + k1*r2 + k2*r4 + k3*r6;
    
    // Map to pixel space.
    vec3 pixelCoords = cameraTransform*vec3(imageCoords, 1);
    

    cameraTransform 是 3x3 矩阵:

    [ fx   0  cx ]
    [  0  fy  cy ]
    [  0   0   1 ]
    

    fxfycxcyk1k2k3 来自TangoCameraIntrinsics

    pixelCoords 被声明为vec3,但实际上是齐次坐标中的 2D。第三个坐标始终为 1,因此在实际应用中可以忽略。

    请注意,如果您想要纹理坐标而不是像素坐标,那只是另一个可以提前预乘到 cameraTransform 上的线性变换(就像任何从上到下与从下到上的扫描线寻址一样) )。

    至于什么“平台”(我松散地解释为“语言”)最简单,native API 似乎是获得相机像素的最直接方法,尽管人们似乎也成功使用了@ 987654323@和Java


    * TangoXYZij 提供的点已经包含深度相机外部变换。从技术上讲,由于当前的开发平板电脑在深度和彩色图像采集之间共享相同的硬件,因此除非您的设备和场景都是静止的,否则您将无法获得完全匹配的彩色图像。幸运的是,在实践中,大多数应用程序可能会假设相机姿势和场景在一帧时间内的变化都不足以显着影响颜色查找。

    【讨论】:

      【解决方案2】:

      这个答案不是原创的,它只是为了方便那些想要@rhashimoto 提供的正确答案的 Unity 用户,为他们制定。我的贡献(希望)是提供代码,通过丢弃所有零结果,将正常的 16 次乘法和 12 次加法(假设 Unity 仅执行 4x4 矩阵)减少到 2 次乘法和 2 次加法。我通过测试跑了不到一百万点,每次检查我的计算是否与基本矩阵计算一致 - 定义为两个结果之间的绝对差异小于机器 epsilon - 我对此感到满意要知道@rhashimoto 可能会出现并在其中戳一个大洞:-)

      如果要来回切换,请记住这是 C#,因此 USEMATRIXMATH 定义必须出现在文件开头。

      鉴于目前只有一个 Tango 设备,并且我假设所有设备的内在函数都是恒定的,我只是将它们作为常量转储,这样

      fx = 1042.73999023438
      fy = 1042.96997070313
      cx = 637.273986816406
      cy = 352.928985595703
      k1 = 0.228532999753952
      k2 = -0.663019001483917
      k3 = 0.642908990383148
      

      是的,它们可以作为常量转储,这将使内容更具可读性,而且 C# 可能足够聪明,可以对其进行优化 - 但是,我在 Agner Fogg 的东西上花费了太多时间,而且总是偏执。

      底部注释掉的代码用于测试差异,如果您愿意的话。如果您想测试结果,您必须取消注释一些其他内容,并注释掉返回值。

      再次感谢@rhashimoto,这比我拥有的要好得多

      我一直忠实于他的逻辑,记住这些是像素坐标,而不是 UV 坐标 - 他是正确的,您可以预乘变换以获得标准化的 UV 值,但既然他已经教过我一次,我会坚持正是他在我摆弄太多之前提出的数学:-)

      static public Vector2 PictureUV(Vector3 tangoDepthPoint)
          {
              Vector2 imageCoords = new Vector2(tangoDepthPoint.x / tangoDepthPoint.z, tangoDepthPoint.y / tangoDepthPoint.z);
              float r2 = Vector2.Dot(imageCoords, imageCoords);
              float r4 = r2*r2;
              float r6 = r2*r4;
              imageCoords *= 1.0f + 0.228532999753952f*r2 + -0.663019001483917f*r4 + 0.642908990383148f*r6;
              Vector3 ic3 = new Vector3(imageCoords.x,imageCoords.y,1);
      
      #if USEMATRIXMATH
              Matrix4x4 cameraTransform  = new Matrix4x4();
              cameraTransform.SetRow(0,new Vector4(1042.73999023438f,0,637.273986816406f,0));
              cameraTransform.SetRow(1, new Vector4(0, 1042.96997070313f, 352.928985595703f, 0));
              cameraTransform.SetRow(2, new Vector4(0, 0, 1, 0));
              cameraTransform.SetRow(3, new Vector4(0, 0, 0, 1));
              Vector3 pixelCoords = cameraTransform * ic3;
              return new Vector2(pixelCoords.x, pixelCoords.y);
      #else
              //float v1 = 1042.73999023438f * imageCoords.x + 637.273986816406f;
              //float v2 = 1042.96997070313f * imageCoords.y + 352.928985595703f;
              //float v3 = 1;
              return new Vector2(1042.73999023438f * imageCoords.x + 637.273986816406f,1042.96997070313f * imageCoords.y + 352.928985595703);
      #endif
      
              //float dx = Math.Abs(v1 - pixelCoords.x);
              //float dy = Math.Abs(v2 - pixelCoords.y);
              //float dz = Math.Abs(v3 - pixelCoords.z);
              //if (dx > float.Epsilon || dy > float.Epsilon || dz > float.Epsilon)
              //    UnityEngine.Debug.Log("Well, that didn't work");
              //return new Vector2(v1, v2);
          }
      

      最后一点,请注意他提供的代码是 GLSL - 如果您只是将它用于漂亮的图片,请使用它 - 这是用于那些实际需要执行额外处理的代码。

      【讨论】:

        猜你喜欢
        • 2021-06-02
        • 1970-01-01
        • 1970-01-01
        • 2013-10-04
        • 2014-02-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-16
        相关资源
        最近更新 更多