Point Cloud Library 1.8 - DepthSense Grabber似乎没有为NaN XYZ点提供RGB数据

时间:2015-11-16 02:19:38

标签: c++ computer-vision point-cloud-library openni

使用Xtion Pro和DS325深度相机运行以下代码会产生截然不同的结果。 Xtion Pro完美地显示了彩色点云和RGB,而DS325在图像中有许多黑色模糊区域,使得它无法用于我想要的OpenCV功能(转换为Mat格式后)。

此链接似乎是在将XYZ数据捕获为NaN时。例如,即使指出窗口(使得大部分XYZ数据为NaN),Xtion Pro也会显示完整的RGB精细,而对DS325执行相同操作会使整个RGB图像显示为黑色。

有人能告诉我这是否只是新抓取器代码的不完美之处?或者更固有地链接到不同硬件的映射差异?

运行deepsense查看器应用程序(来自primesense SDK)确实向我确认深度和完整RGB数据可以同时进行流式传输,因此有点混淆RGB似乎被丢弃的原因。任何帮助将不胜感激!感谢。

Windows,VS2013,PCL 1.8

#include <iostream>
#include <mutex>

#include <boost/thread/mutex.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/format.hpp>

#include <pcl/io/pcd_io.h>
#include <pcl/common/time.h>
#include <pcl/console/print.h>
#include <pcl/console/parse.h>
#include <pcl/io/io_exception.h>
#include <pcl/io/openni_grabber.h>
#include <pcl/io/depth_sense_grabber.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/visualization/image_viewer.h>

using namespace pcl::console; 
typedef pcl::PointCloud<pcl::PointXYZRGBA> PointCloudT; 

std::mutex cloud_mutex; 

void cloud_cb_(const PointCloudT::ConstPtr& callback_cloud, PointCloudT::Ptr& new_cloud_, 
    bool* new_cloud_available_flag) 
{ 
    cloud_mutex.lock(); 
    *new_cloud_ = *callback_cloud; 
    cloud_mutex.unlock(); 
    *new_cloud_available_flag = true; 
} 

void PointXYZRGBAtoCharArray(pcl::PointCloud<pcl::PointXYZRGBA>::Ptr point_cloud_ptr, unsigned char * Image) 
{ 
        for (int i = 0; i < point_cloud_ptr->height; i++) 
        { 
                for (int j = 0; j < point_cloud_ptr->width; j++) 
                { 
                    Image[(i * point_cloud_ptr->width + j) * 3] = point_cloud_ptr->points.at(i * point_cloud_ptr->width + j).r; 
                    Image[(i * point_cloud_ptr->width + j) * 3 + 1] = point_cloud_ptr->points.at(i * point_cloud_ptr->width + j).g; 
                    Image[(i * point_cloud_ptr->width + j) * 3 + 2] = point_cloud_ptr->points.at(i * point_cloud_ptr->width + j).b; 
                } 
        } 
} 

int main() 
{ 
    boost::mutex new_cloud_mutex_; 
    PointCloudT::Ptr cloud(new PointCloudT); 
    bool new_cloud_available_flag = false; 
    std::string device_id = ""; 
    boost::function<void(const typename PointCloudT::ConstPtr&)> f = boost::bind(&cloud_cb_, _1, cloud, &new_cloud_available_flag); 
    boost::shared_ptr<pcl::Grabber> grabber; 
    try 
    { 
            grabber.reset(new pcl::OpenNIGrabber); 
            cout << "Using OpenNI Device" << endl; 
    } 
    catch (pcl::IOException& e) 
    { 
            grabber.reset(new pcl::DepthSenseGrabber); 
            cout << "Using DepthSense Device" << endl; 
    } 
    grabber->registerCallback(f); 
    grabber->start(); 

    // Image Viewer 
    pcl::visualization::ImageViewer Imageviewer("Image Viewer"); 
    unsigned char* Image = new unsigned char[3*cloud->height*cloud->width]; 
    Imageviewer.addRGBImage(Image, cloud->width, cloud->height); 

    // Point Cloud Viewer: 
    pcl::visualization::PCLVisualizer viewer("PCL Viewer"); 
    viewer.setCameraPosition(0, 0, -2, 0, -1, 0, 0); 

    for (;;) 
    { 
            if (new_cloud_available_flag) 
            { 
                    new_cloud_available_flag = false; 
                    cloud_mutex.lock(); 

                    // Update Image 
                    Imageviewer.removeLayer("rgb_image"); 
                    PointXYZRGBAtoCharArray(cloud, Image); 
                    Imageviewer.addRGBImage(Image,cloud->width,cloud->height); 
                    Imageviewer.spinOnce(); 

                    // Update Point Cloud 
                    viewer.removeAllPointClouds(); 
                    viewer.addPointCloud<pcl::PointXYZRGBA>(cloud); 
                    cloud_mutex.unlock(); 
                    viewer.spinOnce(); 
            } 
    } 
    grabber->stop(); 

}

1 个答案:

答案 0 :(得分:2)

DepthSense抓取器从驱动程序接收两个流:深度和颜色。它们被合并为带有颜色的单点云,然后返回给最终用户。由于所涉及的两个传感器(红外和彩色相机)具有一定的位移和不同的分辨率(分别为QVGA和VGA),因此流中的深度和彩色像素之间的映射并不是微不足道的。实际上,对于每个深度/颜色帧,相机驱动器另外产生所谓的UV图,其可用于建立对应关系。不幸的是,它无法为无效深度像素设置UV坐标,这使得无法为NaN点找到相应的RGB值。

我建议直接使用DepthSense SDK访问原始RGB图像。