(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 != 2) //提示如果執行可執行文件輸入兩個參數 -f 或者-p { std::cerr << "please specify command line arg '-f' or '-p'" << std::endl; exit(0); } //申明三個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 = 5; cloud_a.height = cloud_b.height = n_cloud_b.height = 1; //設置都為無序點雲 cloud_a.points.resize (cloud_a.width * cloud_a.height); //總數 if (strcmp(argv[1], "-p") == 0) //判斷是否為連接a+b=c(點雲連接) { cloud_b.width = 3; cloud_b.points.resize (cloud_b.width * cloud_b.height); } else{ n_cloud_b.width = 5; //如果是連接XYZ與normal則生成5個法線(字段間連接) n_cloud_b.points.resize (n_cloud_b.width * n_cloud_b.height); } //以下循環生成無序點雲填充上面定義的兩種類型的點雲數據 for (size_t i = 0; i < cloud_a.points.size (); ++i) { //cloud_a產生三個點(每個點都有X Y Z 三個隨機填充的值) cloud_a.points[i].x = 1024 * rand () / (RAND_MAX + 1.0f); cloud_a.points[i].y = 1024 * rand () / (RAND_MAX + 1.0f); cloud_a.points[i].z = 1024 * rand () / (RAND_MAX + 1.0f); } if (strcmp(argv[1], "-p") == 0) for (size_t i = 0; i < cloud_b.points.size (); ++i) { //如果連接a+b=c,則cloud_b用三個點作為xyz的數據 cloud_b.points[i].x = 1024 * rand () / (RAND_MAX + 1.0f); cloud_b.points[i].y = 1024 * rand () / (RAND_MAX + 1.0f); cloud_b.points[i].z = 1024 * rand () / (RAND_MAX + 1.0f); } else for (size_t i = 0; i < n_cloud_b.points.size (); ++i) { //如果連接xyz+normal=xyznormal則n_cloud_b用5個點作為normal數據 n_cloud_b.points[i].normal[0] = 1024 * rand () / (RAND_MAX + 1.0f); n_cloud_b.points[i].normal[1] = 1024 * rand () / (RAND_MAX + 1.0f); n_cloud_b.points[i].normal[2] = 1024 * 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 = 0; 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[1], "-p") == 0) for (size_t i = 0; 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 = 0; i < n_cloud_b.points.size (); ++i) std::cerr << " " << n_cloud_b.points[i].normal[0] << " " << n_cloud_b.points[i].normal[1] << " " << n_cloud_b.points[i].normal[2] << std::endl; // Copy the point cloud data if (strcmp(argv[1], "-p") == 0) { cloud_c = cloud_a; cloud_c += cloud_b;//把cloud_a和cloud_b連接一起創建cloud_c 后輸出 std::cerr << "Cloud C: " << std::endl; for (size_t i = 0; 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 = 0; 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[0] << " " << p_n_cloud_c.points[i].normal[1] << " " << p_n_cloud_c.points[i].normal[2] << std::endl; } return (0); }
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 = 0; static double last = pcl::getTime (); //獲取當前時間 if (++count == 30) //每30ms一次輸出 { double now = pcl::getTime (); // >>右移 std::cout << "distance of center pixel :" << cloud->points [(cloud->width >> 1) * (cloud->height + 1)].z << " mm. Average framerate: " << double(count)/double(now - last) << " Hz" << std::endl; count = 0; 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 (1)); // 停止采集 interface->stop (); } }; int main () { SimpleOpenNIProcessor v; v.run (); return (0); }
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