首页 > 解决方案 > Hololens - Unity c#:将点集从相机计划投影到统一坐标系?

问题描述

我目前正在为 Hololens 开发一个应用程序,该应用程序允许用户从不同的角度拍摄场景的多个帧(例如一个盒子)并将它们转换为代表对象的点集。获取每帧的深度位图效果很好,但是当我想将点集转换为 Unity 坐标系时,我的问题就来了……

每次用户拍摄时,我都会得到深度位图、框架坐标系、投影变换矩阵、摄像机视图变换矩阵以及从摄像机坐标系到统一坐标系的变换矩阵。

// Get the spatial coordinates system from the mediaFrameReferecence
var coordinateSystem = mediaFrameReference.CoordinateSystem;

// Get the projection Transform matrix
object n;
mediaFrameReference.Properties.TryGetValue(projectionTransformGuid, out n);

// ByteArrayMatrix(byte[]) is a method a developped which works fine
projectionTransformMatrix = ByteArrayToMatrix(n as byte[]);

/// HERE n is a byte[48] but I'm expecting byte[64] like m below

// Get the view transform then invert it
byte[] m = mediaFrameReference.Properties[viewTransformGuid] as byte[];
cameraViewTransformMatrix = ConvertByteArrayToMatrix4x4(m);

// Get the camera to world transfrom
cameraToWorldTransformMatrix = (System.Numerics.Matrix4x4)coordinateSystem.TryGetTransformTo(rootSpatialCoordinateSystem);

// ... Doing Some stuff ...

在有了这些之后,对于每个像素,我将我的点保存到一个 .obj 文件中,格式为:v x y z r g b在下面的 SavePoint 方法中:

private static Vector2 PixelToWorldCoordonate(int u, int v)
{
    float x = a * (u - width / 2) + b * (v - height / 2);
    float y = c * (u - width / 2) + d * (v - height / 2);
    return new Vector2(x, y);
}

/// This method is to project a pixel to unity coordinate system
private String SavePoint((int x, int y, byte* inputRowBytes,
                          float depthScale, float minReliableDepth, float maxReliableDepth,
                          System.Numerics.Matrix4x4 cameraViewTransformMatrix, 
                          System.Numerics.Matrix4x4 cameraToWorldTransformMatrix, 
                          double r, double g, double b) 
{
    if (depth < 2)
    {
        string mes = "";
        Vector2 realPoint = PixelToWorldCoordonate(x, y);
        System.Numerics.Vector3 point3d = new System.Numerics.Vector3(realPoint.x, realPoint.y, 1.0f);
        point3d *= depth;
        System.Numerics.Vector3 position = System.Numerics.Vector3.Transform(point3d, cameraViewTransformMatrix);

        // Saving the point's position and color
        return "v " + position.X.ToString() + " " + position.Y.ToString() + " " + position.Z.ToString()
            + " " + r.ToString() + " " + g.ToString() + " " + b.ToString() + Environment.NewLine;
    }
}

使用我的实际代码,我得到了每个捕获的连贯点集,但问题是: 当进行多次捕获时,点集似乎在不同的计划中(见下面的截图):

在 meshlab 中设置的点

在这张图片中,红色部分是为第一次拍摄设置的点,绿色部分是在右侧移动 50 厘米后为第二次拍摄设置的点。圆圈区域是我在拍照时正在查看的对象。我希望这个物体在我四处走动时会留在同一个地方,但毕竟我可能错了......

如果有人对我可能遗漏的东西有一点想法

标签: c#unity3dpoint-cloudshololens

解决方案


除了 Herdnando 已经说过的,问题可能是 cameraViewTransformMatrix 只在相机和点之间转换。所以当相机移动时,参考坐标系随之移动,点云不对齐。您还必须应用您的 cameraToWorldTransformMatrix 将所有内容都放入您的根坐标系。


推荐阅读