如何使用颜色

时间:2017-01-23 21:52:45

标签: c++ opencv ros point-cloud-library point-clouds

我正在尝试将带有rgb信息的pointcloud从pcl格式转换为cv :: Mat并返回到pcl。我在stackoverflow上找到了convert mat to pointcloud

代码已更新

因此我使用stackoverflow上找到的代码作为起点。现在有以下几点:

//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);

显示上面的图像确保我正确提取颜色(图像通过眼睛与原始图像进行比较)。然后我想将它转换回pointcloud:

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?

附加

即使我使用OpenCVPointCloudColor向所有点cvCloudColor.at<cv::Vec3f>(x,y) = cv::Vec3f(0,0,255);强制使用红色,然后从OpenCVPointCloudColor读取仍会在pcl云中创建错误的颜色信息。

1 个答案:

答案 0 :(得分:1)

我几乎可以肯定你的代码中有一个关于这些函数的错误。我尝试了一个简单的例子,遵循你的范例,它完美地工作(从源代码构建的PCL 1.8,从源代码构建的OpenCV 3.1,g ++ 5.x或g ++ 6.x,Ubuntu 16.10):

<section id="progress-bar-container">
    <div class="container-fluid">
        <div class="progress-bar-bottom" id="progress-bar-bottom"></div>
        <div class="progress-background"></div>
    </div>
</section> 

“初始”和“返回”图像完全相同。在PCL的查看器中,我将我的图像视为点云,当然,z = 10,因为我对其进行了硬编码。您可能应该使用鼠标滚轮缩小并查看整个图像。

要运行此示例,您的工作目录中应该有名为“test.png”的文件。

我很抱歉硬编码的输入文件名并调整为固定分辨率。

尝试一下,如果它在您的系统中有效,请尝试在代码中查找错误。如果它不起作用,可能你的PCL版本太旧甚至坏了。