连接两个点云中的字段或数据形成新点云以及Opennni Grabber初识
(1)学习如何连接两个不同点云为一个点云,进行操作前要确保两个数据集中字段的类型相同和维度相等,同时了解如何连接两个不同点云的字段(例如颜色 法线)这种操作的强制约束条件是两个数据集中点的数目必须一样,例如:点云A是N个点XYZ点,点云B是N个点的RGB点,则连接两个字段形成点云C是N个点xyzrgb类型
新建文件concatenate_clouds.cpp CMakeLists.txt
concatenate_clouds.cpp :
#include <iostream>
#include <pcl/io/pcd_io.h> //io模块
#include <pcl/point_types.h> //数据类型 int
main (int argc, char** argv)
{
if (argc != ) //提示如果执行可执行文件输入两个参数 -f 或者-p
{
std::cerr << "please specify command line arg '-f' or '-p'" << std::endl;
exit();
}
//申明三个pcl::PointXYZ点云数据类型,分别为cloud_a, cloud_b, cloud_c
pcl::PointCloud<pcl::PointXYZ> cloud_a, cloud_b, cloud_c;
//存储进行连接时需要的Normal点云,Normal (float n_x, float n_y, float n_z)
pcl::PointCloud<pcl::Normal> n_cloud_b;
//存储连接XYZ与normal后的点云
pcl::PointCloud<pcl::PointNormal> p_n_cloud_c; // 创建点云数据
//设置cloud_a的个数为5
cloud_a.width = ;
cloud_a.height = cloud_b.height = n_cloud_b.height = ; //设置都为无序点云
cloud_a.points.resize (cloud_a.width * cloud_a.height); //总数
if (strcmp(argv[], "-p") == ) //判断是否为连接a+b=c(点云连接)
{
cloud_b.width = ;
cloud_b.points.resize (cloud_b.width * cloud_b.height);
}
else{
n_cloud_b.width = ; //如果是连接XYZ与normal则生成5个法线(字段间连接)
n_cloud_b.points.resize (n_cloud_b.width * n_cloud_b.height);
}
//以下循环生成无序点云填充上面定义的两种类型的点云数据
for (size_t i = ; i < cloud_a.points.size (); ++i)
{ //cloud_a产生三个点(每个点都有X Y Z 三个随机填充的值)
cloud_a.points[i].x = * rand () / (RAND_MAX + 1.0f);
cloud_a.points[i].y = * rand () / (RAND_MAX + 1.0f);
cloud_a.points[i].z = * rand () / (RAND_MAX + 1.0f);
}
if (strcmp(argv[], "-p") == )
for (size_t i = ; i < cloud_b.points.size (); ++i)
{ //如果连接a+b=c,则cloud_b用三个点作为xyz的数据
cloud_b.points[i].x = * rand () / (RAND_MAX + 1.0f);
cloud_b.points[i].y = * rand () / (RAND_MAX + 1.0f);
cloud_b.points[i].z = * rand () / (RAND_MAX + 1.0f);
}
else
for (size_t i = ; i < n_cloud_b.points.size (); ++i)
{ //如果连接xyz+normal=xyznormal则n_cloud_b用5个点作为normal数据
n_cloud_b.points[i].normal[] = * rand () / (RAND_MAX + 1.0f);
n_cloud_b.points[i].normal[] = * rand () / (RAND_MAX + 1.0f);
n_cloud_b.points[i].normal[] = * rand () / (RAND_MAX + 1.0f);
}
/*******************************************************************
定义了连接点云会用到的5个点云对象:3个输入(cloud_a cloud_b 和n_cloud_b)
两个输出(cloud_c n_cloud_c)然后就是为两个输入点云cloud_a和 cloud_b或者cloud_a 和n_cloud_b填充数据 ********************************************************************/
//输出Cloud A
std::cerr << "Cloud A: " << std::endl;
for (size_t i = ; i < cloud_a.points.size (); ++i)
std::cerr << " " << cloud_a.points[i].x << " " << cloud_a.points[i].y << " " << cloud_a.points[i].z << std::endl;
//输出Cloud B
std::cerr << "Cloud B: " << std::endl;
if (strcmp(argv[], "-p") == )
for (size_t i = ; i < cloud_b.points.size (); ++i)
std::cerr << " " << cloud_b.points[i].x << " " << cloud_b.points[i].y << " " << cloud_b.points[i].z << std::endl;
else//输出n_Cloud_b
for (size_t i = ; i < n_cloud_b.points.size (); ++i)
std::cerr << " " << n_cloud_b.points[i].normal[] << " " << n_cloud_b.points[i].normal[] << " " << n_cloud_b.points[i].normal[] << std::endl; // Copy the point cloud data
if (strcmp(argv[], "-p") == )
{
cloud_c = cloud_a;
cloud_c += cloud_b;//把cloud_a和cloud_b连接一起创建cloud_c 后输出
std::cerr << "Cloud C: " << std::endl;
for (size_t i = ; i < cloud_c.points.size (); ++i)
std::cerr << " " << cloud_c.points[i].x << " " << cloud_c.points[i].y << " " << cloud_c.points[i].z << " " << std::endl;
}
else
{ //连接字段 把cloud_a和 n_cloud_b字段连接 一起创建 p_n_cloud_c)
pcl::concatenateFields (cloud_a, n_cloud_b, p_n_cloud_c);
std::cerr << "Cloud C: " << std::endl;
for (size_t i = ; i < p_n_cloud_c.points.size (); ++i)
std::cerr << " " <<
p_n_cloud_c.points[i].x << " " << p_n_cloud_c.points[i].y << " " << p_n_cloud_c.points[i].z << " " <<
p_n_cloud_c.points[i].normal[] << " " << p_n_cloud_c.points[i].normal[] << " " << p_n_cloud_c.points[i].normal[] << std::endl;
}
return ();
}
CMakeLists.txt:
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(ch2_2)
find_package(PCL 1.2 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
add_executable (concatenate_clouds concatenate_clouds.cpp)
target_link_libraries (concatenate_clouds ${PCL_LIBRARIES})
编译执行后的结果,仔细研究看一下就可以看出点云连接和字段间连接的区别,字段间连接是在行的基础后连接,而点云连接是在列的下方连接,最重要的就是要考虑维度问题,同时每个点云都有XYZ三个数据值
字段间连接:

点云连接

(2)对于获取传感器的深度信息可以使用OpenNI Grabber类,(其中涉及到如何安装传感器的驱动等问题,比如我使用的是kinect 1.0 可能会遇到一些安装问题,但是网上还是有很多的解决办法的,在这里不对于叙述)
新建文件openni_grabber.cpp
#include <pcl/point_cloud.h> //点云类定义头文件
#include <pcl/point_types.h> //点 类型定义头文件
#include <pcl/io/openni_grabber.h> //OpenNI数据流获取头文件
#include <pcl/common/time.h> //时间头文件 //类SimpleOpenNIProcessor 的回调函数,作为在获取数据时,对数据进行处理的回调函数的封装,在本例中并没有什么处理,只是实时的在标准输出设备打印处信息。
class SimpleOpenNIProcessor
{
public:
void cloud_cb_ (const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr &cloud)
{
static unsigned count = ;
static double last = pcl::getTime (); //获取当前时间
if (++count == ) //每30ms一次输出
{
double now = pcl::getTime ();
// >>右移
std::cout << "distance of center pixel :" << cloud->points [(cloud->width >> ) * (cloud->height + )].z << " mm. Average framerate: " << double(count)/double(now - last) << " Hz" << std::endl;
count = ;
last = now;
}
} void run ()
{
pcl::Grabber* interface = new pcl::OpenNIGrabber(); //创建OpenNI采集对象 // 定义回调函数
boost::function<void (const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr&)> f =
boost::bind (&SimpleOpenNIProcessor::cloud_cb_, this, _1); boost::signals2::connection c = interface->registerCallback (f);//注册回调函数 interface->start (); //开始接受点云数据
//直到用户按下Ctrl -c
while (true)
boost::this_thread::sleep (boost::posix_time::seconds ()); // 停止采集
interface->stop ();
}
}; int main ()
{
SimpleOpenNIProcessor v;
v.run ();
return ();
}
CMakeLists.txt
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(openni_grabber)
find_package(PCL 1.2 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
add_executable (openni_grabber openni_grabber.cpp)
target_link_libraries (openni_grabber ${PCL_LIBRARIES})
编译后执行可执行文件的结果如下

微信公众号号可扫描二维码一起共同学习交流

未完待续*******************************************8
连接两个点云中的字段或数据形成新点云以及Opennni Grabber初识的更多相关文章
- 关于left join连接查询 两张表里有同名字段的问题
左连接查询在开发中很常用,但有个问题常常会遇到,两个表中有同名字段时,比如左右表都有一个id字段,会造成查询结果中左表的id值被右表的id值覆盖掉(大部分php框架都是这个效果),而且还不会报错,容易 ...
- JavaScript concat() 方法-连接两个或多个数组
一,定义和用法 concat() 方法用于连接两个或多个数组. 该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本. 语法 arrayObject.concat(arrayX,arrayX,. ...
- Linq to Entity中连接两个数据库时要注意的问题
Linq to Entity中连接两个数据库时要注意的问题 今天大学同学问了我一个问题,Linq to Entity中连接两个数据库时,报错“指定的 LINQ 表达式包含对与不同上下文关联的查询的引用 ...
- Android 通过外键连接两个数据库
Learn: 1.Android数据库的语法. 2.通过外键连接两个数据库. 3.加强了对数据库的熟悉度. 4.对文本框的visiblity属性的了解. Demo:http://pan.baidu.c ...
- 表A中有两个表示时间的字段A,B;如果B的值大于A的值,则把B的值更新为A的值
sql语句:表A中有两个表示时间的字段A,B:如果B的值大于A的值,则把B的值更新为A的值 update 表名 set B=A where B>A
- DirectX:函数连接两个随机filter
函数连接两个随机filter HRESULT ConnectFilters( IBaseFilter *pSrc, IBaseFilter *pDest ) { IPin *pIn = 0; IPin ...
- mysql 连接两列
以下划线符号,连接两列,作为查询结果: SELECT CONCAT(col_1,'_',col_2) FROM yourtable
- [转载]INNER JOIN连接两个表、三个表、五个表的SQL语句
SQL INNER JOIN关键字表示在表中存在至少一个匹配时,INNER JOIN 关键字返回行. 1.连接两个数据表的用法: FROM Member INNER JOIN MemberSort O ...
- 怎么用ChemDraw连接两个结构片段
作为最新版的ChemOffice 15.1的核心组件,ChemDraw几乎能解决所有平面化学结构中的绘制问题.如果用户想连接两个分开的结构片段,ChemDraw提供两种连接两个化学结构片段的方法,分别 ...
随机推荐
- 硬盘 SMART 检测参数详解[转]
一.SMART概述 硬盘的故障一般分为两种:可预测的(predictable)和不可预测的(unpredictable).后者偶而会发生,也没有办法去预防它,例如芯片突然失效,机械撞击等.但像电机轴承 ...
- PHP的生成器、yield和协程
虽然之前就接触了PHP的yield关键字和与之对应的生成器,但是一直没有场景去使用它,就一直没有对它上心的研究.不过公司的框架是基于php的协程实现,觉得有必要深入的瞅瞅了. 由于之前对于生成器接触不 ...
- centos安装Elasticsearch步骤
1.安装JDK:centos删除openJDK,安装JDK,vim /etc/profile配置JAVA_HOME 2.官网下载elasticsearch:https://www.elastic.co ...
- [LintCode] Subarray Sum & Subarray Sum II
Subarray Sum Given an integer array, find a subarray where the sum of numbers is zero. Your code sho ...
- 设置 debug 版本签名与生产版本一致
debug 版本使用生产版本的签名 在开发过程中,app 直接跑到手机上,用的签名文件是 Android Studio 默认的自动生成的一个签名,与生产版本的 app 签名是不一样的.当接入华为推送的 ...
- 使用gradle多渠道打包
以友盟的多渠道打包为例,如果我们须要打包出例如以下渠道:UMENG, WANDOUJIA, YINGYONGBAO. 第一种方法.是须要创建文件的. 我们在写完我们的代码之后,在app/src以下.分 ...
- zabbix 对/etc/ssh/sshd_config文件的监控 但status为unknowen
原因为该文件没有被访问的权限: # ll /etc/ssh/sshd_config -rw------- root root Apr : /etc/ssh/sshd_config 授权后再看: [ro ...
- HTML5学习笔记(六):CSS基本样式
背景 需要注意:背景的所有属性都不会向下进行继承. 背景色 我们可以设定一个纯色为背景色. p {background-color: red;} a {background-color: #ff000 ...
- (原创)C++11改进我们的程序之简化我们的程序(二)
这次要讲的是:C++11如何通过组合函数来简化我们的程序.关于组合函数,大家可能对这个概念有点陌生.组合函数是将N个一元函数组成一种更复杂的函数,每个函数的返回值作为参数传给下一个函数,直到传到最后一 ...
- SAP BI vs. Oracle BI
对比Oracle BI产品和SAP BI 产品,做一些简单的产品功能比较,经供参考. 这里把SAP和Oracle同类的产品放在一行,用于比较. SAP BI 特点 Oracle BI 特点 BW 和S ...