PCL求取点云的均值、协方差、PCA

PCL求取点云的均值、协方差、PCA

原理

  1. 均值
  2. 协方差
    • 正常的协方差
    • 归一化的,协方差除以总共的点云个数
  3. PCA
    可以理解为讲协方差分解成三个轴的法向量,就是SVD获取了特征向量与特征值
    • 特征向量:反应了三维物体三个轴的方向,vPCA的行向量就是特征向量。三行代表三个。
    • 特征值:大小反应各个轴的分布情况,DigV大的对应的特征向量是主轴,小的对应的特征向量可能是平面法向量。使用eigen计算

代码实现

#include <iomanip>
#include <fstream>
#include <pcl/io/pcd_io.h>
#include <pcl/filters/voxel_grid.h>
#include <Eigen/Core>
#include <pcl/common/transforms.h>
#include <pcl/io/pcd_io.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/keypoints/uniform_sampling.h>
#include <pcl/common/common.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/features/normal_3d_omp.h> //使用OMP需要添加的头文件
#include <pcl/filters/passthrough.h>    //分块使用
#include <pcl/common/transforms.h>
int main(int argc, char **argv)
{
    //加载整体地图
    pcl::PointCloud<pcl::PointXYZL>::Ptr pointCloudLabelPtr(new pcl::PointCloud<pcl::PointXYZL>); //所有的点云地图
    std::string frameFile = "/home/wgq/PrioriMapLoc/test/testdata/000253.pcd";
    pcl::io::loadPCDFile<pcl::PointXYZL>(frameFile, *pointCloudLabelPtr);
    std::cout << "frameFile 加载:" << frameFile << "点云数量数:" << pointCloudLabelPtr->size() << std::endl;

    pcl::PointXYZL min, max;
    pcl::getMinMax3D(*pointCloudLabelPtr, min, max);
    std::cout << "x:[" << min.x << "," << max.x << "]" << std::endl;
    std::cout << "y:[" << min.y << "," << max.y << "]" << std::endl;
    std::cout << "z:[" << min.z << "," << max.z << "]" << std::endl;

    //计算均值mean和协方差cov
    {
        Eigen::Vector4f mean;
        Eigen::Matrix3f cov;
        pcl::compute3DCentroid(*pointCloudLabelPtr, mean);            //输入点云,输出均值
        pcl::computeCovarianceMatrix(*pointCloudLabelPtr, mean, cov); //输入点云、均值,输出协方差矩阵
        std::cout << "mean:" << mean.transpose() << std::endl
                  << "cov:" << cov << std::endl
                  << "cov1:" << cov / pointCloudLabelPtr->size() << std::endl
                  << std::endl;
    }
    {
        Eigen::Vector4f mean;
        Eigen::Matrix3f cov;
        pcl::computeMeanAndCovarianceMatrix(*pointCloudLabelPtr, cov, mean); //输入点云,输出均值,协方差矩阵
        std::cout << "mean:" << mean.transpose() << std::endl
                  << "cov1:" << cov << std::endl
                  << std::endl;
    }

    // PCA计算主成分
    {
        Eigen::Vector4f mean;
        Eigen::Matrix3f cov;
        pcl::compute3DCentroid(*pointCloudLabelPtr, mean);                      //输入点云,输出均值
        pcl::computeCovarianceMatrixNormalized(*pointCloudLabelPtr, mean, cov); //输入点云、均值,输出归一化的协方差矩阵,1/n 为总点数
        std::cout << "mean:" << mean.transpose() << std::endl
                  << "cov1:" << cov << std::endl
                  << std::endl;

        Eigen::Matrix3f vPCA;                               //特征向量,行向量排列,第一行对应的特征值最小
        Eigen::Vector3f DigV;                               //特征值,其中特征值最小的为第一个
        Eigen::Matrix3f DigM = Eigen::Matrix3f::Identity(); //对角矩阵
        Eigen::SelfAdjointEigenSolver<Eigen::Matrix3f> eigen_solver(cov, Eigen::ComputeEigenvectors);
        vPCA = eigen_solver.eigenvectors();
        DigV = eigen_solver.eigenvalues();

        std::cout << "vPCA:" << vPCA.transpose() << std::endl
                  << "DigV:" << DigV.transpose() << std::endl
                  << std::endl;

        DigM(0, 0) = DigV.x();
        DigM(1, 1) = DigV.y();
        DigM(2, 2) = DigV.z();
        // SVD分解,特征值最大的特征向量值对应主轴,最小值对应法向量如果是平面
        std::cout << "cov = vPCA*Dig*vPCAT" << vPCA * DigM * vPCA.transpose() << std::endl;
    }

    return 0;
}
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用PCL库中的`computeCentroid()`函数求取点云的质心,并使用可视化工具(如PCL Visualizer)将其可视化。下面是一个示例代码: ```c++ #include <iostream> #include <pcl/io/pcd_io.h> #include <pcl/point_types.h> #include <pcl/visualization/pcl_visualizer.h> int main(int argc, char** argv) { if (argc < 2) { std::cerr << "Usage: " << argv[0] << " point_cloud.pcd" << std::endl; return -1; } // Load point cloud data from file pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); if (pcl::io::loadPCDFile<pcl::PointXYZ>(argv[1], *cloud) == -1) { std::cerr << "Failed to load point cloud file " << argv[1] << std::endl; return -1; } // Compute the centroid of the point cloud Eigen::Vector4f centroid; pcl::compute3DCentroid(*cloud, centroid); // Print the centroid coordinates std::cout << "Centroid: (" << centroid[0] << ", " << centroid[1] << ", " << centroid[2] << ")" << std::endl; // Visualize the point cloud and its centroid pcl::visualization::PCLVisualizer viewer("Point Cloud Viewer"); viewer.setBackgroundColor(0.0, 0.0, 0.0); viewer.addPointCloud<pcl::PointXYZ>(cloud); viewer.addSphere<pcl::PointXYZ>(pcl::PointXYZ(centroid[0], centroid[1], centroid[2]), 0.1, "centroid"); viewer.spin(); return 0; } ``` 在此示例代码中,我们首先加载点云文件,然后使用`compute3DCentroid()`函数计算点云的质心。我们还将质心作为一个小球添加到可视化工具中,以便更好地展示。最后,我们使用`spin()`函数进入可视化循环,直到用户关闭可视化窗口为止。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值