【问题标题】:Generate and export point cloud from Project Tango从 Project Tango 生成和导出点云
【发布时间】:2016-07-07 10:55:30
【问题描述】:

经过几周的等待,我终于有了我的 Project Tango。我的想法是创建一个应用程序来生成我房间的点云并将其导出到 .xyz 数据。然后,我将使用 .xyz 文件在浏览器中显示点云!我首先编译和调整了 Google github 上的点云示例。

现在我使用onXyzIjAvailable(TangoXyzIjData tangoXyzIjData) 来获取x y 和z 值的帧;点。然后我将这些帧以Vector3 的形式保存在PCLManager 中。扫描完房间后,我简单地将 PCLManager 中的所有 Vector3 写入 .xyz 文件,使用:

OutputStream os = new FileOutputStream(file);
size = pointCloud.size();
for (int i = 0; i < size; i++) {
    String row = String.valueOf(pointCloud.get(i).x) + " " 
               + String.valueOf(pointCloud.get(i).y) + " " 
               + String.valueOf(pointCloud.get(i).z) + "\r\n";
    os.write(row.getBytes());
}
os.close();

一切正常,没有编译错误或崩溃。唯一似乎出错的是云中点的旋转或平移。当我查看点云时,一切都搞砸了;我扫描的区域无法识别,尽管点数与记录的相同。

这可能与我不将 PoseData 与 XyzIjData 一起使用这一事实有关吗?我对这个主题有点陌生,很难理解 PoseData 究竟做了什么。有人可以向我解释并帮助我修复我的点云吗?

【问题讨论】:

  • 设备的位姿是捕捉点云的视点。如果您不使用该姿势,则点云会从同一视点显示,这就是为什么一切看起来都一团糟的原因。

标签: android google-project-tango point-clouds


【解决方案1】:

是的,你必须使用TangoPoseData

我猜你正确使用了TangoXyzIjData;但是您以这种方式获得的数据与设备的位置以及拍摄时设备的倾斜方式有关。

我是这样解决这个问题的:
我从java_point_to_point_example开始。在此示例中,他们使用 2 个不同的坐标系获得 2 个不同点的坐标,然后将这些坐标写入基本坐标系对。

首先,您必须设置您的外参,这样您就可以执行您需要的所有转换。为此,我在 setTangoListener() 函数的末尾调用 mExstrinsics = setupExtrinsics(mTango) 函数。这是代码(您也可以在我上面链接的示例中找到)。

private DeviceExtrinsics setupExtrinsics(Tango mTango) {
    //camera to IMU tranform
    TangoCoordinateFramePair framePair = new TangoCoordinateFramePair();
    framePair.baseFrame = TangoPoseData.COORDINATE_FRAME_IMU;
    framePair.targetFrame = TangoPoseData.COORDINATE_FRAME_CAMERA_COLOR;
    TangoPoseData imu_T_rgb = mTango.getPoseAtTime(0.0,framePair);
    //IMU to device transform
    framePair.targetFrame = TangoPoseData.COORDINATE_FRAME_DEVICE;
    TangoPoseData imu_T_device = mTango.getPoseAtTime(0.0,framePair);
    //IMU to depth transform
    framePair.targetFrame = TangoPoseData.COORDINATE_FRAME_CAMERA_DEPTH;
    TangoPoseData imu_T_depth = mTango.getPoseAtTime(0.0,framePair);
    return new DeviceExtrinsics(imu_T_device,imu_T_rgb,imu_T_depth);
}

然后,当您获得点云时,您必须对其进行“标准化”。使用你的 extrinsics 非常简单:

public ArrayList<Vector3> normalize(TangoXyzIjData cloud, TangoPoseData cameraPose, DeviceExtrinsics extrinsics) {
    ArrayList<Vector3> normalizedCloud = new ArrayList<>();

    TangoPoseData camera_T_imu = ScenePoseCalculator.matrixToTangoPose(extrinsics.getDeviceTDepthCamera());

    while (cloud.xyz.hasRemaining()) {
        Vector3 rotatedV = ScenePoseCalculator.getPointInEngineFrame(
                new Vector3(cloud.xyz.get(),cloud.xyz.get(),cloud.xyz.get()),
                camera_T_imu,
                cameraPose
        );
        normalizedCloud.add(rotatedV);
    }

    return normalizedCloud;
}

这应该足够了,现在你有一个点云 wrt 你的基本参考框架。 如果您过度叠加两个或更多这种“标准化”云,您可以获得房间的 3D 表示。

还有另一种使用旋转矩阵的方法,解释了here

我的解决方案非常慢(开发工具包大约需要 700 毫秒来标准化约 3000 个点的云),因此它不适合用于 3D 重建的实时应用程序。

Atm 我正在尝试使用 NDK 和 JNI 在 C 中使用 Tango 3D Reconstruction Library。该库有很好的文档记录,但设置环境并开始使用 JNI 非常痛苦。 (事实上​​,我现在被困住了)。

漂流

当我用设备转身时仍然有问题。看来点云散开了很多。

我猜你正在经历一些漂流。
当您单独使用 Motion Tracking 时会发生漂移:它包含在估计您的 Pose 时的许多非常小的错误,这些错误加在一起会导致您相对于世界的姿势出现很大错误.例如,如果你带着你的探戈设备绕着一个圆圈走,追踪你的TangoPoseData,然后你在电子表格或任何你想要的东西中画出你的轨迹,你会注意到平板电脑永远不会回到他的起点,因为他在漂流离开。
解决方案是使用区域学习。 如果您对此主题没有明确的想法,我建议您观看 Google I/O 2016 上的 talk。它将涵盖很多要点并给您一个很好的介绍。

使用区域学习非常简单。
您只需在TangoPoseData.COORDINATE_FRAME_AREA_DESCRIPTION 中更改您的基本参考框架。通过这种方式,你告诉你的 Tango 估计他的姿势,而不是你启动应用程序时的位置,而是该区域的某个固定点。 这是我的代码:

private static final ArrayList<TangoCoordinateFramePair> FRAME_PAIRS = 
    new ArrayList<TangoCoordinateFramePair>();
{
    FRAME_PAIRS.add(new TangoCoordinateFramePair(
            TangoPoseData.COORDINATE_FRAME_AREA_DESCRIPTION,
            TangoPoseData.COORDINATE_FRAME_DEVICE
    ));
}

现在您可以像往常一样使用这个FRAME_PAIRS

然后您必须修改您的TangoConfig 以使用密钥TangoConfig.KEY_BOOLEAN_DRIFT_CORRECTION 发布Tango 以使用区域学习。请记住,当使用TangoConfig.KEY_BOOLEAN_DRIFT_CORRECTION 时,您不能使用学习模式和加载 ADF(区域描述文件)。
所以你不能使用:

  • TangoConfig.KEY_BOOLEAN_LEARNINGMODE
  • TangoConfig.KEY_STRING_AREADESCRIPTION

这是我在我的应用程序中初始化TangoConfig 的方式:

TangoConfig config = tango.getConfig(TangoConfig.CONFIG_TYPE_DEFAULT);
//Turning depth sensor on.
config.putBoolean(TangoConfig.KEY_BOOLEAN_DEPTH, true);
//Turning motiontracking on.
config.putBoolean(TangoConfig.KEY_BOOLEAN_MOTIONTRACKING,true);
//If tango gets stuck he tries to autorecover himself.
config.putBoolean(TangoConfig.KEY_BOOLEAN_AUTORECOVERY,true);
//Tango tries to store and remember places and rooms,
//this is used to reduce drifting.
config.putBoolean(TangoConfig.KEY_BOOLEAN_DRIFT_CORRECTION,true);
//Turns the color camera on.
config.putBoolean(TangoConfig.KEY_BOOLEAN_COLORCAMERA, true); 

使用这种技术,您将摆脱这些价差。

PS
在上面链接的谈话中,大约在 22:35,他们向您展示了如何将您的应用程序移植到 Area Learning。在他们的示例中,他们使用 TangoConfig.KEY_BOOLEAN_ENABLE_DRIFT_CORRECTION。该密钥不再存在(至少在 Java API 中)。请改用TangoConfig.KEY_BOOLEAN_DRIFT_CORRECTION

【讨论】:

  • 非常感谢,我会尽快尝试一下!我不会在构建点云时渲染它。我只需要使用姿势数据并对云进行规范化,然后将其写入 xyz 文件!再次感谢,如果遇到麻烦,我会通知您。
  • 我已经尝试并实施了您的解决方案。这比我拥有的好多了!当我用设备转身时仍然有问题。点云似乎散开了很多。我还能做错什么吗?还是 Project Tango 不那么精确?如果你愿意,我可以给你一个扫描示例和真实扫描对象的图片!
  • 您遇到了一些drifting。可以使用Area Learning 解决。我现在很忙,如果您需要更多帮助,我会编辑此评论并提供更多关于明天的详细信息。
  • 我编辑了我的答案,检查关于漂流的部分。希望对您有所帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-23
  • 1970-01-01
  • 2016-04-06
  • 2016-10-01
  • 2018-01-29
  • 1970-01-01
相关资源
最近更新 更多