example_difference_of_normals.cpp
Go to the documentation of this file.
00001 
00008 #include <string>
00009 
00010 #include <pcl/point_types.h>
00011 #include <pcl/io/pcd_io.h>
00012 #include <pcl/kdtree/kdtree_flann.h>
00013 #include <pcl/common/point_operators.h>
00014 #include <pcl/common/io.h>
00015 #include <pcl/search/organized.h>
00016 #include <pcl/search/octree.h>
00017 #include <pcl/search/kdtree.h>
00018 #include <pcl/features/normal_3d_omp.h>
00019 #include <pcl/filters/conditional_removal.h>
00020 #include <pcl/segmentation/sac_segmentation.h>
00021 #include <pcl/segmentation/extract_clusters.h>
00022 #include <pcl/io/vtk_io.h>
00023 #include <pcl/filters/voxel_grid.h>
00024 
00025 #include <pcl/features/don.h>
00026 
00027 using namespace pcl;
00028 using namespace std;
00029 
00030 typedef pcl::PointXYZRGB PointT;
00031 typedef pcl::PointNormal PointNT;
00032 typedef pcl::PointNormal PointOutT;
00033 typedef pcl::search::Search<PointT>::Ptr SearchPtr;
00034 
00035 int main (int argc, char *argv[])
00036 {
00038         double scale1 = 0.2;
00039 
00041         double scale2 = 2.0;
00042 
00044         double threshold = 0.25;
00045 
00047         double segradius = 0.2;
00048 
00049         //voxelization factor of pointcloud to use in approximation of normals
00050         bool approx = false;
00051         double decimation = 100;
00052 
00053         if(argc < 2){
00054                 cerr << "Expected 2 arguments: inputfile outputfile" << endl;
00055         }
00056 
00058         string infile = argv[1];
00059 
00061         string outfile = argv[2];
00062 
00063         // Load cloud in blob format
00064         pcl::PCLPointCloud2 blob;
00065         pcl::io::loadPCDFile (infile.c_str(), blob);
00066 
00067         pcl::PointCloud<PointT>::Ptr cloud (new pcl::PointCloud<PointT>);
00068         cout << "Loading point cloud...";
00069         pcl::fromPCLPointCloud2 (blob, *cloud);
00070         cout << "done." << endl;
00071 
00072         SearchPtr tree;
00073 
00074         if (cloud->isOrganized ())
00075         {
00076           tree.reset (new pcl::search::OrganizedNeighbor<PointT> ());
00077         }
00078         else
00079         {
00080       tree.reset (new pcl::search::KdTree<PointT> (false));
00081         }
00082 
00083         tree->setInputCloud (cloud);
00084 
00085         PointCloud<PointT>::Ptr small_cloud_downsampled;
00086         PointCloud<PointT>::Ptr large_cloud_downsampled;
00087 
00088         // If we are using approximation
00089         if(approx){
00090           cout << "Downsampling point cloud for approximation" << endl;
00091 
00092           // Create the downsampling filtering object
00093           pcl::VoxelGrid<PointT> sor;
00094           sor.setDownsampleAllData (false);
00095           sor.setInputCloud (cloud);
00096 
00097           // Create downsampled point cloud for DoN NN search with small scale
00098           small_cloud_downsampled = PointCloud<PointT>::Ptr(new pcl::PointCloud<PointT>);
00099           float smalldownsample = static_cast<float> (scale1 / decimation);
00100           sor.setLeafSize (smalldownsample, smalldownsample, smalldownsample);
00101           sor.filter (*small_cloud_downsampled);
00102           cout << "Using leaf size of " << smalldownsample << " for small scale, " << small_cloud_downsampled->size() << " points" << endl;
00103 
00104           // Create downsampled point cloud for DoN NN search with large scale
00105           large_cloud_downsampled = PointCloud<PointT>::Ptr(new pcl::PointCloud<PointT>);
00106           const float largedownsample = float (scale2/decimation);
00107           sor.setLeafSize (largedownsample, largedownsample, largedownsample);
00108           sor.filter (*large_cloud_downsampled);
00109           cout << "Using leaf size of " << largedownsample << " for large scale, " << large_cloud_downsampled->size() << " points" << endl;
00110         }
00111 
00112         // Compute normals using both small and large scales at each point
00113         pcl::NormalEstimationOMP<PointT, PointNT> ne;
00114         ne.setInputCloud (cloud);
00115         ne.setSearchMethod (tree);
00116 
00121         ne.setViewPoint(std::numeric_limits<float>::max(),std::numeric_limits<float>::max(),std::numeric_limits<float>::max());
00122 
00123         if(scale1 >= scale2){
00124           cerr << "Error: Large scale must be > small scale!" << endl;
00125           exit(EXIT_FAILURE);
00126         }
00127 
00128         //the normals calculated with the small scale
00129         cout << "Calculating normals for scale..." << scale1 << endl;
00130         pcl::PointCloud<PointNT>::Ptr normals_small_scale (new pcl::PointCloud<PointNT>);
00131 
00132         if(approx){
00133                 ne.setSearchSurface(small_cloud_downsampled);
00134     }
00135 
00136         ne.setRadiusSearch (scale1);
00137         ne.compute (*normals_small_scale);
00138 
00139         cout << "Calculating normals for scale..." << scale2 << endl;
00140         //the normals calculated with the large scale
00141         pcl::PointCloud<PointNT>::Ptr normals_large_scale (new pcl::PointCloud<PointNT>);
00142 
00143         if(approx){
00144           ne.setSearchSurface(large_cloud_downsampled);
00145         }
00146         ne.setRadiusSearch (scale2);
00147         ne.compute (*normals_large_scale);
00148 
00149         // Create output cloud for DoN results
00150         PointCloud<PointOutT>::Ptr doncloud (new pcl::PointCloud<PointOutT>);
00151         copyPointCloud<PointT, PointOutT>(*cloud, *doncloud);
00152 
00153         cout << "Calculating DoN... " << endl;
00154         // Create DoN operator
00155         pcl::DifferenceOfNormalsEstimation<PointT, PointNT, PointOutT> don;
00156         don.setInputCloud (cloud);
00157         don.setNormalScaleLarge(normals_large_scale);
00158         don.setNormalScaleSmall(normals_small_scale);
00159 
00160         if(!don.initCompute ()){
00161           std::cerr << "Error: Could not intialize DoN feature operator" << std::endl;
00162           exit(EXIT_FAILURE);
00163         }
00164 
00165         //Compute DoN
00166         don.computeFeature(*doncloud);
00167 
00168         pcl::PCDWriter writer;
00169 
00170         // Save DoN features
00171         writer.write<PointOutT> (outfile.c_str (), *doncloud, false);
00172 
00173         //Filter by magnitude
00174         cout << "Filtering out DoN mag <= "<< threshold <<  "..." << endl;
00175 
00176         // build the condition
00177         pcl::ConditionOr<PointOutT>::Ptr range_cond (new
00178         pcl::ConditionOr<PointOutT> ());
00179         range_cond->addComparison (pcl::FieldComparison<PointOutT>::ConstPtr (new
00180         pcl::FieldComparison<PointOutT> ("curvature", pcl::ComparisonOps::GT, threshold)));
00181         // build the filter
00182         pcl::ConditionalRemoval<PointOutT> condrem (range_cond);
00183         condrem.setInputCloud (doncloud);
00184 
00185         pcl::PointCloud<PointOutT>::Ptr doncloud_filtered (new pcl::PointCloud<PointOutT>);
00186 
00187         // apply filter
00188         condrem.filter (*doncloud_filtered);
00189 
00190         doncloud = doncloud_filtered;
00191 
00192         // Save filtered output
00193         std::cout << "Filtered Pointcloud: " << doncloud->points.size () << " data points." << std::endl;
00194         std::stringstream ss;
00195         ss << outfile.substr(0,outfile.length()-4) << "_threshold_"<< threshold << "_.pcd";
00196         writer.write<PointOutT> (ss.str (), *doncloud, false);
00197 
00198         //Filter by magnitude
00199         cout << "Clustering using EuclideanClusterExtraction with tolerance <= "<< segradius <<  "..." << endl;
00200 
00201         pcl::search::KdTree<PointOutT>::Ptr segtree (new pcl::search::KdTree<PointOutT>);
00202         segtree->setInputCloud (doncloud);
00203 
00204         std::vector<pcl::PointIndices> cluster_indices;
00205         pcl::EuclideanClusterExtraction<PointOutT> ec;
00206 
00207         ec.setClusterTolerance (segradius);
00208         ec.setMinClusterSize (50);
00209         ec.setMaxClusterSize (100000);
00210         ec.setSearchMethod (segtree);
00211         ec.setInputCloud (doncloud);
00212         ec.extract (cluster_indices);
00213 
00214         int j = 0;
00215         for (std::vector<pcl::PointIndices>::const_iterator it = cluster_indices.begin (); it != cluster_indices.end (); ++it, j++)
00216         {
00217                 pcl::PointCloud<PointOutT>::Ptr cloud_cluster_don (new pcl::PointCloud<PointOutT>);
00218                 for (std::vector<int>::const_iterator pit = it->indices.begin (); pit != it->indices.end (); pit++){
00219                   cloud_cluster_don->points.push_back (doncloud->points[*pit]);
00220                 }
00221 
00222                 cloud_cluster_don->width = int (cloud_cluster_don->points.size ());
00223                 cloud_cluster_don->height = 1;
00224                 cloud_cluster_don->is_dense = true;
00225 
00226                 std::cout << "PointCloud representing the Cluster: " << cloud_cluster_don->points.size () << " data points." << std::endl;
00227                 std::stringstream ss;
00228                 ss << outfile.substr(0,outfile.length()-4) << "_threshold_"<< threshold << "_cluster_" << j << ".pcd";
00229                 writer.write<PointOutT> (ss.str (), *cloud_cluster_don, false);
00230         }
00231 }


pcl
Author(s): Open Perception
autogenerated on Wed Aug 26 2015 15:23:35