将pcl::Pointcloud转换为cv::Mat深度图像

3
我正在将这个深度图像转换为 pcl::pointcloud。

enter image description here

使用以下内容:
PointCloud::Ptr PointcloudUtils::RGBDtoPCL(cv::Mat depth_image, Eigen::Matrix3f& _intrinsics)
{
    PointCloud::Ptr pointcloud(new PointCloud);

    float fx = _intrinsics(0, 0);
    float fy = _intrinsics(1, 1);
    float cx = _intrinsics(0, 2);
    float cy = _intrinsics(1, 2);

    float factor = 1;

    depth_image.convertTo(depth_image, CV_32F); // convert the image data to float type 

    if (!depth_image.data) {
        std::cerr << "No depth data!!!" << std::endl;
        exit(EXIT_FAILURE);
    }

    pointcloud->width = depth_image.cols; //Dimensions must be initialized to use 2-D indexing 
    pointcloud->height = depth_image.rows;
    pointcloud->resize(pointcloud->width*pointcloud->height);

#pragma omp parallel for
    for (int v = 0; v < depth_image.rows; v += 4)
    {
        for (int u = 0; u < depth_image.cols; u += 4)
        {
            float Z = depth_image.at<float>(v, u) / factor;

            PointT p;
            p.z = Z;
            p.x = (u - cx) * Z / fx;
            p.y = (v - cy) * Z / fy;

            p.z = p.z / 1000;
            p.x = p.x / 1000;
            p.y = p.y / 1000;

            pointcloud->points.push_back(p);

        }
    }

    return pointcloud;

}

这很好用,我已经在云端上处理了一些内容,现在需要将点云转换回cv :: Mat深度图像。我找不到一个例子,并且对此感到困惑。以上功能的相反操作是什么?
如何将pcl :: pointcloud转换回cv :: mat?
谢谢。

你想让 p.x, p.y, p.z 表示一个浮点像素吗? - zindarod
目标是反转上述函数。因此,从图像到点云,然后再回到完全相同的图像。谢谢! - anti
啊,抱歉,那只是为了测试降采样。我已经用 ++ 替换了它。我正在尝试您的新代码,看起来应该可以工作!但我仍然得到黑色图像。我正在测试各种设置,以便找出问题所在。非常感谢您的帮助。 - anti
类型 = 2,通道数 = 1; - anti
让我们在聊天中继续这个讨论 - zindarod
显示剩余3条评论
2个回答

1

这是未经测试的代码,因为我机器上没有点云。 从你自己的转换代码来看,我假设你的图像是单通道的。

void PCL2Mat(PointCloud::Ptr pointcloud, cv::Mat& depth_image, int original_width, int original_height)
{
    if (!depth_image.empty())
        depth_image.release();

    depth_image.create(original_height, original_width, CV_32F);

    int count = 0;

    #pragma omp parallel for
    for (int v = 0; v < depth_image.rows; ++v)
    {
        for (int u = 0; u < depth_image.cols; ++u)
        {
            depth_image.at<float>(v, u) = pointcloud->points.at(count++).z * 1000;

        }
    }

    depth_image.convertTo(depth_image,CV_8U);

}

谢谢!我正在使用以下代码运行程序:'PCL2Mat(newCloud, newDepth, depth_image.cols, depth_image.rows, depth_image.channels());',但是它给出了一张黑色图片。 - anti
嗯,我没有PointCloud,也不知道您对点云数据进行了哪些处理,所以无法再帮助您更多了。但是,这段代码应该能向您展示从PCL转换为Mat的基本操作。 - zindarod
这是为了测试目的,直接转换回来而没有进行处理。可能是通道的问题吗?再次感谢。 - anti

0

我不熟悉OpenCV的方法,但如果你做了一些使你的点云变得无结构的事情,那么你的处理过程可能是这样的

% rescale the points by 1000
p.x = p.x * 1000; p.y = p.y * 1000; p.z = p.z * 1000;

% project points on image plane and correct center point + factor
 image_p.x = ( p.x * fx / p.z  -cf ) * factor;
 image_p.y = ( p.y * fy / p.z  -cy ) * factor;

现在根据您对点云的处理方式,点可能无法完全映射到图像矩阵像素中心点(或某些应用程序的左上角),或者您可能会丢失点-> NaN / 0值像素。如何处理取决于您,但最简单的方法是将image_p.x和image_p.y转换为整数,确保它们在图像边界内,并设置

depth_image.at<float>(image_p.y, image_p.x) = p.Z;`

点不是按顺序的吗?它们不能只是在循环中赋值z值吗? - simplename

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接