Referring to the answer on my other question I tried to project two pointclouds to their eigenvectors.
I am using c++
and the PointCloudLibrary. Unfortunately I wasn't able to find a good documentation of the PCA
class.
I tried the following to do the projectiong while model_cloud
is my pointcloud:
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();
I don't understand why I have to set this inputCloud
but then give a specific cloud as parameter for the projection. I just want to PCA it down to 2D and get the Eigenvectors.
Can anyone help me? Thanks alot!
I believe that you are trying to put a cloud into it's eigenspace (orientedGolden is the cloud in eigenspace). This is how that could be done:
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;
Explanation: PCA is used to calculate the mean and primary axes of variation. The eigenvectors from PCA can be directly inserted into a transformation matrix as a rotation matrix because they are always mutually orthogonal (ie represent a frame). The midpoint is also taken so that in combination with the vectors, a full transformation matrix can be made which (when applied to the target cloud) will move it such that its mean is on origin and its primary axes of variation align with the cartesian coordinate system (xyz). This can be useful to get what is called an oriented bounding box (what I think you are trying to do in your other question), which is the bounding box calculated about a cloud in its eigen space. The reason an oriented bounding box is better than a general bound box is that it will remain the same for a given cloud despite any number of rotations to that cloud whereas a standard bounding box will vary in dimensions.
Project function:
This:
pcl::PointCloud<pcl::PointXYZ>::Ptr orientedGolden(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PCA<pcl::PointXYZ> pcaGolden;
pcaGolden.setInputCloud(goldenCloud);
pcaGolden.project(*goldenCloud, *orientedGolden);
Is equivalent to this:
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());