2014-02-28 43 views
1

這是一個PCL(點雲庫)特定問題。我正在嘗試爲來自Kinect的實時數據流顯示範圍圖像。我已經能夠從Kinect中讀取點雲並顯示點雲。生成範圍圖像然而非常痛苦。我已經閱讀了PCL文檔中的示例,並使用了與那裏相同的代碼。 生成的距離圖像非常小,全部爲NAN。 showRangeImage函數似乎掛起(我已經評論了這個調用)。 PCL示例中的3D查看器代碼給出了vtkOutputWindow中的錯誤。用於PCL(點雲庫)中的活動kinect數據的距離圖像生成

我不確定sensorFose輸入應該用於createFromPointCloud函數。我目前正在使用 Eigen::Affine3f sensorPose = (Eigen::Affine3f)Eigen::Translation3f(0.0f, 0.0f, 0.0f); 我不知道這是否導致錯誤。

我也嘗試讀取磁盤上的pcd文件(相關代碼在下面的程序中的其他塊中)。我試圖使用相同的代碼,並在PCL文檔的示例中使用。從磁盤讀取pcd文件似乎也不工作。

任何建議將不勝感激。

#include<pcl/point_cloud.h> 
#include<pcl/point_types.h> 
#include<pcl/io/openni_grabber.h> 
#include<pcl/common/time.h> 
#include<pcl/visualization/pcl_visualizer.h>  
#include<pcl/point_types.h> 
#include<pcl/visualization/cloud_viewer.h> 
#include<pcl/range_image/range_image.h> 
#include<pcl/visualization/range_image_visualizer.h> 
#include<pcl/io/pcd_io.h> 

typedef pcl::PointXYZRGBA PointT; 
typedef pcl::PointXYZ PointType; 

pcl::visualization::CloudViewer viewer("PCL Viewer"); 
pcl::visualization::RangeImageVisualizer range_image_widget("Range image"); 
pcl::visualization::PCLVisualizer viewer3D ("3D Viewer"); 

//From PCL documentation example code 
void 
setViewerPose (pcl::visualization::PCLVisualizer& viewer, const Eigen::Affine3f&   viewer_pose) 
{ 
Eigen::Vector3f pos_vector = viewer_pose * Eigen::Vector3f(0, 0, 0); 
Eigen::Vector3f look_at_vector = viewer_pose.rotation() * Eigen::Vector3f(0, 0, 1) + pos_vector; 
Eigen::Vector3f up_vector = viewer_pose.rotation() * Eigen::Vector3f(0, -1, 0); 
viewer.setCameraPose (pos_vector[0], pos_vector[1], pos_vector[2], 
    look_at_vector[0], look_at_vector[1], look_at_vector[2], 
    up_vector[0], up_vector[1], up_vector[2]); 
} 

//Call back method 
void cloud_cb_ (const pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr &cloud) 

{ 
static unsigned count = 0; 
static double last = pcl::getTime(); 
if (++count == 30) 
{ 
    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; 
} 
// PCL viewer // 
// Display pointcloud: 
viewer.showCloud (cloud); 

//DO USEFUL OPERATIONS HERE 
//Create a range image and display it 

// We now want to create a range image from the above point cloud, with a 1deg angular resolution 
float angularResolution = (float) ( 1.0f * (M_PI/180.0f)); // 1.0 degree in radians 
float maxAngleWidth  = (float) (360.0f * (M_PI/180.0f)); // 360.0 degree in radians 
float maxAngleHeight = (float) (180.0f * (M_PI/180.0f)); // 180.0 degree in radians 
Eigen::Affine3f sensorPose = (Eigen::Affine3f)Eigen::Translation3f(0.0f, 0.0f, 0.0f); 
pcl::RangeImage::CoordinateFrame coordinate_frame = pcl::RangeImage::CAMERA_FRAME; 
float noiseLevel=0.00; 
float minRange = 0.0f; 
int borderSize = 1; 

boost::shared_ptr<pcl::RangeImage> range_image_ptr(new pcl::RangeImage); 
pcl::RangeImage& rangeImage = *range_image_ptr; 

//Range image for live stream from Kinect 
if(1){ 
rangeImage.createFromPointCloud(*cloud, angularResolution, maxAngleWidth, maxAngleHeight, 
    sensorPose, coordinate_frame, noiseLevel, minRange, borderSize); 
} 

//Alternative test - from PCD file on disk 
else{ 
    pcl::PointCloud<PointType>::Ptr point_cloud_ptr (new pcl::PointCloud<PointType>); 
    pcl::PointCloud<PointType>& point_cloud = *point_cloud_ptr; 

    //pcd file from http://download.ros.org/data/pcl/ 
    if (pcl::io::loadPCDFile ("src\\office_scene.pcd", point_cloud) == -1) 
     std::cout<<"Cannot load scene file\n"; 
    Eigen::Affine3f scene_sensor_pose (Eigen::Affine3f::Identity()); 
    scene_sensor_pose = Eigen::Affine3f (Eigen::Translation3f (point_cloud.sensor_origin_[0], 
     point_cloud.sensor_origin_[1], 
     point_cloud.sensor_origin_[2])) * 
     Eigen::Affine3f (point_cloud.sensor_orientation_); 

    rangeImage.createFromPointCloud(point_cloud, angularResolution, maxAngleWidth, maxAngleHeight, 
     scene_sensor_pose, coordinate_frame, noiseLevel, minRange, borderSize); 
} 

std::cout << rangeImage << "\n"; 

//showRangeImage seems to take a very long time (infinite loop?). Hence commented out 
//range_image_widget.showRangeImage(rangeImage); 

//viewer3D gives error 
viewer3D.setBackgroundColor (1, 1, 1); 
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointWithRange> range_image_color_handler (range_image_ptr, 0, 0, 0); 
viewer3D.addPointCloud (range_image_ptr, range_image_color_handler, "range image"); 
viewer3D.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "range image"); 
viewer3D.initCameraParameters(); 
setViewerPose(viewer3D, rangeImage.getTransformationToWorldSystem()); 


} 

int main() 
{ 
// create a new grabber for OpenNI devices 
pcl::Grabber* interface = new pcl::OpenNIGrabber(); 

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

// connect callback function for desired signal. In this case its a point cloud with color values 
boost::signals2::connection c = interface->registerCallback (f); 

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

// wait until user quits program with Ctrl-C, but no busy-waiting -> sleep (1); 
while (true) 
    boost::this_thread::sleep (boost::posix_time::seconds (1)); 

// stop the grabber 
interface->stop(); 

    return (0); 
}` 
+0

我想你應該使用RangeImagePlanar而不是RangeImage。 – Simson

回答

2

mnut,我找到了解決問題的方法。所以你得到的距離圖像太小,因爲你設置的角度參數是錯誤的。正確的方法是使用Kinect的傳感器規格的規格爲下面兩行(參照https://msdn.microsoft.com/en-us/library/jj131033.aspx):

float maxAngleWidth = (float) (57.0f * (M_PI/180.0f)); 
float maxAngleHeight = (float) (43.0f * (M_PI/180.0f)); 
float angularResolution = (float)(57.0f/640.0f * (M_PI/180.0f)); 

中的數字57和43被觀看的視場的角度,因此角分辨率是像素的量每一度,因此應該由480

對於sensorPose除以640或43 57我用下面的值(這是默認值):

Eigen::Affine3f sensorPose = Eigen::Affine3f::Identity(); 

最後,爲了顯示所得到的圖像範圍,請使用以下內容:

range_image_widget.showRangeImage(rangeImage); 
range_image_widget.spinOnce(); // This line was missing 

但你會得到的結果遠遠不是令人滿意的,因爲幀率會相當小。請參閱以下視頻進行演示:http://youtu.be/iao3BeI4LqM

而viewer3D不適合顯示rangeImages。