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
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
00050 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
00051 pcl::fromPCLPointCloud2 (*input_cloud, *cloud);
00052
00054
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
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
00071 pcl::IndicesPtr extracted_indices (new std::vector<int> ());
00072
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
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
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
00097 pcl::PCLPointCloud2::Ptr remainder_cloud (new pcl::PCLPointCloud2(*input_cloud));
00098 if (cluster_indices.size () > 0)
00099 {
00100
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 }