【问题标题】:How to convert cv::Mat to pcl::pointcloud如何将 cv::Mat 转换为 pcl::pointcloud
【发布时间】:2015-12-07 20:55:27
【问题描述】:

如何从 opencv Mat 点云到 pcl::pointcloud?颜色对我来说并不重要,只有点本身。

【问题讨论】:

    标签: opencv converter point-cloud-library


    【解决方案1】:

    你可以这样做:

    pcl::PointCloud<pcl::PointXYZ>::Ptr SimpleOpenNIViewer::MatToPoinXYZ(cv::Mat OpencVPointCloud)
             {
                 /*
                 *  Function: Get from a Mat to pcl pointcloud datatype
                 *  In: cv::Mat
                 *  Out: pcl::PointCloud
                 */
    
                 //char pr=100, pg=100, pb=100;
                 pcl::PointCloud<pcl::PointXYZ>::Ptr point_cloud_ptr(new pcl::PointCloud<pcl::PointXYZ>);//(new pcl::pointcloud<pcl::pointXYZ>);
    
                 for(int i=0;i<OpencVPointCloud.cols;i++)
                 {
                    //std::cout<<i<<endl;
    
                    pcl::PointXYZ point;
                    point.x = OpencVPointCloud.at<float>(0,i);
                    point.y = OpencVPointCloud.at<float>(1,i);
                    point.z = OpencVPointCloud.at<float>(2,i);
    
                    // when color needs to be added:
                    //uint32_t rgb = (static_cast<uint32_t>(pr) << 16 | static_cast<uint32_t>(pg) << 8 | static_cast<uint32_t>(pb));
                    //point.rgb = *reinterpret_cast<float*>(&rgb);
    
                    point_cloud_ptr -> points.push_back(point);
    
    
                 }
                 point_cloud_ptr->width = (int)point_cloud_ptr->points.size();
                 point_cloud_ptr->height = 1;
    
                 return point_cloud_ptr;
    
             }
    

    反之亦然

     cv::Mat MVW_ICP::PoinXYZToMat(pcl::PointCloud<pcl::PointXYZ>::Ptr point_cloud_ptr){
    
         cv::Mat OpenCVPointCloud(3, point_cloud_ptr->points.size(), CV_64FC1);
         for(int i=0; i < point_cloud_ptr->points.size();i++){
            OpenCVPointCloud.at<double>(0,i) = point_cloud_ptr->points.at(i).x;
            OpenCVPointCloud.at<double>(1,i) = point_cloud_ptr->points.at(i).y;
            OpenCVPointCloud.at<double>(2,i) = point_cloud_ptr->points.at(i).z;
        }
    
        return OpenCVPointCloud;
    }
    

    【讨论】:

    • 这仅适用于 unorganized 云。
    【解决方案2】:

    要将 Kinect 传感器捕获并由 depthMat 表示的范围图像转换为 pcl::PointCloud,您可以尝试此功能。标定参数为here使用的参数。

    {
        pcl::PointCloud<pcl::PointXYZ>::Ptr MatToPoinXYZ(cv::Mat depthMat)
    {
        pcl::PointCloud<pcl::PointXYZ>::Ptr ptCloud (new pcl::PointCloud<pcl::PointXYZ>);
    
    // calibration parameters
        float const fx_d = 5.9421434211923247e+02;
        float const fy_d = 5.9104053696870778e+02;
        float const cx_d = 3.3930780975300314e+02;
        float const cy_d = 2.4273913761751615e+02;
    
        unsigned char* p = depthMat.data;
        for (int i = 0; i<depthMat.rows; i++)
        {
            for (int j = 0; j < depthMat.cols; j++)
            {
                float z = static_cast<float>(*p);
                pcl::PointXYZ point;
                point.z = 0.001 * z;
                point.x = point.z*(j - cx_d)  / fx_d;
                point.y = point.z *(cy_d - i) / fy_d;
                ptCloud->points.push_back(point);
                ++p;
            }
        }
        ptCloud->width = (int)depthMat.cols; 
        ptCloud->height = (int)depthMat.rows; 
    
        return ptCloud;
    
    }
    }
    

    【讨论】:

    • 这是一个慢速函数,可以通过更少的乘法和更多的 for 循环之外的次数来加速。在函数 1/fx_d 和 1/fy_d 之前执行 fx_d 和 fy_d,然后将其相乘。试试看!
    • @MartijnvanWezel 感谢您的评论。我编辑了答案。
    • points.push_back也许我们可以根据图像大小定义具有预定义大小的点云而不重新分配内存?
    猜你喜欢
    • 2017-06-08
    • 2018-03-24
    • 2015-03-26
    • 1970-01-01
    • 2019-05-15
    • 1970-01-01
    • 2012-10-22
    • 2018-07-17
    • 1970-01-01
    相关资源
    最近更新 更多