euclidean_clustering.cpp
Go to the documentation of this file.
00001 #include <pcl/apps/cloud_composer/tools/euclidean_clustering.h>
00002 #include <pcl/apps/cloud_composer/items/cloud_item.h>
00003 
00004 #include <pcl/point_types.h>
00005 #include <pcl/filters/extract_indices.h>
00006 #include <pcl/kdtree/kdtree.h>
00007 #include <pcl/segmentation/extract_clusters.h>
00008 
00009 Q_EXPORT_PLUGIN2(cloud_composer_euclidean_clustering_tool, pcl::cloud_composer::EuclideanClusteringToolFactory)
00010 
00011 pcl::cloud_composer::EuclideanClusteringTool::EuclideanClusteringTool (PropertiesModel* parameter_model, QObject* parent)
00012   : SplitItemTool (parameter_model, parent)
00013 {
00014   
00015 }
00016 
00017 pcl::cloud_composer::EuclideanClusteringTool::~EuclideanClusteringTool ()
00018 {
00019   
00020 }
00021 
00022 QList <pcl::cloud_composer::CloudComposerItem*>
00023 pcl::cloud_composer::EuclideanClusteringTool::performAction (ConstItemList input_data, PointTypeFlags::PointType)
00024 {
00025   QList <CloudComposerItem*> output;
00026   const CloudComposerItem* input_item;
00027   // Check input data length
00028   if ( input_data.size () == 0)
00029   {
00030     qCritical () << "Empty input in Euclidean Clustering Tool!";
00031     return output;
00032   }
00033   else if ( input_data.size () > 1)
00034   {
00035     qWarning () << "Input vector has more than one item in Euclidean Clustering!";
00036   }
00037   input_item = input_data.value (0);
00038   
00039   if (input_item->type () == CloudComposerItem::CLOUD_ITEM)
00040   {
00041     const CloudItem* cloud_item = dynamic_cast <const CloudItem*> (input_item);
00042     if ( cloud_item->isSanitized())
00043     {
00044       double cluster_tolerance = parameter_model_->getProperty ("Cluster Tolerance").toDouble();
00045       int min_cluster_size = parameter_model_->getProperty ("Min Cluster Size").toInt();
00046       int max_cluster_size = parameter_model_->getProperty ("Max Cluster Size").toInt();
00047     
00048       pcl::PCLPointCloud2::ConstPtr input_cloud = input_item->data (ItemDataRole::CLOUD_BLOB).value <pcl::PCLPointCloud2::ConstPtr> ();
00049       //Get the cloud in template form
00050       pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
00051       pcl::fromPCLPointCloud2 (*input_cloud, *cloud);
00052       
00054       // Creating the KdTree object for the search method of the extraction
00055       pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ>);
00056       tree->setInputCloud (cloud);
00057     
00058       std::vector<pcl::PointIndices> cluster_indices;
00059       pcl::EuclideanClusterExtraction<pcl::PointXYZ> ec;
00060       ec.setClusterTolerance (cluster_tolerance); 
00061       ec.setMinClusterSize (min_cluster_size);
00062       ec.setMaxClusterSize (max_cluster_size);
00063       ec.setSearchMethod (tree);
00064       ec.setInputCloud (cloud);
00065       ec.extract (cluster_indices);
00067       //Get copies of the original origin and orientation
00068       Eigen::Vector4f source_origin = input_item->data (ItemDataRole::ORIGIN).value<Eigen::Vector4f> ();
00069       Eigen::Quaternionf source_orientation =  input_item->data (ItemDataRole::ORIENTATION).value<Eigen::Quaternionf> ();
00070       //Vector to accumulate the extracted indices
00071       pcl::IndicesPtr extracted_indices (new std::vector<int> ());
00072       //Put found clusters into new cloud_items!
00073       qDebug () << "Found "<<cluster_indices.size ()<<" clusters!";
00074       int cluster_count = 0;
00075       pcl::ExtractIndices<pcl::PCLPointCloud2> filter;
00076       for (std::vector<pcl::PointIndices>::const_iterator it = cluster_indices.begin (); it != cluster_indices.end (); ++it)
00077       {
00078         filter.setInputCloud (input_cloud);
00079         // It's annoying that I have to do this, but Euclidean returns a PointIndices struct
00080         pcl::PointIndices::ConstPtr indices_ptr = boost::make_shared<pcl::PointIndices>(*it);
00081         filter.setIndices (indices_ptr);
00082         extracted_indices->insert (extracted_indices->end (), it->indices.begin (), it->indices.end ());
00083         //This means remove the other points
00084         filter.setKeepOrganized (false);
00085         pcl::PCLPointCloud2::Ptr cloud_filtered (new pcl::PCLPointCloud2);
00086         filter.filter (*cloud_filtered);
00087       
00088         qDebug() << "Cluster has " << cloud_filtered->width << " data points.";
00089         CloudItem* cloud_item = new CloudItem (input_item->text ()+tr("-Clstr %1").arg(cluster_count)
00090                                               , cloud_filtered
00091                                               , source_origin
00092                                               , source_orientation);
00093         output.append (cloud_item);
00094         ++cluster_count;
00095       } 
00096       //We copy input cloud over for special case that no clusters found, since ExtractIndices doesn't work for 0 length vectors
00097       pcl::PCLPointCloud2::Ptr remainder_cloud (new pcl::PCLPointCloud2(*input_cloud));
00098       if (cluster_indices.size () > 0)
00099       {
00100         //make a cloud containing all the remaining points
00101         filter.setIndices (extracted_indices);
00102         filter.setNegative (true);
00103         filter.filter (*remainder_cloud);
00104       }
00105       qDebug() << "Cloud has " << remainder_cloud->width << " data points after clusters removed.";
00106       CloudItem* cloud_item = new CloudItem (input_item->text ()+ " unclustered"
00107                                               , remainder_cloud
00108                                               , source_origin
00109                                               , source_orientation);
00110       output.push_front (cloud_item);
00111     }
00112     else
00113       qCritical () << "Input item in Clustering is not SANITIZED!!!";
00114   }
00115   else
00116   {
00117     qCritical () << "Input item in Clustering is not a cloud!!!";
00118   }
00119   
00120   
00121   return output;
00122 }
00123 
00125 pcl::cloud_composer::PropertiesModel*
00126 pcl::cloud_composer::EuclideanClusteringToolFactory::createToolParameterModel (QObject* parent)
00127 {
00128   PropertiesModel* parameter_model = new PropertiesModel(parent);
00129   
00130   parameter_model->addProperty ("Cluster Tolerance", 0.02,  Qt::ItemIsEditable | Qt::ItemIsEnabled);
00131   parameter_model->addProperty ("Min Cluster Size", 100,  Qt::ItemIsEditable | Qt::ItemIsEnabled);
00132   parameter_model->addProperty ("Max Cluster Size", 25000,  Qt::ItemIsEditable | Qt::ItemIsEnabled);
00133     
00134 
00135   return parameter_model;
00136 }


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