欢迎点云相关产学研的学者和团体加入我们。
从PCL 1.0开始,PCL提供了一个通用采集接口,这样可以方便地连接到不同的设备及其驱动、文件格式和其他数据源。PCL集成的第一个数据获取驱动是新的OpenNI Grabber,它使得从OpenNI兼容的设备请求数据流变得十分简单。本小节展示如何设置并使用该采集卡,正因为它如此简单,我们讲得很简短。
图1 PCL OpenNI Viewer运行效果
PCL测试例子中在visualization(可视化)中有一段非常简短的代码,它包含了设置pcl::PointCloud<XYZ>或者pcl::PointCloud<XYZRGB>回调函数所需要的所有东西。下面如图1和2所示是屏幕截图,是运行PCL OpenNI Viewer的实时截图,其使用的正是OpenNI Grabber类。
我们看看代码。在PCL的源码目录下visualization/tools/openni_viewer_simple.cpp文件中。
就像你看到的,SimpleOpenNIViewer的run()函数首先创建了一个新的OpenNIGrabber接口,下面的一行第一眼看起来挺吓人的,但是并非这样。我们用回调函数cloud_cb_地址创建boost::bind对象,给SimpleOpenNIViewer传递一个引用和参数_1作为占位符。
该bind被固定到boost::function对象中,boost::function对象的函数类型是实例化的模板函数,在本例中是void (constpcl::PointCloud<pcl::PointXYZ>::ConstPtr&)。生成的函数对象可以在OpenNIGrabber中注册,随后开始在OpenNIGrabber起作用。注意不需要调用stop()方法,因为析构函数可以完成相应的功能。
图2 openni_viewer_simple测试结果
OpenNIGrabber提供不止一种数据类型,这是PCL把Grabber接口设计得如此通用的原因,而这也使得boost::bind一行相对复杂。实际上,我们可以注册下面几种类型的回调函数:
void (const boost::shared_ptr<constpcl::PointCloud<pcl::PointXYZRGB> >&)
void (const boost::shared_ptr<constpcl::PointCloud<pcl::PointXYZ> >&)
void (const boost::shared_ptr<openni_wrapper::Image>&)
这仅仅提供内置摄像头生成的RGB图像。
void (const boost::shared_ptr<openni_wrapper::DepthImage>&)
这个提供深度图像,不带任何颜色或者亮度信息。
void (const boost::shared_ptr<openni_wrapper::Image>&, const boost::shared_ptr<openni_wrapper::DepthImage>&, float constant)
当注册上面这种类型的回调函数时,采集器会发送RGB图像和深度图像,以及一个常数(1/焦距),该常数用于用户自定义进行视差转换计算。所有需要深度图像和RGB图像流的回调函数类型都会启用一个同步机制,它能保证一致的深度和图像数据。这样引入了一个小的时延,因为同步机制在发送第一张图像之前至少需要等待采集到一组图片。
调用registerCallback将返回一个boost::signals2::connection对象,上面的例子里我们忽略掉了它。然而,如果你想要中断或者取消一个或多个注册数据流,只需要断开与回调函数的连接,而不用停止整个采集器,这样其他还在进行处理的回调函数可以正常工作:
boost::signals2::connection=interface(registerCallback(f));
if(c.connected())
c.disconnect();
下面的代码段尝试请求访问深度和颜色数据流,它是作为一种基准来测试你的采集系统能否正常使用而提供的。如果你的电脑太慢,可能不能达到29Hz以上。
首先,在PCL(Point Cloud Learning)中国协助发行的书[1]提供光盘的第4章例4文件夹中,打开名为openni_grabber.cpp的代码文件。
现在,解析上面的打开的源代码,在下面几行声明相关头文件,其中openni_grabber.h是openni相关类接口定义的头文件。
#include <pcl/point_cloud.h> //点云类定义头文件
#include <pcl/point_types.h> //点类型定义头文件
#include <pcl/io/openni_grabber.h> //OpenNI数据流获取类头文件
#include <pcl/common/time.h>
下面定义为类SimpleOpenNIProcessor的回调函数,作为在获取数据时对数据进行处理的回调函数的封装,在本例中并没有什么处理,只是实时在标准输出设备打印出些信息。
void cloud_cb_(const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr &cloud)
{
static unsigned count=0;
static double last=pcl::getTime();
if(++count==30)
{
double now=pcl::getTime();
std::cout<<"distance of centerpixel :"<<cloud->points[(cloud->width>>1)*(cloud->height+1)].z<<" mm. Average framerate: "<<double(count)/double(now-last)<<" Hz"<<std::endl; //打印信息
下面是类SimpleOpenNIProcessor的run()函数,实现对设备的打开和数据的采集,并同时实现对回调函数的注册。
pcl::Grabber* interface= new pcl::OpenNIGrabber();//创建OpenNI采集对象
boost::function<void(constpcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr&)>f=
boost::bind(&SimpleOpenNIProcessor::cloud_cb_,this,_1);// 定义回调函数
boost::signals2::connectionc=interface->registerCallback(f);// 注册回调函数
interface->start(); // 开始接收点云数据
while(true) // 等待直到用户按Ctrl-C
sleep(1);
interface->stop(); //停止采集
未完待续,敬请关注“PCL中的OpenNI点云获取框架(2)”的编译和运行程序的结果。