如何从Kinect保存PCD文件?

4
前言:我对编程比较陌生。使用 Ubuntu 12.04,并从其网站下载了最新的 PCL(我相信是 PCL 1.7)。我已经成功地编译和构建了此处列出的 iograbber 程序:http://pointclouds.org/documentation/tutorials/openni_grabber.php 我已经查阅了 pointclouds.org 的教程,但没有任何内容解释如何添加几行代码以将当前 Kinect 点云保存为 PCD 文件。在“writer”教程中,它说:
pcl::io::savePCDFileASCII ("test_pcd.pcd", cloud)

但这仅仅是为了保存随机的示例点。我想要用按键执行 PCD 保存,例如按下空格键。我知道有人以前做过这个,但我找不到示例代码。请问有人可以指导我吗?

3个回答

2
这是对于任何从事ROS工作的人的理想解决方案。我将解决方案分为两个部分 - 一、将其存储为ROS bag文件(用于存储来自ROS主题的任何类型的数据的便捷工具);二、将rosbag文件写入pcd文件。现在这非常简单。
(参考文献:http://wiki.ros.org/Bags
A)将数据存储在BAG文件中(ROS文件类型)
首先将数据(任何类型的数据都可以存储)存储为ROSBAG。 ROSBAG仅记录主题的数据。
1.要开始使用kinect,请打开终端并运行:
 $roslaunch kinect2_bridge kinect2_bridge.launch publish_tf:=true

这将让ROS系统开始从Kinect获取数据。您应该看到系统启动并显示“等待客户端连接”的状态。
2.要查看点云,请打开一个新终端。运行:
$ rosrun kinect2_viewer kinect2_viewer sd cloud

您将看到一个新窗口弹出,显示点云视图。这里是解释kinect2_viewer函数参数的链接:https://github.com/code-iai/iai_kinect2/tree/master/kinect2_viewer

3.要记录数据,在新终端中运行:

$ rosbag record -O pcl_sample1.bag -a 

在这里,“-a”表示您将订阅所有可用的ros主题并记录它们的数据。当您认为数据足够时,可以通过ctrl-C停止它。数据将存储在.bag文件中,这里的名称是name.bag。更多设置可以在此处找到:http://wiki.ros.org/rosbag/Commandline#record 现在拔掉Kinect。bag文件包含了通过启动kinect2_bridge运行的所有主题的数据。现在,您可以像实际插入Kinect一样使用主题数据。
4. 要回放数据,您需要停止第一个终端(即启动文件)中的程序。然后运行:
$ roscore

这将启动一个ROS服务器。然后在另一个终端中运行以下命令:

  1. 播放bag文件:

    $ rosbag play pcl_sample1.bag

这将使ROS系统回放您刚刚记录的数据,就好像设备仍在工作一样。然后,您可以使用kinect2_viewer查看数据,例如:

  1. 运行任何与Kinect实际插入时相同的命令。

    $ rosrun kinect2_viewer kinect2_viewer sd cloud

注意:如果您想记录特定主题,请访问http://wiki.ros.org/Bags

B) 将BAG转换为PCD文件:(现在只需一个命令。)

将适当的主题写入相应的文件夹:

rosrun pcl_ros bag_to_pcd pcl_sample1.bag /kinect2/sd/image_color_rect src/

rosrun pcl_ros bag_to_pcd pcl_sample1.bag /kinect2/sd/image_depth_rect src/PCD\ Files/

这个解决方案很好,但是如何将它集成到启动文件中? - Kevin Patel

2
使用同样的教程,您可以添加以下内容
 void cloud_cb_ (const pcl::PointCloud<pcl::PointXYZ>::ConstPtr &cloud)
 {
   if (!viewer.wasStopped())
     viewer.showCloud (cloud);
 }

在回调函数中,您之前编写的代码行(该函数接收来自抓取器的点云)需要更改为以下内容:

 void cloud_cb_ (const pcl::PointCloud<pcl::PointXYZ>::ConstPtr &cloud)
 {
   if (!viewer.wasStopped()){
     viewer.showCloud (cloud);
     pcl::io::savePCDFile ("test_pcd.pcd", cloud);
   }
 }

这段代码应该保存您正在可视化的点云。如果您没有可视化点云,请留言告知。

注意: 您也可以使用

pcl::io::savePCDFile ("test_pcd.pcd", cloud, true);

为了以二进制模式保存,这样会更快(但你可能无法在文本编辑器中读取文件)

希望这可以帮到你


你是指使用 pcl::io::savePCDFileBinary 以二进制模式保存,对吧? - Simson
@Simson 抱歉,我混淆了我使用的函数名称。我已经编辑了答案并更正了函数名称。最后一个值的默认设置为 false,会以 ASCII 形式保存;如果设置为 true,则会以二进制形式保存。 - api55
但是我要怎样决定它何时保存到云端呢?我看过其他示例程序,它们会在按下某个按键时进行保存。我该如何做到这一点呢? - athoesen
是的,这是可能的,但如果您正在使用pcl抓取器,则需要绑定键回调函数;如果您直接使用openni,则可以使用任何c++键抓取函数并创建自己的键回调函数。如果您将其显示为opencv mat,则可以尝试使用waitKey函数(最后一个示例可以在此处查看:https://github.com/cvlabbonn/tools_openni2)。希望能有所帮助,如果不行,请提出新问题,我会用更多的示例和更完整的答案来回答它。 - api55
@Shashwat,每次创建图像时都可以创建一个pcd文件,但要注意...这将大大降低FPS,因为它必须将其写入硬盘。我建议将其保存在内存中,然后保存到磁盘(如果您的内存足够大),或仅保存图像(深度和RGB),然后再将它们组合成一个pcd文件。 - api55
显示剩余2条评论

-1

我曾经遇到过同样的问题,但是我找到了解决方案。

在这段代码中:

     void cloud_cb_ (const pcl::PointCloud<pcl::PointXYZ>::ConstPtr &cloud)
 {
   if (!viewer.wasStopped())
     viewer.showCloud (cloud);
 }

你需要添加这行代码

pcl::io::savePCDFileASCII ("test_pcd.pcd", *cloud);

像这样

 void cloud_cb_ (const pcl::PointCloud<pcl::PointXYZ>::ConstPtr &cloud)
 {
   if (!viewer.wasStopped())
   {
       viewer.showCloud (cloud);
       pcl::io::savePCDFileASCII ("test_pcd.pcd", *cloud);
   }
 }

这会减慢 .exe 的速度,但您可以尝试将此行放在程序的其他部分


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接