for a mathematical description of the fast point cloud histogram (FPFH) feature, do not introduce too much here, you can view the FPFH. You can also view the PCL's official website, the Chinese version can directly search PCL China FPFH.
Main program
First or a bunch of header files (of course, a good long file is useless here, can be deleted by itself)
#include <pcl/io/pcd_io.h> #include <ctime> #include <Eigen/Core> #include <pcl/point_types.h > #include <pcl/point_cloud.h> #include <pcl/features/fpfh.h> #include <pcl/registration/ia_ ransac.h> #include <pcl/features/normal_3d.h> #include <pcl/kdtree/kdtree_flann.h> #include <pcl/ visualization/pcl_visualizer.h> #include <boost/thread/thread.hpp> #include <pcl/features/fpfh_omp.h >//OMP (multi-core parallel computing) with FPFH accelerated calculation #include <pcl/registration/correspondence_estimation.h> #include <pcl/ Registration/correspondence_rejection_features.h>//Feature error correlation removal #include <pcl/registration/correspondence_ rejection_sample_consensus.h>//Random sampling consistency removal #include <pcl/filters/voxel_grid.h> #include <pcl/filters/ Approximate_voxel_grid.h
For convenience Remember:
using namespace std;
typedef PCL::P OINTCLOUD<PCL::P ointxyz> pointcloud;
typedef PCL::P ointcloud<pcl::normal> pointnormal;
typedef PCL::P ointcloud<pcl::fpfhsignature33> fpfhfeature;
To use FPFP feature matching, declare a function that calculates the FPFH feature point:
Fpfhfeature::P tr compute_fpfh_feature (pointcloud::P tr INPUT_CLOUD,PCL::SEARCH::KDTREE<PCL::P ointxyz>::P TR
Tree) {//normal vector pointnormal::P tr point_normal (new pointnormal);
PCL::NORMALESTIMATION<PCL::P ointxyz,pcl::normal> est_normal;
Est_normal.setinputcloud (Input_cloud);
Est_normal.setsearchmethod (tree);
Est_normal.setksearch (10);
Est_normal.compute (*point_normal);
FPFH estimated fpfhfeature::P tr fpfh (new fpfhfeature);
PCL::FPFHESTIMATION<PCL::P ointxyz,pcl::normal,pcl::fpfhsignature33> est_target_fpfh;
PCL::FPFHESTIMATIONOMP<PCL::P ointxyz,pcl::normal,pcl::fpfhsignature33> est_fpfh; Est_fpfh.setnumberofthreads (4);
Specify 4-core calculations//PCL::SEARCH::KDTREE<PCL::P ointxyz>::P tr tree4 (new PCL::SEARCH::KDTREE<PCL::P ointxyz> ());
Est_fpfh.setinputcloud (Input_cloud);
Est_fpfh.setinputnormals (Point_normal);
Est_fpfh.setsearchmethod (tree);Est_fpfh.setksearch (10);
Est_fpfh.compute (*FPFH);
return FPFH; }
As can be seen, in the calculation of FPFH features, the first need to calculate the point set of the normal vector (normal vector is a point cloud is a very important feature, should be handled alone, only here for convenience, less write two lines of code, packaged in the calculation of the FPFH feature), based on the calculated normal vector, the calculation of FPFH characteristics. When calculating the FPFH feature, the number of neighbor points is not easy to get too large, otherwise a result of the increase in computational capacity, two will make the calculation of fpfh loss of meaning (through other features, too large set of neighbors can not reflect the local characteristics).
Main function:
int main (int argc, char **argv) {if (ARGC < 3) {cout<< "Please input-the POINTC
Loud "<<endl;
return-1;
} clock_t Start,end,time;
start = Clock ();
Pointcloud::P tr Source (new Pointcloud);
Pointcloud::P tr Target (new Pointcloud);
PCL::SEARCH::KDTREE<PCL::P ointxyz>::P tr Tree (new PCL::SEARCH::KDTREE<PCL::P ointxyz> ());
Fpfhfeature::P TR source_fpfh = Compute_fpfh_feature (Source,tree);
Fpfhfeature::P TR target_fpfh = Compute_fpfh_feature (Target,tree); Aligned (takes up most of the running time) PCL::SAMPLECONSENSUSINITIALALIGNMENT<PCL::P ointxyz, PCL::P ointxyz, pcl::fpfhsignature33> SA
C_ia;
Sac_ia.setinputsource (source);
Sac_ia.setsourcefeatures (SOURCE_FPFH);
Sac_ia.setinputtarget (target);
Sac_ia.settargetfeatures (TARGET_FPFH);
Pointcloud::P tr align (new pointcloud); Sac_ia.setnumberofsamples (20); Save time Sac_ia.setcorrespondencerandomness (6) by setting the number of samples to be used in each iteration calculation (can be saved); When you set the number of neighbors to select when calculating covariance, the greater the value, the more accurate the covariance, but the lower the computational efficiency.
(Can Save) sac_ia.align (*align);
end = Clock ();
cout << "Calculate time is:" << float (end-start)/clocks_per_sec<<endl; Visualize boost::shared_ptr<pcl::visualization::P clvisualizer> View (new pcl::visualization::P clvisualizer ("Fpfh
Test "));
int v1;
int v2;
View->createviewport (0,0.0,0.5,1.0,V1);
View->createviewport (0.5,0.0,1.0,1.0,V2);
View->setbackgroundcolor (0,0,0,V1);
View->setbackgroundcolor (0.05,0,0,V2);
Pcl::visualization::P ointcloudcolorhandlercustom<pcl::P ointxyz> sources_cloud_color (source,250,0,0);
View->addpointcloud (Source,sources_cloud_color, "Sources_cloud_v1", v1);
Pcl::visualization::P ointcloudcolorhandlercustom<pcl::P ointxyz> target_cloud_color (target,0,250,0); View->addPointcloud (Target,target_cloud_color, "Target_cloud_v1", v1);
View->setpointcloudrenderingproperties (pcl::visualization::P cl_visualizer_point_size,2, "SOURCES_CLOUD_V1");
Pcl::visualization::P OINTCLOUDCOLORHANDLERCUSTOM<PCL::P ointxyz>aligend_cloud_color (final,255,0,0);
View->addpointcloud (Align,aligend_cloud_color, "ALIGEND_CLOUD_V2", V2);
View->addpointcloud (Target,target_cloud_color, "TARGET_CLOUD_V2", V2);
View->setpointcloudrenderingproperties (pcl::visualization::P cl_visualizer_point_size,4, "Aligend_cloud_v2");
View->setpointcloudrenderingproperties (pcl::visualization::P cl_visualizer_point_size,2, "Target_cloud_v2"); VIEW->ADDCORRESPONDENCES<PCL::P ointxyz> (source,target,*cru_correspondences, "correspondence", v1);//
Add display corresponding point to while (!view->wasstopped ()) {//View->spin ();
View->spinonce (100); Boost::this_thread::sleep (boost::p OSIX_time::microseconds (100000));
} pcl::io::savepcdfile ("CROU_OUTPUT.PCD", *align);
Pcl::io::savepcdfile ("FINAL_ALIGN.PCD", *final);
return 0; }
With FPFH feature registration, the effect is good, but the computational efficiency is very low, especially for large-scale point cloud data. Therefore, many times, the original point cloud is simplified, the simplified data to do registration, the obtained registration parameters are applied to the original point cloud, in order to improve the computational efficiency. voxel Mesh Simplification
Main program:
//pcl::approximatevoxelgrid<pcl::P ointxyz> Approximate_voxel_grid;
PCL::VOXELGRID<PCL::P ointxyz> Approximate_voxel_grid; Approximate_voxel_grid.setleafsize (0.5,0.5,0.5);
The length of the mesh edge. The larger the value here, the more streamlined (with less data left) Pointcloud::P tr Source (new Pointcloud);
Pointcloud::P tr sample_sources (new Pointcloud);
Approximate_voxel_grid.setinputcloud (source);
Approximate_voxel_grid.filter (*sample_source);
cout << "source voxel grid Filte cloud size is" << sample_source->size () <<endl; Pcl::io::savepcdfile ("VOXELGRID.PCD", *out);
For voxel mesh Simplification, the PCL provides two methods: First, PCL::APPROXIMATEVOXELGRID<PCL::P ointxyz> class, and the other, PCL::VOXELGRID<PCL::P ointxyz> class. As can be seen, the second is less than the first "about" approximate, which means that the second is more accurate in some cases than the first. The reason is that the first method is to use the center of the voxel Grid (the center of the box) instead of the original point, and the second is to have a bit of mean in the voxel mesh, with the expectation that the mean point is the alternative to the original point set visualization
In the above main program, has already included the visualization function, more visualization can see my blog PCL visualization of those things, here, detailed how to add the corresponding point pair visualization.
To visualize the corresponding relationship, we first need to calculate the correspondence, the example of this document registration:
pcl::registration::correspondenceestimation<pcl::fpfhsignature33,pcl::fpfhsignature33> Crude_cor_est;
Boost::shared_ptr<pcl::correspondences> cru_correspondences (new pcl::correspondences);
Crude_cor_est.setinputsource (SOURCE_FPFH);
Crude_cor_est.setinputtarget (TARGET_FPFH);
Crude_cor_est.determinecorrespondences (cru_correspondences);
Crude_cor_est.determinereciprocalcorrespondences (*cru_correspondences); cout<< "Crude size is:" <<cru_correspondences->size () <<endl;