PCL中的OpenNI點雲獲取框架(OpenNI Grabber Framework in PCL)


  PCL 1.0開始,PCL(三維點雲處理庫Point Cloud Library)提供了一個通用采集接口,這樣可以方便地連接到不同的設備及其驅動、文件格式和其他數據源。PCL集成的第一個數據獲取驅動是OpenNI Grabber,它使得從OpenNI兼容的設備請求數據流變得十分通用和簡單。

  目前PCL最新的1.8.0版本需要自行編譯,而官網上的PCL 1.6.0 All-in-one Installer只支持OpenNI 1。由於我使用的奧比中光3D攝像頭只支持OpenNI 2,因此必須使用PCL 1.8.0版本。從源代碼開始編譯可以參考官網教程Compiling from source,為了圖省事我找到一個別人編譯好的PCL 1.8.0 All-in-one Installer

  將PCL 1.8.0 All-in-one Installer MSVC2013 Win64下載並安裝在默認的C盤路徑下“C:\Program Files\PCL 1.8.0”,OpenNI2也裝到默認路徑下(注意最好安裝到默認了路徑下,否則可能出現一些問題)。安裝好后可以參考官網的教程The OpenNI Grabber Framework in PCL,實現3D點雲實時獲取。不過官網的教程還停留在OpenNI 1。而在OpenNI 2中OpenNIGrabber()函數的調用方式有所不同,如下所示:

// OpenNI 1:
pcl::Grabber* interface = new pcl::OpenNIGrabber();    //  #include <pcl/io/openni_grabber.h>

// OpenNI 2:
pcl::Grabber* interface = new pcl::io::OpenNIGrabber();  //  #include <pcl/io/openni2_grabber.h>

  注意相應的頭文件也要改變。通過下面簡單的代碼,可以實現從3D體感攝像頭中讀取深度信息,並實時顯示3D點雲:

#include <pcl/io/openni2_grabber.h>
#include <pcl/visualization/cloud_viewer.h>

class SimpleOpenNIViewer
{
public:
    SimpleOpenNIViewer() : viewer("PCL OpenNI Viewer") {}  // Construct a cloud viewer, with a window name
    
    // 定義回調函數cloud_cb_,獲取到數據時對數據進行處理
    void cloud_cb_(const pcl::PointCloud<pcl::PointXYZ>::ConstPtr &cloud)
    {
        if (!viewer.wasStopped()) // Check if the gui was quit. true if the user signaled the gui to stop
            viewer.showCloud(cloud);
    }

    void run()
    {
        // create a new grabber for OpenNI devices
        pcl::Grabber* interface = new pcl::io::OpenNI2Grabber();

        // make callback function from member function
        boost::function<void(const pcl::PointCloud<pcl::PointXYZ>::ConstPtr&)> f =
            boost::bind(&SimpleOpenNIViewer::cloud_cb_, this, _1);

         // connect callback function for desired signal
        boost::signals2::connection c = interface->registerCallback(f);

        // start receiving point clouds
        interface->start();

        while (!viewer.wasStopped())
        {
            boost::this_thread::sleep(boost::posix_time::seconds(1));
        }

        // Stop the data acquisition
        interface->stop();
    }

    pcl::visualization::CloudViewer viewer;
};


int main()
{
    SimpleOpenNIViewer v;
    
    v.run();
    
    return 0;
}

  上面代碼中SimpleOpenNIViewerrun()函數首先創建了一個新的OpenNI2Grabber接口。接下來用回調函數cloud_cb_地址創建boost::bind對象,給SimpleOpenNIViewer傳遞一個引用和參數_1作為占位符。The bind then gets casted to a boost::function object which is templated on the callback function type, in this case void (const pcl::PointCloud<pcl::PointXYZ>::ConstPtr&). The resulting function object can the be registered with the OpenNIGrabber and subsequently started. 

  OpenNIGrabber提供不止一種數據類型,我們可以注冊下面幾種類型的回調函數:

  1. void (const boost::shared_ptr<const pcl::PointCloud<pcl::PointXYZRGB> >&)

  2. void (const boost::shared_ptr<const pcl::PointCloud<pcl::PointXYZ> >&)

  3. void (const boost::shared_ptr<openni_wrapper::Image>&)  這僅僅提供內置攝像頭生成的RGB圖像

  4. void (const boost::shared_ptr<openni_wrapper::DepthImage>&)  這個提供深度圖像,不帶任何顏色或者亮度信息。

  5. void (const boost::shared_ptr<openni_wrapper::Image>&, const boost::shared_ptr<openni_wrapper::DepthImage>&, float constant) 采集器會發送RGB圖像和深度圖像

  注意:所有需要深度圖像和RGB圖像流的回調函數類型都會啟用一個同步機制,它能保證圖像和深度數據的一致。這樣引入了一個小的時延,因為同步機制在發送第一張圖像之前至少需要等待采集到一組圖片。

  調用registerCallback將返回一個boost::signals2::connection對象,上面的例子里我們忽略掉了它。然而,如果你想要中斷或者取消一個或多個注冊數據流,只需要斷開與回調函數的連接,而不用停止整個采集器,這樣其他還在進行處理的回調函數可以正常工作:

boost::signals2::connection c = interface (registerCallback (f));

// ...

if (c.connected ())
  c.disconnect ();

  下面通過CMake創建工程文件:

cmake_minimum_required(VERSION 2.8 FATAL_ERROR)

project(openni_grabber)

find_package(PCL 1.8 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})

  從這里開始我遇到了很多奇怪的問題:

  1. 一開始我使用CMake生成VS2010的工程文件,可是在生成工程文件過程中總是出現“common is required but boost was not found”錯誤:

  按照網上提出的修改CMake文件等方式還是不管用,后來有人說是因為版本問題,應該對應的選擇生成VS2013工程文件。

  2. 我又裝了一個VS2013,這次選擇生成VS2013工程文件,生成過程中出現了一些警告信息,如OPENNI_LIBRARY-NOTFOUND等,忽略這些信息;

  打開成功生成的工程文件,進行編譯:

  可是在生成解決方案時,出現了這種錯誤: fatal error C1001: 編譯器中發生內部錯誤。1>  (編譯器文件“msc1.cpp”,第 1325 行)

  網上查找原因,說是VS2013編譯器的Bug,需要安裝Microsoft Visual Studio 2013 Update 5適用於Visual Studio 2013的一系列新增功能和Bug修復中的最新更新)。這個更新的安裝過程比較漫長...怎么安裝這個更新可以參考百度知道:怎樣更新VS2013 update 5

  更新裝完后再重新生成就可以了,下面是通過獲取攝像頭探測到的深度信息生成的3D點雲:

 

 

 

參考:

The OpenNI Grabber Framework in PCL

PCL中的OpenNI點雲獲取框架

Capture Point Cloud with PCL 1.8 and Kinect 

PCL-1.8.0 All In One安裝配置

http://unanancyowen.com/en/pcl18/

pcl/visualization/tools/openni2_viewer.cpp


免責聲明!

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



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