首页 > 其他分享 >PCL_PCA点云主方向分析

PCL_PCA点云主方向分析

时间:2023-06-15 18:23:40浏览次数:40  
标签:tm PCA 点云主 矩阵 covariance eigenVectorsPCA PCL include Eigen

1.使用PCA计算点云主方向,并进行矫正


#include"vtkAutoInit.h"
#ifndef  VTK_MODULE_INIT
VTK_MODULE_INIT(vtkRenderingOpenGL); // VTK was built with vtkRenderingOpenGL
VTK_MODULE_INIT(vtkInteractionStyle);
VTK_MODULE_INIT(vtkRenderingFreeType);
#endif
#include<vtkRenderingFreeTypeModule.h> //屏蔽vtk警告显示窗口
#include <iostream>
#include <string>
#include <pcl/io/pcd_io.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <Eigen/Core>
#include <pcl/common/transforms.h>
#include <pcl/common/common.h>
#include <pcl/visualization/pcl_visualizer.h>

using namespace std;
typedef pcl::PointXYZ PointType;

int main(int argc, char **argv)
{
	pcl::PointCloud<PointType>::Ptr cloud(new pcl::PointCloud<PointType>());

	//std::cout << "请输入需要显示的点云文件名:";
	//std::string fileName("rabbit");
	//getline(cin, fileName);
	//fileName += ".pcd";
	std::string fileName(argv[1]);
	pcl::io::loadPCDFile(fileName, *cloud);

	Eigen::Vector4f pcaCentroid;
	pcl::compute3DCentroid(*cloud, pcaCentroid);//计算点云质心
	Eigen::Matrix3f covariance;
	pcl::computeCovarianceMatrixNormalized(*cloud, pcaCentroid, covariance);//计算目标点云协方差矩阵
	Eigen::SelfAdjointEigenSolver<Eigen::Matrix3f> eigen_solver(covariance, Eigen::ComputeEigenvectors);//构造一个特定的自伴随矩阵类便于后续分解
	Eigen::Matrix3f eigenVectorsPCA = eigen_solver.eigenvectors();//计算特征向量
	Eigen::Vector3f eigenValuesPCA = eigen_solver.eigenvalues();//计算特征值
	eigenVectorsPCA.col(2) = eigenVectorsPCA.col(0).cross(eigenVectorsPCA.col(1)); //校正主方向间垂直
	eigenVectorsPCA.col(0) = eigenVectorsPCA.col(1).cross(eigenVectorsPCA.col(2));
	eigenVectorsPCA.col(1) = eigenVectorsPCA.col(2).cross(eigenVectorsPCA.col(0));

	std::cout << "特征值va(3x1):\n" << eigenValuesPCA << std::endl;
	std::cout << "特征向量ve(3x3):\n" << eigenVectorsPCA << std::endl;
	std::cout << "质心点(4x1):\n" << pcaCentroid << std::endl;
	/*
	// 另一种计算点云协方差矩阵特征值和特征向量的方式:通过pcl中的pca接口,如下,这种情况得到的特征向量相似特征向量
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloudPCAprojection (new pcl::PointCloud<pcl::PointXYZ>);
	pcl::PCA<pcl::PointXYZ> pca;
	pca.setInputCloud(cloudSegmented);
	pca.project(*cloudSegmented, *cloudPCAprojection);
	std::cerr << std::endl << "EigenVectors: " << pca.getEigenVectors() << std::endl;//计算特征向量
	std::cerr << std::endl << "EigenValues: " << pca.getEigenValues() << std::endl;//计算特征值
	*/
	Eigen::Matrix4f tm = Eigen::Matrix4f::Identity();
	Eigen::Matrix4f tm_inv = Eigen::Matrix4f::Identity();
	tm.block<3, 3>(0, 0) = eigenVectorsPCA.transpose();   //R.
	tm.block<3, 1>(0, 3) = -1.0f * (eigenVectorsPCA.transpose()) *(pcaCentroid.head<3>());//  -R*t
	tm_inv = tm.inverse();

	std::cout << "变换矩阵tm(4x4):\n" << tm << std::endl;
	std::cout << "逆变矩阵tm'(4x4):\n" << tm_inv << std::endl;


	pcl::PointCloud<PointType>::Ptr transformedCloud(new pcl::PointCloud<PointType>);
	pcl::transformPointCloud(*cloud, *transformedCloud, tm);

	//x方向与z方向互换
	for (auto it = transformedCloud->begin(); it != transformedCloud->end(); it++)
	{
		float temp_x = it->x;
		float temP_z = it->z;
		it->x = temP_z;
		it->z = temp_x;
	}
	pcl::io::savePCDFileBinary("transformedCloud.pcd", *transformedCloud);
}

2 computeCovarianceMatrixNormalized 计算给点云的协方差矩阵

/** \简介计算给定点集的3x3协方差矩阵归一化。
     *结果作为eigen :: matrix3f返回。
     *归一化意味着每个条目都已除以点云中的点数。
     *对于少量的积分,或者如果要明确的样品变量,请使用ComputeCovarianCematrix
     *并用1 /(n-1)缩放协方差矩阵,其中n是用于计算的点数
     *协方差矩阵,并由ComputeCovarianCematrix函数返回。
     * \ param [in]云输入点云
     * \ param [in] centroid云中点集的质心
     * \ param [out] covariance_matrix结果3x3协方差矩阵
     * \返回数量的有效点用于确定协方差矩阵。
     *如果有密集的点云,则与输入云的大小相同。
     * \ group common
     */

/** \brief Compute normalized the 3x3 covariance matrix of a given set of points.

    * The result is returned as a Eigen::Matrix3f.
    * Normalized means that every entry has been divided by the number of points in the point cloud.
    * For small number of points, or if you want explicitly the sample-variance, use computeCovarianceMatrix
    * and scale the covariance matrix with 1 / (n-1), where n is the number of points used to calculate
    * the covariance matrix and is returned by the computeCovarianceMatrix function.
    * \param[in] cloud the input point cloud
    * \param[in] centroid the centroid of the set of points in the cloud
    * \param[out] covariance_matrix the resultant 3x3 covariance matrix
    * \return number of valid points used to determine the covariance matrix.
    * In case of dense point clouds, this is the same as the size of input cloud.
    * \ingroup common
    */
  template <typename PointT, typename Scalar> inline unsigned int
  computeCovarianceMatrixNormalized (const pcl::PointCloud<PointT> &cloud,
                                     const Eigen::Matrix<Scalar, 4, 1> &centroid,
                                     Eigen::Matrix<Scalar, 3, 3> &covariance_matrix);
                                     

3 协方差矩阵

https://www.zhihu.com/tardis/zm/art/37609917?source_id=1005
https://zhuanlan.zhihu.com/p/464822791

4 自伴随矩阵

https://zhuanlan.zhihu.com/p/550779050
Eigen::SelfAdjointEigenSolver<Eigen::Matrix3f> eigen_solver(covariance, Eigen::ComputeEigenvectors);//

构造一个自伴随举证类便于后续分解

5.总体算法思路分析

1首先将点云归一化后计算其3*3协方差矩阵
2.创建一个伴随矩阵的,并基于次对于分解得到特征向量以及值
3.由于特征矩阵只有x\y\z三个方向需要将其矫正垂直
4.后续这一步已经完全看不懂了

	Eigen::Matrix4f tm = Eigen::Matrix4f::Identity();
	Eigen::Matrix4f tm_inv = Eigen::Matrix4f::Identity();
	tm.block<3, 3>(0, 0) = eigenVectorsPCA.transpose();   //R 计算PCA矩阵的转置矩阵
	tm.block<3, 1>(0, 3) = -1.0f * (eigenVectorsPCA.transpose()) *(pcaCentroid.head<3>());//  -R*t
	tm_inv = tm.inverse();

标签:tm,PCA,点云主,矩阵,covariance,eigenVectorsPCA,PCL,include,Eigen
From: https://www.cnblogs.com/codeAndlearn/p/17483736.html

相关文章

  • 如何优化深度克隆 deepclone
    普通克隆的方式 1.大部分会使用序列化和反序列化的方式,缺点:这种方式不会对对象中的函数或者Map对象进行深度克隆。constresult=JSON.parse(JSON.stringify(value)) 2.手写一个deepclone函数 //创建可回收map集合来处理环形引用的情况例如:obj.c=objconstc......
  • 机器学习之——线性判别分析(LDA), 主成分分析(PCA)
    前言:    第二篇的文章中谈到,和部门老大一宁出去outing的时候,他给了我相当多的机器学习的建议,里面涉及到很多的算法的意义、学习方法等等。一宁上次给我提到,如果学习分类算法,最好从线性的入手,线性分类器最简单的就是LDA,它可以看做是简化版的SVM,如果想理解SVM这种分类器,那理解LDA......
  • delphi通过TNetHttpClient监测小红书笔记有无新增评论
    一、实现原理及步骤 每隔一定时间间隔(比如2分钟),抓取特定笔记ID的全部评论,统计出评论数量及子评论数量,与前一次抓取的数量比较,如数量增加,说明有新增评论。然后通过排序评论,找出最新添加的评论。二、技术要点1、评论接口https://edith.xiaohongshu.com/api/sns/web/v2/comment......
  • c# HttpClient超时重试
    //调用方式3秒后超时重试2次.netframework4.5HttpMessageHandlerhandler=newTimeoutHandler(2,3000);using(varclient=newHttpClient(handle......
  • post请求方式 - 抖音生活服务 使用restTemplate而不使用httpClient
    publicstaticStringdoPostForJson(Stringurl,Stringjson,StringbyteAuthorization){RestTemplaterestTemplate=newRestTemplate();logger.info("restTemplateinvokepostmethod.url:[{}],json:[{}]",url,json);long......
  • HttpClient的使用
    一般的情况下我们都是使用IE或者Navigator浏览器来访问一个WEB服务器,用来浏览页面查看信息或者提交一些数据等等。所访问的这些页面有的仅仅是一些普通的页面,有的需要用户登录后方可使用,或者需要认证以及是一些通过加密方式传输,例如HTTPS。目前我们使用的浏览器处理这些情况都不会......
  • httpclient in .net _ 压缩
     压缩 优势: 小带宽,更快的响应 压缩格式gzip,deflate(普遍压缩格式)  how获取压缩文件?Accept-Encoding:设置为压缩格式SocketsHttpHandler:启用自动解压 how发送压缩文件?client:压缩requestbody内置stream:GZipStream,DeflateStreamContent-......
  • Java中HttpClientUtil工具类
     HttpClientUtil包含get和post方法。发送HttpPost或HttpGet请求一共三个步骤:1、创建CloseableHttpClient对象,用于执行excute方法2、创建HttpPost或者HttpGet请求对象3、执行请求,判断返回状态,接收响应对象  publicclassHttpClientUtil{/****编码集*/......
  • Java中HttpClientUtil工具类
     HttpClientUtil包含get和post方法。发送HttpPost或HttpGet请求一共三个步骤:1、创建CloseableHttpClient对象,用于执行excute方法2、创建HttpPost或者HttpGet请求对象3、执行请求,判断返回状态,接收响应对象  publicclassHttpClientUtil{/****编码集*/......
  • Java中HttpClientUtil工具类
    ​ HttpClientUtil包含get和post方法。发送HttpPost或HttpGet请求一共三个步骤:1、创建CloseableHttpClient对象,用于执行excute方法2、创建HttpPost或者HttpGet请求对象3、执行请求,判断返回状态,接收响应对象  publicclassHttpClientUtil{/****编码集......