ppf_object_recognition.cpp
Go to the documentation of this file.
00001 #include <pcl/features/ppf.h>
00002 #include <pcl/io/pcd_io.h>
00003 #include <pcl/filters/voxel_grid.h>
00004 #include <pcl/features/normal_3d.h>
00005 #include <pcl/registration/ppf_registration.h>
00006 
00007 #include <pcl/visualization/pcl_visualizer.h>
00008 #include <boost/thread/thread.hpp>
00009 
00010 #include <pcl/segmentation/sac_segmentation.h>
00011 #include <pcl/filters/extract_indices.h>
00012 #include <pcl/sample_consensus/method_types.h>
00013 #include <pcl/sample_consensus/model_types.h>
00014 
00015 using namespace pcl;
00016 using namespace std;
00017 
00018 const Eigen::Vector4f subsampling_leaf_size (0.02f, 0.02f, 0.02f, 0.0f);
00019 const float normal_estimation_search_radius = 0.05f;
00020 
00021 
00022 PointCloud<PointNormal>::Ptr
00023 subsampleAndCalculateNormals (PointCloud<PointXYZ>::Ptr cloud)
00024 {
00025   PointCloud<PointXYZ>::Ptr cloud_subsampled (new PointCloud<PointXYZ> ());
00026   VoxelGrid<PointXYZ> subsampling_filter;
00027   subsampling_filter.setInputCloud (cloud);
00028   subsampling_filter.setLeafSize (subsampling_leaf_size);
00029   subsampling_filter.filter (*cloud_subsampled);
00030 
00031   PointCloud<Normal>::Ptr cloud_subsampled_normals (new PointCloud<Normal> ());
00032   NormalEstimation<PointXYZ, Normal> normal_estimation_filter;
00033   normal_estimation_filter.setInputCloud (cloud_subsampled);
00034   search::KdTree<PointXYZ>::Ptr search_tree (new search::KdTree<PointXYZ>);
00035   normal_estimation_filter.setSearchMethod (search_tree);
00036   normal_estimation_filter.setRadiusSearch (normal_estimation_search_radius);
00037   normal_estimation_filter.compute (*cloud_subsampled_normals);
00038 
00039   PointCloud<PointNormal>::Ptr cloud_subsampled_with_normals (new PointCloud<PointNormal> ());
00040   concatenateFields (*cloud_subsampled, *cloud_subsampled_normals, *cloud_subsampled_with_normals);
00041 
00042   PCL_INFO ("Cloud dimensions before / after subsampling: %u / %u\n", cloud->points.size (), cloud_subsampled->points.size ());
00043   return cloud_subsampled_with_normals;
00044 }
00045 
00046 int
00047 main (int argc, char** argv)
00048 {
00049   if (argc != 3)
00050   {
00051     PCL_ERROR ("Syntax: ./ppf_object_recognition pcd_model_list pcd_scene\n");
00052     return -1;
00053   }
00054 
00055 
00057   PCL_INFO ("Reading scene ...\n");
00058   PointCloud<PointXYZ>::Ptr cloud_scene (new PointCloud<PointXYZ> ());
00059   PCDReader reader;
00060   reader.read (argv[2], *cloud_scene);
00061   PCL_INFO ("Scene read: %s\n", argv[2]);
00062 
00063   PCL_INFO ("Reading models ...\n");
00064   vector<PointCloud<PointXYZ>::Ptr > cloud_models;
00065   ifstream pcd_file_list (argv[1]);
00066   while (!pcd_file_list.eof())
00067   {
00068     char str[512];
00069     pcd_file_list.getline (str, 512);
00070     PointCloud<PointXYZ>::Ptr cloud (new PointCloud<PointXYZ> ());
00071     reader.read (str, *cloud);
00072     cloud_models.push_back (cloud);
00073     PCL_INFO ("Model read: %s\n", str);
00074   }
00075 
00076   pcl::SACSegmentation<pcl::PointXYZ> seg;
00077   pcl::ExtractIndices<pcl::PointXYZ> extract;
00078   seg.setOptimizeCoefficients (true);
00079   seg.setModelType (pcl::SACMODEL_PLANE);
00080   seg.setMethodType (pcl::SAC_RANSAC);
00081   seg.setMaxIterations (1000);
00082   seg.setDistanceThreshold (0.05);
00083   extract.setNegative (true);
00084   pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients ());
00085   pcl::PointIndices::Ptr inliers (new pcl::PointIndices ());
00086   unsigned nr_points = unsigned (cloud_scene->points.size ());
00087   while (cloud_scene->points.size () > 0.3 * nr_points)
00088   {
00089     seg.setInputCloud (cloud_scene);
00090     seg.segment (*inliers, *coefficients);
00091     PCL_INFO ("Plane inliers: %u\n", inliers->indices.size ());
00092     if (inliers->indices.size () < 50000) break;
00093 
00094     extract.setInputCloud (cloud_scene);
00095     extract.setIndices (inliers);
00096     extract.filter (*cloud_scene);
00097   }
00098 
00099   PointCloud<PointNormal>::Ptr cloud_scene_input = subsampleAndCalculateNormals (cloud_scene);
00100   vector<PointCloud<PointNormal>::Ptr > cloud_models_with_normals;
00101 
00102   PCL_INFO ("Training models ...\n");
00103   vector<PPFHashMapSearch::Ptr> hashmap_search_vector;
00104   for (size_t model_i = 0; model_i < cloud_models.size (); ++model_i)
00105   {
00106     PointCloud<PointNormal>::Ptr cloud_model_input = subsampleAndCalculateNormals (cloud_models[model_i]);
00107     cloud_models_with_normals.push_back (cloud_model_input);
00108 
00109     PointCloud<PPFSignature>::Ptr cloud_model_ppf (new PointCloud<PPFSignature> ());
00110     PPFEstimation<PointNormal, PointNormal, PPFSignature> ppf_estimator;
00111     ppf_estimator.setInputCloud (cloud_model_input);
00112     ppf_estimator.setInputNormals (cloud_model_input);
00113     ppf_estimator.compute (*cloud_model_ppf);
00114 
00115     PPFHashMapSearch::Ptr hashmap_search (new PPFHashMapSearch (12.0f / 180.0f * float (M_PI),
00116                                                                  0.05f));
00117     hashmap_search->setInputFeatureCloud (cloud_model_ppf);
00118     hashmap_search_vector.push_back (hashmap_search);
00119   }
00120 
00121 
00122   visualization::PCLVisualizer viewer ("PPF Object Recognition - Results");
00123   viewer.setBackgroundColor (0, 0, 0);
00124   viewer.addPointCloud (cloud_scene);
00125   viewer.spinOnce (10);
00126   PCL_INFO ("Registering models to scene ...\n");
00127   for (size_t model_i = 0; model_i < cloud_models.size (); ++model_i)
00128   {
00129 
00130     PPFRegistration<PointNormal, PointNormal> ppf_registration;
00131     // set parameters for the PPF registration procedure
00132     ppf_registration.setSceneReferencePointSamplingRate (10);
00133     ppf_registration.setPositionClusteringThreshold (0.2f);
00134     ppf_registration.setRotationClusteringThreshold (30.0f / 180.0f * float (M_PI));
00135     ppf_registration.setSearchMethod (hashmap_search_vector[model_i]);
00136     ppf_registration.setInputCloud (cloud_models_with_normals[model_i]);
00137     ppf_registration.setInputTarget (cloud_scene_input);
00138 
00139     PointCloud<PointNormal> cloud_output_subsampled;
00140     ppf_registration.align (cloud_output_subsampled);
00141 
00142     PointCloud<PointXYZ>::Ptr cloud_output_subsampled_xyz (new PointCloud<PointXYZ> ());
00143     for (size_t i = 0; i < cloud_output_subsampled.points.size (); ++i)
00144       cloud_output_subsampled_xyz->points.push_back ( PointXYZ (cloud_output_subsampled.points[i].x, cloud_output_subsampled.points[i].y, cloud_output_subsampled.points[i].z));
00145 
00146 
00147     Eigen::Matrix4f mat = ppf_registration.getFinalTransformation ();
00148     Eigen::Affine3f final_transformation (mat);
00149 
00150 
00151     //  io::savePCDFileASCII ("output_subsampled_registered.pcd", cloud_output_subsampled);
00152 
00153     PointCloud<PointXYZ>::Ptr cloud_output (new PointCloud<PointXYZ> ());
00154     pcl::transformPointCloud (*cloud_models[model_i], *cloud_output, final_transformation);
00155 
00156 
00157     stringstream ss; ss << "model_" << model_i;
00158     visualization::PointCloudColorHandlerRandom<PointXYZ> random_color (cloud_output->makeShared ());
00159     viewer.addPointCloud (cloud_output, random_color, ss.str ());
00160 //    io::savePCDFileASCII (ss.str ().c_str (), *cloud_output);
00161     PCL_INFO ("Showing model %s\n", ss.str ().c_str ());
00162   }
00163 
00164   PCL_INFO ("All models have been registered!\n");
00165 
00166 
00167   while (!viewer.wasStopped ())
00168   {
00169     viewer.spinOnce (100);
00170     boost::this_thread::sleep (boost::posix_time::microseconds (100000));
00171   }
00172 
00173   return 0;
00174 }


pcl
Author(s): Open Perception
autogenerated on Mon Oct 6 2014 03:17:21