【问题标题】:Projecting pointcloud on its eigenvectors在其特征向量上投影点云
【发布时间】:2020-01-03 12:52:59
【问题描述】:

参考我另一个 question 上的答案,我尝试将两个点云投影到它们的特征向量。

我正在使用c++PointCloudLibrary。不幸的是,我找不到关于 PCA 类的好的文档。

model_cloud 是我的点云时,我尝试了以下方法来进行投影:

pcl::PCA<pcl::PointNormal> pca;
pca.setInputCloud(model_cloud_ptr);
pcl::PointCloud<pcl::PointNormal> projection;
pca.project(model_cloud_nt, projection);

Eigen::Matrix3f ev_M = pca.getEigenVectors();

我不明白为什么我必须设置这个inputCloud,然后给出一个特定的云作为投影的参数。我只想将 PCA 降到 2D 并获得特征向量。

谁能帮助我?非常感谢!

【问题讨论】:

    标签: c++ pca point-cloud-library


    【解决方案1】:

    我相信您正在尝试将云放入其特征空间(orientedGolden 是特征空间中的云)。这是可以做到的:

    pcl::PCA<pcl::PointXYZ> pcaGolden;
    pcl::PointCloud<pcl::PointXYZ>::Ptr orientedGolden(new pcl::PointCloud<pcl::PointXYZ>);
    pcaGolden.setInputCloud(goldenCloud);
    pcaGolden.project(*goldenCloud, *orientedGolden);
    
    //this is the scale factor described in the other question
    pcl::PointXYZ goldenMin, goldenMax;
    pcl::getMinMax3D(*orientedGolden, goldenMin, goldenMax);
    double scale = goldenMax.x - goldenMin.x;
    

    说明:PCA 用于计算变异的均值轴和主轴。来自 PCA 的特征向量可以作为旋转矩阵直接插入到变换矩阵中,因为它们总是相互正交的(即表示一个框架)。还取中点,以便与向量组合,可以制作一个完整的变换矩阵,该矩阵(当应用于目标云时)将移动它,使其平均值位于原点,并且其主轴变化与笛卡尔坐标对齐系统 (xyz)。这对于获得所谓的定向边界框(我认为您在另一个问题中尝试做的事情)很有用,这是围绕其特征空间中的云计算的边界框。定向边界框优于一般边界框的原因在于,尽管对给定的云进行了任意数量的旋转,但对于给定的云,它将保持不变,而标准边界框的尺寸会有所不同。

    项目功能:

    这个:

    pcl::PointCloud<pcl::PointXYZ>::Ptr orientedGolden(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::PCA<pcl::PointXYZ> pcaGolden;
    pcaGolden.setInputCloud(goldenCloud);
    pcaGolden.project(*goldenCloud, *orientedGolden);
    

    相当于这个:

    pcl::PointCloud<pcl::PointXYZ>::Ptr orientedGolden(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::PCA<pcl::PointXYZ> pcaGolden;
    pcaGolden.setInputCloud(goldenCloud);
    Eigen::Matrix3f goldenEVs_Dir = pcaGolden.getEigenVectors();
    Eigen::Vector4f goldenMidPt = pcaGolden.getMean();
    Eigen::Matrix4f goldenTransform = Eigen::Matrix4f::Identity();
    goldenTransform.block<3, 3>(0, 0) = goldenEVs_Dir;
    goldenTransform.block<4, 1>(0, 3) = goldenMidPt;
    pcl::transformPointCloud(*goldenCloud, *orientedGolden, goldenTransform.inverse());
    

    【讨论】:

      【解决方案2】:

      要计算主成分(计算特征向量),您需要:

      pcl::PCA<pcl::PointXYZ> pca(cloud); // computed in the constructor
      Eigen::Matrix3f eigen_vectors = pca.getEigenVectors(); // returns computed eigen vectors as a matrix
      

      或者(getEigenVectors()):

      pcl::PCA<pcl::PointNormal> pca;
      pca.setInputCloud(cloud);
      Eigen::Matrix3f eigen_vectors = pca.getEigenVectors(); // pca computed here
      

      这两种方法都是合法的,此时,您已经计算了投影(主成分)。请注意,这是 3D 到 3D 投影(基本上是旋转)。 2D 只是忽略第三轴的结果(方差最小)。您可以通过以下方式获取相关轴(特征向量):

      Eigen::Vector3f x_axis = eigen_vector.col(0);
      Eigen::Vector3f y_axis = eigen_vector.col(1);
      

      计算投影后,您可以将其应用于任何云。

      pca.project(cloud, projection);  // project the cloud that was used to calculate the projection
      pca.project(another_cloud, projection); // project any other cloud
      

      最后一个例子:

      pcl::PCA<pcl::PointNormal> pca;
      pca.setInputCloud(cloud_a);
      pca.project(cloud_b, projection);  // calculate projection based on cloud_a, and apply the projection to cloud_b 
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-12-30
        相关资源
        最近更新 更多