2017-01-23 103 views
2

我想一个点云从PCL格式RGB信息转换为CV ::垫和回PCL。我发现convert mat to pointcloud上计算器。如何CV ::垫转换为PCL ::点云颜色

代码更新

我因此用在计算器为起点发现代码。现在有以下几点:

//input pcl::PointCloud<pcl::PointXYZRGB> point_cloud_ptr 
cv::Mat OpenCVPointCloud(3, point_cloud_ptr.points.size(), CV_64FC1); 
OpenCVPointCloudColor = cv::Mat(480, 640, CV_8UC3); 
for(int y=0;y<OpenCVPointCloudColor.rows;y++) 
{ 
    for(int x=0;x<OpenCVPointCloudColor.cols;x++) 
    { 
     OpenCVPointCloud.at<double>(0,y*OpenCVPointCloudColor.cols+x) = point_cloud_ptr.points.at(y*OpenCVPointCloudColor.cols+x).x; 
     OpenCVPointCloud.at<double>(1,y*OpenCVPointCloudColor.cols+x) = point_cloud_ptr.points.at(y*OpenCVPointCloudColor.cols+x).y; 
     OpenCVPointCloud.at<double>(2,y*OpenCVPointCloudColor.cols+x) = point_cloud_ptr.points.at(y*OpenCVPointCloudColor.cols+x).z; 

     cv::Vec3b color = cv::Vec3b(point_cloud_ptr.points.at(y*OpenCVPointCloudColor.cols+x).b,point_cloud_ptr.points.at(y*OpenCVPointCloudColor.cols+x).g,point_cloud_ptr.points.at(y*OpenCVPointCloudColor.cols+x).r); 

     OpenCVPointCloudColor.at<cv::Vec3b>(cv::Point(x,y)) = color; 
    } 
} 

cv::imshow("view 2", OpenCVPointCloudColor); 
cv::waitKey(30); 

显示图像之上确保我的颜色正确提取(图像与原始图像相比眼睛)。然后我想将其转换回点云:

pcl::PointCloud<pcl::PointXYZRGB>::Ptr point_cloud_ptr(new pcl::PointCloud<pcl::PointXYZRGB>); 

for(int y=0;y<OpenCVPointCloudColor.rows;y++) 
{ 
    for(int x=0;x<OpenCVPointCloudColor.cols;x++) 
    { 
     pcl::PointXYZRGB point; 
     point.x = OpencVPointCloud.at<double>(0,y*OpenCVPointCloudColor.cols+x); 
     point.y = OpencVPointCloud.at<double>(1,y*OpenCVPointCloudColor.cols+x); 
     point.z = OpencVPointCloud.at<double>(2,y*OpenCVPointCloudColor.cols+x); 

      cv::Vec3b color = OpenCVPointCloudColor.at<cv::Vec3b>(cv::Point(x,y)); 
     //Try 1 not working 
     //uint8_t r = (color[2]); 
     //uint8_t g = (color[1]); 
     //uint8_t b = (color[0]); 

     //Try 2 not working 
     //point.r = color[2]; 
     //point.g = color[1]; 
     //point.b = color[0]; 

     //Try 3 not working 
     //uint8_t r = (color.val[2]); 
     //uint8_t g = (color.val[1]); 
     //uint8_t b = (color.val[0]); 

     //test working WHY DO THE ABOVE CODES NOT WORK :/ 
     uint8_t r = 255; 
     uint8_t g = 0; 
     uint8_t b = 0; 
     int32_t rgb = (r << 16) | (g << 8) | b; 
     point.rgb = *reinterpret_cast<float*>(&rgb); 

     point_cloud_ptr -> points.push_back(point); 
    } 
} 

任何人都可以解释为什么值明确指定255,0,0颜色一切红色。但是如果我从彩色图像中选择输出,那么云的颜色是错误的?

偶然this,我看不出有什么区别我的代码有其他比,则云类型是不同的?

更新

对PCL阅读this讨论,我切换到xyzrgba(也stackoverflow提到)结束。码转换回来时,我又试图为:

point.b = OpenCVPointCloudColor.at<cv::Vec3b>(x,y)[0]; 
point.g = OpenCVPointCloudColor.at<cv::Vec3b>(x,y)[1]; 
point.r = OpenCVPointCloudColor.at<cv::Vec3b>(x,y)[2]; 
point.a = 255; 

产生的颜色云是从XYZRGB中创建的不同,但仍然是错误的:/ WTF?

额外

即使我强制红色到使用cvCloudColor.at<cv::Vec3f>(x,y) = cv::Vec3f(0,0,255);然后从OpenCVPointCloudColor阅读所有点OpenCVPointCloudColor仍然会在PCL云错误的色彩信息。

+1

在这个例子中,您似乎在尝试从'colorImage'读取它们时将这些点存储在'OpenCVPointCloudColor'中。这些都一样吗? – iamai

+0

@iamai是的,我现在会更新这个问题,以便它们具有相同的变量名称。 (只有他们在两个函数调用)。 – JTIM

+0

(与上面的代码无关)如果您尝试从使用OpenCV加载的图像读取它们,请注意默认颜色系统是BGR而不是RGB。这可能会影响颜色。 – ilke444

回答

1

我几乎可以肯定是有错误的地方围绕这些功能的代码。我想简单的例子,下面的范例,它完美的作品(PCL 1.8从源代码构建的,OpenCV的3.1来源建成,G ++ 5.x或G ++ 6.x中,Ubuntu的16.10):

#include <pcl/visualization/cloud_viewer.h> 

#include <opencv2/core.hpp> 
#include <opencv2/imgproc.hpp> 
#include <opencv2/highgui.hpp> 

void draw_cloud(
    const std::string &text, 
    const pcl::PointCloud<pcl::PointXYZRGB>::Ptr &cloud) 
{ 
    pcl::visualization::CloudViewer viewer(text); 
    viewer.showCloud(cloud); 
    while (!viewer.wasStopped()) 
    { 
    } 
} 

pcl::PointCloud<pcl::PointXYZRGB>::Ptr img_to_cloud(
     const cv::Mat& image, 
     const cv::Mat &coords) 
{ 
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>()); 

    for (int y=0;y<image.rows;y++) 
    { 
     for (int x=0;x<image.cols;x++) 
     { 
      pcl::PointXYZRGB point; 
      point.x = coords.at<double>(0,y*image.cols+x); 
      point.y = coords.at<double>(1,y*image.cols+x); 
      point.z = coords.at<double>(2,y*image.cols+x); 

      cv::Vec3b color = image.at<cv::Vec3b>(cv::Point(x,y)); 
      uint8_t r = (color[2]); 
      uint8_t g = (color[1]); 
      uint8_t b = (color[0]); 

      int32_t rgb = (r << 16) | (g << 8) | b; 
      point.rgb = *reinterpret_cast<float*>(&rgb); 

      cloud->points.push_back(point); 
     } 
    } 
    return cloud; 
} 

void cloud_to_img(
     const pcl::PointCloud<pcl::PointXYZRGB>::Ptr &cloud, 
     cv::Mat &coords, 
     cv::Mat &image) 
{ 
    coords = cv::Mat(3, cloud->points.size(), CV_64FC1); 
    image = cv::Mat(480, 640, CV_8UC3); 
    for(int y=0;y<image.rows;y++) 
    { 
     for(int x=0;x<image.cols;x++) 
     { 
      coords.at<double>(0,y*image.cols+x) = cloud->points.at(y*image.cols+x).x; 
      coords.at<double>(1,y*image.cols+x) = cloud->points.at(y*image.cols+x).y; 
      coords.at<double>(2,y*image.cols+x) = cloud->points.at(y*image.cols+x).z; 

      cv::Vec3b color = cv::Vec3b(
        cloud->points.at(y*image.cols+x).b, 
        cloud->points.at(y*image.cols+x).g, 
        cloud->points.at(y*image.cols+x).r); 

      image.at<cv::Vec3b>(cv::Point(x,y)) = color; 
     } 
    } 
} 

int main(int argc, char *argv[]) 
{ 
    cv::Mat image = cv::imread("test.png"); 
    cv::resize(image, image, cv::Size(640, 480)); 
    cv::imshow("initial", image); 

    cv::Mat coords(3, image.cols * image.rows, CV_64FC1); 
    for (int col = 0; col < coords.cols; ++col) 
    { 
     coords.at<double>(0, col) = col % image.cols; 
     coords.at<double>(1, col) = col/image.cols; 
     coords.at<double>(2, col) = 10; 
    } 

    pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud = img_to_cloud(image, coords); 
    draw_cloud("points", cloud); 

    cloud_to_img(cloud, coords, image); 
    cv::imshow("returned", image); 

    cv::waitKey(); 
    return 0; 
} 

“初始”和“返回”的图像完全相同。在PCL的观众看到我的形象点云,当然,与Z = 10,因为我硬编码了。您可能应该使用鼠标滚轮缩小并查看整个图像。

为了运行这个例子,你应该在你的工作目录中有一个名为'test.png'的文件。

我对硬编码输入文件名惋惜和调整到固定的分辨率。

试试吧,如果它在你的系统中有效,试着在你的代码中查找错误。如果它不起作用,可能你的PCL版本太旧甚至损坏。

+0

谢谢,明天我会试试这个。然而,我有(pcl 1.7,Ubuntu 14.04,ROS indigo full,即opencv 2.4)。 pcl 1.8和opencv 3.1和ROS有多个问题。我能够运行Pcl节点和opencv节点,但由于某些奇怪的原因没有任何联合。所以这是新的全新安装。不过,谢谢我会测试你的代码,看看我是否犯了一个错误。 – JTIM

+0

必须在我的配置中破坏某些东西。谢谢你澄清它。我会将其标记为由您解决 – JTIM