# -*- coding: utf-8 -*- # Difference of Normals Based Segmentation # http://pointclouds.org/documentation/tutorials/don_segmentation.php#don-segmentation /** * @file don_segmentation.cpp * Difference of Normals Example for PCL Segmentation Tutorials. * @author Yani Ioannou * @date 2012-09-24 */ # #include # # #include # #include # #include # #include # #include # #include # #include # # #include # # using namespace pcl; # using namespace std; import pcl # ///The smallest scale to use in the DoN filter. # double scale1; # # ///The largest scale to use in the DoN filter. # double scale2; # # ///The minimum DoN magnitude to threshold by # double threshold; # # ///segment scene into clusters with given distance tolerance using euclidean clustering # double segradius; # # if (argc < 6) # { # cerr << "usage: " << argv[0] << " inputfile smallscale largescale threshold segradius" << endl; # exit (EXIT_FAILURE); # } # # /// the file to read from. # string infile = argv[1]; # /// small scale # istringstream (argv[2]) >> scale1; # /// large scale # istringstream (argv[3]) >> scale2; # istringstream (argv[4]) >> threshold; // threshold for DoN magnitude # istringstream (argv[5]) >> segradius; // threshold for radius segmentation # # // Load cloud in blob format # pcl::PCLPointCloud2 blob; # pcl::io::loadPCDFile (infile.c_str (), blob); # pcl::PointCloud::Ptr cloud (new pcl::PointCloud); # pcl::fromPCLPointCloud2 (blob, *cloud); # # // Create a search tree, use KDTreee for non-organized data. # pcl::search::Search::Ptr tree; # if (cloud->isOrganized ()) # { # tree.reset (new pcl::search::OrganizedNeighbor ()); # } # else # { # tree.reset (new pcl::search::KdTree (false)); # } # # // Set the input pointcloud for the search tree # tree->setInputCloud (cloud); # # if (scale1 >= scale2) # { # cerr << "Error: Large scale must be > small scale!" << endl; # exit (EXIT_FAILURE); # } # # // Compute normals using both small and large scales at each point # pcl::NormalEstimationOMP ne; # ne.setInputCloud (cloud); # ne.setSearchMethod (tree); # # /** # * NOTE: setting viewpoint is very important, so that we can ensure # * normals are all pointed in the same direction! # */ # ne.setViewPoint (std::numeric_limits::max (), std::numeric_limits::max (), std::numeric_limits::max ()); # # // calculate normals with the small scale # cout << "Calculating normals for scale..." << scale1 << endl; # pcl::PointCloud::Ptr normals_small_scale (new pcl::PointCloud); # # ne.setRadiusSearch (scale1); # ne.compute (*normals_small_scale); # # // calculate normals with the large scale # cout << "Calculating normals for scale..." << scale2 << endl; # pcl::PointCloud::Ptr normals_large_scale (new pcl::PointCloud); # # ne.setRadiusSearch (scale2); # ne.compute (*normals_large_scale); # # // Create output cloud for DoN results # PointCloud::Ptr doncloud (new pcl::PointCloud); # copyPointCloud(*cloud, *doncloud); # # cout << "Calculating DoN... " << endl; # // Create DoN operator # pcl::DifferenceOfNormalsEstimation don; # don.setInputCloud (cloud); # don.setNormalScaleLarge (normals_large_scale); # don.setNormalScaleSmall (normals_small_scale); # # if (!don.initCompute ()) # { # std::cerr << "Error: Could not intialize DoN feature operator" << std::endl; # exit (EXIT_FAILURE); # } # # // Compute DoN # don.computeFeature (*doncloud); # # // Save DoN features # pcl::PCDWriter writer; # writer.write ("don.pcd", *doncloud, false); # # // Filter by magnitude # cout << "Filtering out DoN mag <= " << threshold << "..." << endl; # # // Build the condition for filtering # pcl::ConditionOr::Ptr range_cond ( # new pcl::ConditionOr () # ); # range_cond->addComparison (pcl::FieldComparison::ConstPtr ( # new pcl::FieldComparison ("curvature", pcl::ComparisonOps::GT, threshold)) # ); ### # // Build the filter # pcl::ConditionalRemoval condrem (range_cond); # condrem.setInputCloud (doncloud); # # pcl::PointCloud::Ptr doncloud_filtered (new pcl::PointCloud); # # // Apply filter # condrem.filter (*doncloud_filtered); # # doncloud = doncloud_filtered; # # // Save filtered output # std::cout << "Filtered Pointcloud: " << doncloud->points.size () << " data points." << std::endl; # writer.write ("don_filtered.pcd", *doncloud, false); ### # # // Filter by magnitude # cout << "Clustering using EuclideanClusterExtraction with tolerance <= " << segradius << "..." << endl; # # pcl::search::KdTree::Ptr segtree (new pcl::search::KdTree); # segtree->setInputCloud (doncloud); ### # std::vector cluster_indices; # pcl::EuclideanClusterExtraction ec; # # ec.setClusterTolerance (segradius); # ec.setMinClusterSize (50); # ec.setMaxClusterSize (100000); # ec.setSearchMethod (segtree); # ec.setInputCloud (doncloud); # ec.extract (cluster_indices); ### # int j = 0; # for (std::vector::const_iterator it = cluster_indices.begin (); it != cluster_indices.end (); ++it, j++) # { # pcl::PointCloud::Ptr cloud_cluster_don (new pcl::PointCloud); # for (std::vector::const_iterator pit = it->indices.begin (); pit != it->indices.end (); ++pit) # { # cloud_cluster_don->points.push_back (doncloud->points[*pit]); # } # # cloud_cluster_don->width = int (cloud_cluster_don->points.size ()); # cloud_cluster_don->height = 1; # cloud_cluster_don->is_dense = true; # # //Save cluster # cout << "PointCloud representing the Cluster: " << cloud_cluster_don->points.size () << " data points." << std::endl; # stringstream ss; # ss << "don_cluster_" << j << ".pcd"; # writer.write (ss.str (), *cloud_cluster_don, false); # } ###