連接兩個點雲中的字段或數據形成新點雲以及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 != 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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM