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
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
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
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 }