(1)学习如何连接两个不同点云为一个点云,进行操作前要确保两个数据集中字段的类型相同和维度相等,同时了解如何连接两个不同点云的字段(例如颜色 法线)这种操作的强制约束条件是两个数据集中点的数目必须一样,例如:点云A是N个点XYZ点,点云B是N个点的RGB点,则连接两个字段形成点云C是N个点xyzrgb类型

新建文件concatenate_clouds.cpp  CMakeLists.txt

concatenate_clouds.cpp :

  1. #include <iostream>
  2. #include <pcl/io/pcd_io.h> //io模块
  3. #include <pcl/point_types.h> //数据类型
  4.  
  5. int
  6. main (int argc, char** argv)
  7. {
  8. if (argc != ) //提示如果执行可执行文件输入两个参数 -f 或者-p
  9. {
  10. std::cerr << "please specify command line arg '-f' or '-p'" << std::endl;
  11. exit();
  12. }
  13. //申明三个pcl::PointXYZ点云数据类型,分别为cloud_a, cloud_b, cloud_c
  14. pcl::PointCloud<pcl::PointXYZ> cloud_a, cloud_b, cloud_c;
  15. //存储进行连接时需要的Normal点云,Normal (float n_x, float n_y, float n_z)
  16. pcl::PointCloud<pcl::Normal> n_cloud_b;
  17. //存储连接XYZ与normal后的点云
  18. pcl::PointCloud<pcl::PointNormal> p_n_cloud_c;
  19.  
  20. // 创建点云数据
  21. //设置cloud_a的个数为5
  22. cloud_a.width = ;
  23. cloud_a.height = cloud_b.height = n_cloud_b.height = ; //设置都为无序点云
  24. cloud_a.points.resize (cloud_a.width * cloud_a.height); //总数
  25. if (strcmp(argv[], "-p") == ) //判断是否为连接a+b=c(点云连接)
  26. {
  27. cloud_b.width = ;
  28. cloud_b.points.resize (cloud_b.width * cloud_b.height);
  29. }
  30. else{
  31. n_cloud_b.width = ; //如果是连接XYZ与normal则生成5个法线(字段间连接)
  32. n_cloud_b.points.resize (n_cloud_b.width * n_cloud_b.height);
  33. }
  34. //以下循环生成无序点云填充上面定义的两种类型的点云数据
  35. for (size_t i = ; i < cloud_a.points.size (); ++i)
  36. { //cloud_a产生三个点(每个点都有X Y Z 三个随机填充的值)
  37. cloud_a.points[i].x = * rand () / (RAND_MAX + 1.0f);
  38. cloud_a.points[i].y = * rand () / (RAND_MAX + 1.0f);
  39. cloud_a.points[i].z = * rand () / (RAND_MAX + 1.0f);
  40. }
  41. if (strcmp(argv[], "-p") == )
  42. for (size_t i = ; i < cloud_b.points.size (); ++i)
  43. { //如果连接a+b=c,则cloud_b用三个点作为xyz的数据
  44. cloud_b.points[i].x = * rand () / (RAND_MAX + 1.0f);
  45. cloud_b.points[i].y = * rand () / (RAND_MAX + 1.0f);
  46. cloud_b.points[i].z = * rand () / (RAND_MAX + 1.0f);
  47. }
  48. else
  49. for (size_t i = ; i < n_cloud_b.points.size (); ++i)
  50. { //如果连接xyz+normal=xyznormal则n_cloud_b用5个点作为normal数据
  51. n_cloud_b.points[i].normal[] = * rand () / (RAND_MAX + 1.0f);
  52. n_cloud_b.points[i].normal[] = * rand () / (RAND_MAX + 1.0f);
  53. n_cloud_b.points[i].normal[] = * rand () / (RAND_MAX + 1.0f);
  54. }
  55. /*******************************************************************
  56. 定义了连接点云会用到的5个点云对象:3个输入(cloud_a cloud_b 和n_cloud_b)
  57. 两个输出(cloud_c n_cloud_c)然后就是为两个输入点云cloud_a和 cloud_b或者cloud_a 和n_cloud_b填充数据
  58.  
  59. ********************************************************************/
  60. //输出Cloud A
  61. std::cerr << "Cloud A: " << std::endl;
  62. for (size_t i = ; i < cloud_a.points.size (); ++i)
  63. std::cerr << " " << cloud_a.points[i].x << " " << cloud_a.points[i].y << " " << cloud_a.points[i].z << std::endl;
  64. //输出Cloud B
  65. std::cerr << "Cloud B: " << std::endl;
  66. if (strcmp(argv[], "-p") == )
  67. for (size_t i = ; i < cloud_b.points.size (); ++i)
  68. std::cerr << " " << cloud_b.points[i].x << " " << cloud_b.points[i].y << " " << cloud_b.points[i].z << std::endl;
  69. else//输出n_Cloud_b
  70. for (size_t i = ; i < n_cloud_b.points.size (); ++i)
  71. std::cerr << " " << n_cloud_b.points[i].normal[] << " " << n_cloud_b.points[i].normal[] << " " << n_cloud_b.points[i].normal[] << std::endl;
  72.  
  73. // Copy the point cloud data
  74. if (strcmp(argv[], "-p") == )
  75. {
  76. cloud_c = cloud_a;
  77. cloud_c += cloud_b;//把cloud_a和cloud_b连接一起创建cloud_c 后输出
  78. std::cerr << "Cloud C: " << std::endl;
  79. for (size_t i = ; i < cloud_c.points.size (); ++i)
  80. std::cerr << " " << cloud_c.points[i].x << " " << cloud_c.points[i].y << " " << cloud_c.points[i].z << " " << std::endl;
  81. }
  82. else
  83. { //连接字段 把cloud_a和 n_cloud_b字段连接 一起创建 p_n_cloud_c)
  84. pcl::concatenateFields (cloud_a, n_cloud_b, p_n_cloud_c);
  85. std::cerr << "Cloud C: " << std::endl;
  86. for (size_t i = ; i < p_n_cloud_c.points.size (); ++i)
  87. std::cerr << " " <<
  88. p_n_cloud_c.points[i].x << " " << p_n_cloud_c.points[i].y << " " << p_n_cloud_c.points[i].z << " " <<
  89. p_n_cloud_c.points[i].normal[] << " " << p_n_cloud_c.points[i].normal[] << " " << p_n_cloud_c.points[i].normal[] << std::endl;
  90. }
  91. return ();
  92. }

CMakeLists.txt:

  1. cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
  2.  
  3. project(ch2_2)
  4.  
  5. find_package(PCL 1.2 REQUIRED)
  6.  
  7. include_directories(${PCL_INCLUDE_DIRS})
  8. link_directories(${PCL_LIBRARY_DIRS})
  9. add_definitions(${PCL_DEFINITIONS})
  10.  
  11. add_executable (concatenate_clouds concatenate_clouds.cpp)
  12. target_link_libraries (concatenate_clouds ${PCL_LIBRARIES})

编译执行后的结果,仔细研究看一下就可以看出点云连接和字段间连接的区别,字段间连接是在行的基础后连接,而点云连接是在列的下方连接,最重要的就是要考虑维度问题,同时每个点云都有XYZ三个数据值

字段间连接:

点云连接

(2)对于获取传感器的深度信息可以使用OpenNI Grabber类,(其中涉及到如何安装传感器的驱动等问题,比如我使用的是kinect 1.0 可能会遇到一些安装问题,但是网上还是有很多的解决办法的,在这里不对于叙述)

新建文件openni_grabber.cpp

  1. #include <pcl/point_cloud.h> //点云类定义头文件
  2. #include <pcl/point_types.h> //点 类型定义头文件
  3. #include <pcl/io/openni_grabber.h> //OpenNI数据流获取头文件
  4. #include <pcl/common/time.h> //时间头文件
  5.  
  6. //类SimpleOpenNIProcessor 的回调函数,作为在获取数据时,对数据进行处理的回调函数的封装,在本例中并没有什么处理,只是实时的在标准输出设备打印处信息。
  7. class SimpleOpenNIProcessor
  8. {
  9. public:
  10. void cloud_cb_ (const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr &cloud)
  11. {
  12. static unsigned count = ;
  13. static double last = pcl::getTime (); //获取当前时间
  14. if (++count == ) //每30ms一次输出
  15. {
  16. double now = pcl::getTime ();
  17. // >>右移
  18. std::cout << "distance of center pixel :" << cloud->points [(cloud->width >> ) * (cloud->height + )].z << " mm. Average framerate: " << double(count)/double(now - last) << " Hz" << std::endl;
  19. count = ;
  20. last = now;
  21. }
  22. }
  23.  
  24. void run ()
  25. {
  26. pcl::Grabber* interface = new pcl::OpenNIGrabber(); //创建OpenNI采集对象
  27.  
  28. // 定义回调函数
  29. boost::function<void (const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr&)> f =
  30. boost::bind (&SimpleOpenNIProcessor::cloud_cb_, this, _1);
  31.  
  32. boost::signals2::connection c = interface->registerCallback (f);//注册回调函数
  33.  
  34. interface->start (); //开始接受点云数据
  35. //直到用户按下Ctrl -c
  36. while (true)
  37. boost::this_thread::sleep (boost::posix_time::seconds ());
  38.  
  39. // 停止采集
  40. interface->stop ();
  41. }
  42. };
  43.  
  44. int main ()
  45. {
  46. SimpleOpenNIProcessor v;
  47. v.run ();
  48. return ();
  49. }

CMakeLists.txt

  1. cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
  2.  
  3. project(openni_grabber)
  4.  
  5. find_package(PCL 1.2 REQUIRED)
  6.  
  7. include_directories(${PCL_INCLUDE_DIRS})
  8. link_directories(${PCL_LIBRARY_DIRS})
  9. add_definitions(${PCL_DEFINITIONS})
  10.  
  11. add_executable (openni_grabber openni_grabber.cpp)
  12. target_link_libraries (openni_grabber ${PCL_LIBRARIES})

编译后执行可执行文件的结果如下

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

未完待续*******************************************8

连接两个点云中的字段或数据形成新点云以及Opennni Grabber初识的更多相关文章

  1. 关于left join连接查询 两张表里有同名字段的问题

    左连接查询在开发中很常用,但有个问题常常会遇到,两个表中有同名字段时,比如左右表都有一个id字段,会造成查询结果中左表的id值被右表的id值覆盖掉(大部分php框架都是这个效果),而且还不会报错,容易 ...

  2. JavaScript concat() 方法-连接两个或多个数组

    一,定义和用法 concat() 方法用于连接两个或多个数组. 该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本. 语法 arrayObject.concat(arrayX,arrayX,. ...

  3. Linq to Entity中连接两个数据库时要注意的问题

    Linq to Entity中连接两个数据库时要注意的问题 今天大学同学问了我一个问题,Linq to Entity中连接两个数据库时,报错“指定的 LINQ 表达式包含对与不同上下文关联的查询的引用 ...

  4. Android 通过外键连接两个数据库

    Learn: 1.Android数据库的语法. 2.通过外键连接两个数据库. 3.加强了对数据库的熟悉度. 4.对文本框的visiblity属性的了解. Demo:http://pan.baidu.c ...

  5. 表A中有两个表示时间的字段A,B;如果B的值大于A的值,则把B的值更新为A的值

    sql语句:表A中有两个表示时间的字段A,B:如果B的值大于A的值,则把B的值更新为A的值 update 表名 set B=A where B>A

  6. DirectX:函数连接两个随机filter

    函数连接两个随机filter HRESULT ConnectFilters( IBaseFilter *pSrc, IBaseFilter *pDest ) { IPin *pIn = 0; IPin ...

  7. mysql 连接两列

    以下划线符号,连接两列,作为查询结果: SELECT CONCAT(col_1,'_',col_2) FROM yourtable

  8. [转载]INNER JOIN连接两个表、三个表、五个表的SQL语句

    SQL INNER JOIN关键字表示在表中存在至少一个匹配时,INNER JOIN 关键字返回行. 1.连接两个数据表的用法: FROM Member INNER JOIN MemberSort O ...

  9. 怎么用ChemDraw连接两个结构片段

    作为最新版的ChemOffice 15.1的核心组件,ChemDraw几乎能解决所有平面化学结构中的绘制问题.如果用户想连接两个分开的结构片段,ChemDraw提供两种连接两个化学结构片段的方法,分别 ...

随机推荐

  1. processing fill()和stroke()函数

    在procesiing有两个基本的函数,fill()和stroke()函数,这两个函数分别用来控制形状填充颜色和形状轮廓的颜色,fill()和stroke()可以接受的参数的个数为1,2,3.当参数的 ...

  2. wifiphisher 钓鱼工具的使用

    wifiphisher 钓鱼工具的使用一.简介 Wifiphisher是一个安全工具,具有安装快速.自动化搭建的优点,利用它搭建起来的网络钓鱼攻击WiFi可以轻松获得密码和其他凭证.与其它(网络钓鱼) ...

  3. 在Windows系统上怎么使用SecureCRT链接Linux AWS EC2 -摘自网络

    在Windows系统上就需要使用SecureCRT,Putty等工具,进行连接.但是AWS提供的XXX.pem文件,需要做一些处理SecureCRT的方法: 1.使用XXX.pem文件生成一个公钥文件 ...

  4. Atitit 软件项目系统托盘图标解决方案

    Atitit 软件项目系统托盘图标解决方案 1.1. Nodejs   node-webkit还实现了本地化的API,例如菜单栏,系统的托盘图标支持1 1.2. Java c# qt c++1 1.3 ...

  5. [jk]服务器远控卡及kvm切换器

    远控卡的需求 经常我们有这么一个需求,那就是某一台器服务器突然宕机,不能启动,而机房却在外地.解决这个问题的方法有两种,一是联系机房人员,二是通过idrac卡远程连接.我们必须根据事情的轻重缓急,来选 ...

  6. TCP/IP 三次握手,温故知新

    今天看网络编程.又又一次看了一遍三次握手.曾经只知道连接有三次握手.今天发现原来断开也有三次握手. 三次握手:指通信两方彼此交换三次信息. 三次握手是在存在数据报丢失.反复和延迟的情况下,确保通信两方 ...

  7. LPAD在Oracle中和 mssql以及在MySQL中的不同用法 以及调用存储过程方法

    Oracle: ,') from dual ,,') from dual 效果: Mssql: )+ltrim(tt.number_no) from Tabletest as tt 效果: MySQL ...

  8. 构造函数 (C++)

    构造函数是一种可初始化其类的实例的成员函数. 构造函数具有与类相同的名称,没有返回值. 构造函数可以具有任意数量的参数,类可以具有任意数量的重载构造函数. 构造函数可以具有任何可访问性(公共.受保护或 ...

  9. 【嵌入式】S3C2410平台移植linux 2.6.14内核

    小续 第一次接触内核的东西,有点小激动啊 激动归激动,这实验还是要继续做下去,书上三两句话就带过去的,剩下的就留给我们了,着实考验动手能力啊 当编译过内核之后,发现这个过程也不复杂嘛(复杂的是内核的配 ...

  10. jackson中自定义处理序列化和反序列化

    http://jackyrong.iteye.com/blog/2005323 ********************************************** 对于一直用gson的人来说 ...