pcl源码解读与实践--pca

25 篇文章 17 订阅

在pcl/common自带pca计算,其主要功能包括计算特征值、特征向量、投影、reconstruction。

特征值特征向量计算,放在initCompute ()函数中,pca核心代码,源码如下:
template<typename PointT> bool
pcl::PCA<PointT>::initCompute () 
{
  if(!Base::initCompute ())
  {
    PCL_THROW_EXCEPTION (InitFailedException, "[pcl::PCA::initCompute] failed");
  }
  if(indices_->size () < 3)
  {
    PCL_THROW_EXCEPTION (InitFailedException, "[pcl::PCA::initCompute] number of points < 3");
  }
  
  // Compute mean
  mean_ = Eigen::Vector4f::Zero ();
  compute3DCentroid (*input_, *indices_, mean_);  
  // Compute demeanished cloud
  Eigen::MatrixXf cloud_demean;
  demeanPointCloud (*input_, *indices_, mean_, cloud_demean);
  assert (cloud_demean.cols () == int (indices_->size ()));
  // Compute the product cloud_demean * cloud_demean^T
  const Eigen::Matrix3f alpha = (1.f / (float (indices_->size ()) - 1.f))
                                  * cloud_demean.topRows<3> () * cloud_demean.topRows<3> ().transpose ();
  
  // Compute eigen vectors and values
  Eigen::SelfAdjointEigenSolver<Eigen::Matrix3f> evd (alpha);
  // Organize eigenvectors and eigenvalues in ascendent order
  for (int i = 0; i < 3; ++i)
  {
    eigenvalues_[i] = evd.eigenvalues () [2-i];
    eigenvectors_.col (i) = evd.eigenvectors ().col (2-i);
  }
  // If not basis only then compute the coefficients
  if (!basis_only_)
    coefficients_ = eigenvectors_.transpose() * cloud_demean.topRows<3> ();
  compute_done_ = true;
  return (true);
}
//通过以下函数获取特征值,特征向量,点云中心(均值),系数,投影到局部坐标系下,reconstruction(我也不知道这个函数是什么意思)
 Eigen::Matrix3f& getEigenVectors ()  
 Eigen::Vector3f& getEigenValues () 
 Eigen::Vector4f& getMean () 
 Eigen::MatrixXf& getCoefficients () 
void project (const PointCloud& input,PointCloud&projection); 
void project (const PointT& input, PointT& projection) 
 
void reconstruct (const PointCloud& projection, PointCloud& input)
应用

//功能求解点云特征值特征向量并投影

#include <iostream>

#include<pcl/io/pcd_io.h>
#include<pcl/point_types.h>
#include<pcl/point_cloud.h>
#include<pcl/common/pca.h>

#include<Eigen/core>

typedef pcl::PointXYZ point;
typedef pcl::PointCloud<point> cloud;
int main()
{
    cloud cloud_in;
    if (pcl::io::loadPCDFile<point>("plane.pcd", cloud_in) < 0)
    {
        PCL_ERROR("读取文件错误");
        return -1;
    }

    pcl::PCA<point>pca;
    pca.setInputCloud(cloud_in.makeShared());
    //求特征值与其对应的特征向量,矩阵的列向量为特征向量
    Eigen::Vector3f eigen_values;
    eigen_values=pca.getEigenValues();
    std::cout << eigen_values << std::endl;
    Eigen::Matrix3f eigen_vector;
    eigen_vector=pca.getEigenVectors();
    std::cout << eigen_vector << std::endl;

    //将点或者点云投影到特征向量(正交)建立的局部坐标系下
    cloud  cloud_out(cloud_in);
    cloud_out.clear();
    point p;
    p.getVector3fMap();
    pca.project(cloud_in, cloud_out);
    pcl::io::savePCDFile<point>("plane_projected.pcd", cloud_out);

    std::cout << "Hello World!\n";
}

实验结果:
特征值与特征向量
在这里插入图片描述
实验数据为平面点云,理论上投影后点云平面应该与坐标轴平面平行:
左侧为投影后点云,pca得到的局部坐标系的原点为(0,0,0),所以二者有一定的偏离量。
在这里插入图片描述
可以发现投影后,点云平面与坐标轴平面重合,理论与实验结果符合。
在这里插入图片描述

  • 5
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值