将点云转换为深度/多通道图像

3
我有一个由立体相机扫描平面表面生成的点云。我已经生成了法线、fpfh等特征,并使用这些信息对点云中的区域进行分类。为了使用更传统的CNN方法,我想将此点云转换为OpenCV中的多通道图像。我将点云折叠到XY平面,并与X轴和Y轴对齐,以便可以为图像创建边界框。
我正在寻找关于如何从点映射到像素的进一步思路。具体而言,我对图像大小感到困惑,以及如何填充每个像素的适当数据。(重叠的点将被平均,空的点将被相应地标记)。由于这是一个无组织的点云,我没有可用的相机参数,我猜测PCL的RangImage类在我的情况下不起作用。
非常感谢您的帮助!
1个回答

1
尝试先创建一个预定大小的空cv::Mat。然后迭代该Mat的每个像素,以确定它应该取什么值。
以下是一些类似于您所描述的代码:
cv::Mat makeImageFromPointCloud(pcl::PointCloud<pcl::PointXYZI>::Ptr cloud, std::string dimensionToRemove, float stepSize1, float stepSize2)
{
    pcl::PointXYZI cloudMin, cloudMax;
    pcl::getMinMax3D(*cloud, cloudMin, cloudMax);

    std::string dimen1, dimen2;
    float dimen1Max, dimen1Min, dimen2Min, dimen2Max;
    if (dimensionToRemove == "x")
    {
        dimen1 = "y";
        dimen2 = "z";
        dimen1Min = cloudMin.y;
        dimen1Max = cloudMax.y;
        dimen2Min = cloudMin.z;
        dimen2Max = cloudMax.z;
    }
    else if (dimensionToRemove == "y")
    {
        dimen1 = "x";
        dimen2 = "z";
        dimen1Min = cloudMin.x;
        dimen1Max = cloudMax.x;
        dimen2Min = cloudMin.z;
        dimen2Max = cloudMax.z;
    }
    else if (dimensionToRemove == "z")
    {
        dimen1 = "x";
        dimen2 = "y";
        dimen1Min = cloudMin.x;
        dimen1Max = cloudMax.x;
        dimen2Min = cloudMin.y;
        dimen2Max = cloudMax.y;
    }

    std::vector<std::vector<int>> pointCountGrid;
    int maxPoints = 0;

    std::vector<pcl::PointCloud<pcl::PointXYZI>::Ptr> grid;

    for (float i = dimen1Min; i < dimen1Max; i += stepSize1)
    {
        pcl::PointCloud<pcl::PointXYZI>::Ptr slice = passThroughFilter1D(cloud, dimen1, i, i + stepSize1);
        grid.push_back(slice);

        std::vector<int> slicePointCount;

        for (float j = dimen2Min; j < dimen2Max; j += stepSize2)
        {
            pcl::PointCloud<pcl::PointXYZI>::Ptr grid_cell = passThroughFilter1D(slice, dimen2, j, j + stepSize2);

            int gridSize = grid_cell->size();
            slicePointCount.push_back(gridSize);

            if (gridSize > maxPoints)
            {
                maxPoints = gridSize;
            }
        }
        pointCountGrid.push_back(slicePointCount);
    }

    cv::Mat mat(static_cast<int>(pointCountGrid.size()), static_cast<int>(pointCountGrid.at(0).size()), CV_8UC1);
    mat = cv::Scalar(0);

    for (int i = 0; i < mat.rows; ++i)
    {
        for (int j = 0; j < mat.cols; ++j)
        {
            int pointCount = pointCountGrid.at(i).at(j);
            float percentOfMax = (pointCount + 0.0) / (maxPoints + 0.0);
            int intensity = percentOfMax * 255;

            mat.at<uchar>(i, j) = intensity;
        }
    }

    return mat;
}

你的代码中 upcloud 和命名空间 upcl 的结构是怎样的? - Cloud Cho
1
修改了答案。对于 passThrough 过滤器,您可以基于此代码编写一个函数:http://pointclouds.org/documentation/tutorials/passthrough.php - brad

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