我正在尝试将带有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云中创建错误的颜色信息。
答案 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版本太旧甚至坏了。