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
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
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
00089 if(approx){
00090 cout << "Downsampling point cloud for approximation" << endl;
00091
00092
00093 pcl::VoxelGrid<PointT> sor;
00094 sor.setDownsampleAllData (false);
00095 sor.setInputCloud (cloud);
00096
00097
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
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
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
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
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
00150 PointCloud<PointOutT>::Ptr doncloud (new pcl::PointCloud<PointOutT>);
00151 copyPointCloud<PointT, PointOutT>(*cloud, *doncloud);
00152
00153 cout << "Calculating DoN... " << endl;
00154
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
00166 don.computeFeature(*doncloud);
00167
00168 pcl::PCDWriter writer;
00169
00170
00171 writer.write<PointOutT> (outfile.c_str (), *doncloud, false);
00172
00173
00174 cout << "Filtering out DoN mag <= "<< threshold << "..." << endl;
00175
00176
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
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
00188 condrem.filter (*doncloud_filtered);
00189
00190 doncloud = doncloud_filtered;
00191
00192
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
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 }