41#ifndef PCL_PEOPLE_HEAD_BASED_SUBCLUSTER_HPP_
42#define PCL_PEOPLE_HEAD_BASED_SUBCLUSTER_HPP_
44#include <pcl/people/head_based_subcluster.h>
46template <
typename Po
intT>
62template <
typename Po
intT>
void
68template <
typename Po
intT>
void
72 sqrt_ground_coeffs_ = (ground_coeffs - Eigen::Vector4f(0.0f, 0.0f, 0.0f, ground_coeffs(3))).norm();
75template <
typename Po
intT>
void
81template <
typename Po
intT>
void
87template <
typename Po
intT>
void
94template <
typename Po
intT>
void
101template <
typename Po
intT>
void
107template <
typename Po
intT>
void
113template <
typename Po
intT>
void
120template <
typename Po
intT>
void
127template <
typename Po
intT>
float
133template <
typename Po
intT>
void
137 float min_distance_between_cluster_centers = 0.4;
140 std::vector <std::vector<int> > connected_clusters;
141 connected_clusters.resize(input_clusters.size());
142 std::vector<bool> used_clusters;
143 used_clusters.resize(input_clusters.size());
144 for(std::size_t i = 0; i < input_clusters.size(); i++)
146 Eigen::Vector3f theoretical_center = input_clusters[i].getTCenter();
147 float t = theoretical_center.dot(head_ground_coeffs) / normalize_factor;
148 Eigen::Vector3f current_cluster_center_projection = theoretical_center - head_ground_coeffs * t;
149 for(std::size_t j = i+1; j < input_clusters.size(); j++)
151 theoretical_center = input_clusters[j].getTCenter();
152 float t = theoretical_center.dot(head_ground_coeffs) / normalize_factor;
153 Eigen::Vector3f new_cluster_center_projection = theoretical_center - head_ground_coeffs * t;
154 if (((new_cluster_center_projection - current_cluster_center_projection).norm()) < min_distance_between_cluster_centers)
156 connected_clusters[i].push_back(j);
161 for(std::size_t i = 0; i < connected_clusters.size(); i++)
163 if (!used_clusters[i])
165 used_clusters[i] =
true;
166 if (connected_clusters[i].empty())
168 output_clusters.push_back(input_clusters[i]);
174 point_indices = input_clusters[i].getIndices();
175 for(
const int &cluster : connected_clusters[i])
177 if (!used_clusters[cluster])
179 used_clusters[cluster] =
true;
180 for(
const auto& cluster_idx : input_clusters[cluster].getIndices().indices)
182 point_indices.
indices.push_back(cluster_idx);
187 output_clusters.push_back(cluster);
193template <
typename Po
intT>
void
200 Eigen::Matrix3Xf maxima_projected(3,maxima_number);
201 Eigen::VectorXi subclusters_number_of_points(maxima_number);
202 std::vector <pcl::Indices> sub_clusters_indices;
203 sub_clusters_indices.resize(maxima_number);
206 for(
int i = 0; i < maxima_number; i++)
208 PointT* current_point = &(*cloud_)[maxima_cloud_indices[i]];
209 Eigen::Vector3f p_current_eigen(current_point->x, current_point->y, current_point->z);
210 float t = p_current_eigen.dot(head_ground_coeffs) / normalize_factor;
211 maxima_projected.col(i).matrix () = p_current_eigen - head_ground_coeffs * t;
212 subclusters_number_of_points(i) = 0;
218 Eigen::Vector3f p_current_eigen((*
cloud_)[cluster_idx].x, (*
cloud_)[cluster_idx].y, (*
cloud_)[cluster_idx].z);
219 float t = p_current_eigen.dot(head_ground_coeffs) / normalize_factor;
220 p_current_eigen -= head_ground_coeffs * t;
223 bool correspondence_detected =
false;
224 while ((!correspondence_detected) && (i < maxima_number))
228 correspondence_detected =
true;
229 sub_clusters_indices[i].push_back(cluster_idx);
230 subclusters_number_of_points(i)++;
238 for(
int i = 0; i < maxima_number; i++)
243 point_indices.
indices = sub_clusters_indices[i];
246 subclusters.push_back(cluster);
252template <
typename Po
intT>
void
258 PCL_ERROR (
"[pcl::people::pcl::people::HeadBasedSubclustering::subcluster] Floor parameters have not been set or they are not valid!\n");
263 PCL_ERROR (
"[pcl::people::pcl::people::HeadBasedSubclustering::subcluster] Cluster indices have not been set!\n");
268 PCL_ERROR (
"[pcl::people::pcl::people::HeadBasedSubclustering::subcluster] Input cloud has not been set!\n");
276 clusters.push_back(cluster);
280 std::vector<pcl::people::PersonCluster<PointT> > new_clusters;
281 for(std::size_t i = 0; i < clusters.size(); i++)
284 new_clusters.push_back(clusters[i]);
286 clusters = new_clusters;
287 new_clusters.clear();
291 clusters = new_clusters;
293 std::vector<pcl::people::PersonCluster<PointT> > subclusters;
294 int cluster_min_points_sub =
static_cast<int>(
static_cast<float>(
min_points_) * 1.5);
303 for(
auto it = clusters.begin(); it != clusters.end(); ++it)
305 float height = it->getHeight();
306 int number_of_points = it->getNumberPoints();
309 if (number_of_points > cluster_min_points_sub)
320 subclusters.push_back(*it);
326 subclusters.push_back(*it);
330 clusters = subclusters;
333template <
typename Po
intT>
void setGround(Eigen::VectorXf &ground_coeffs)
Set the ground coefficients.
bool vertical_
if true, the sensor is considered to be vertically placed (portrait mode)
std::vector< pcl::PointIndices > cluster_indices_
initial clusters indices
void setDimensionLimits(int min_points, int max_points)
Set minimum and maximum allowed number of points for a person cluster.
virtual ~HeadBasedSubclustering()
Destructor.
void setHeadCentroid(bool head_centroid)
Set head_centroid_ to true (person centroid is in the head) or false (person centroid is the whole bo...
void subcluster(std::vector< pcl::people::PersonCluster< PointT > > &clusters)
Compute subclusters and return them into a vector of PersonCluster.
bool head_centroid_
if true, the person centroid is computed as the centroid of the cluster points belonging to the head ...
typename PointCloud::Ptr PointCloudPtr
float min_height_
person clusters minimum height from the ground plane
void mergeClustersCloseInFloorCoordinates(std::vector< pcl::people::PersonCluster< PointT > > &input_clusters, std::vector< pcl::people::PersonCluster< PointT > > &output_clusters)
Merge clusters close in floor coordinates.
PointCloudPtr cloud_
pointer to the input cloud
Eigen::VectorXf ground_coeffs_
ground plane coefficients
void getHeightLimits(float &min_height, float &max_height)
Get minimum and maximum allowed height for a person cluster.
void setInitialClusters(std::vector< pcl::PointIndices > &cluster_indices)
Set initial cluster indices.
void setMinimumDistanceBetweenHeads(float heads_minimum_distance)
Set minimum distance between persons' heads.
void getDimensionLimits(int &min_points, int &max_points)
Get minimum and maximum allowed number of points for a person cluster.
float getMinimumDistanceBetweenHeads()
Get minimum distance between persons' heads.
void setSensorPortraitOrientation(bool vertical)
Set sensor orientation to landscape mode (false) or portrait mode (true).
int min_points_
minimum number of points for a person cluster
void setHeightLimits(float min_height, float max_height)
Set minimum and maximum allowed height for a person cluster.
float sqrt_ground_coeffs_
ground plane normalization factor
int max_points_
maximum number of points for a person cluster
float max_height_
person clusters maximum height from the ground plane
void createSubClusters(pcl::people::PersonCluster< PointT > &cluster, int maxima_number_after_filtering, std::vector< int > &maxima_cloud_indices_filtered, std::vector< pcl::people::PersonCluster< PointT > > &subclusters)
Create subclusters centered on the heads position from the current cluster.
float heads_minimum_distance_
minimum distance between persons' heads
HeadBasedSubclustering()
Constructor.
void setInputCloud(PointCloudPtr &cloud)
Set input cloud.
HeightMap2D represents a class for creating a 2D height map from a point cloud and searching for its ...
std::vector< int > & getMaximaCloudIndicesFiltered()
Return the point cloud indices corresponding to the maxima computed after the filterMaxima method.
void setInputCloud(PointCloudPtr &cloud)
Set initial cluster indices.
void setSensorPortraitOrientation(bool vertical)
Set sensor orientation to landscape mode (false) or portrait mode (true).
int & getMaximaNumberAfterFiltering()
Return the maxima number after the filterMaxima method.
void setGround(Eigen::VectorXf &ground_coeffs)
Set the ground coefficients.
void compute(pcl::people::PersonCluster< PointT > &cluster)
Compute the height map with the projection of cluster points onto the ground plane.
void setMinimumDistanceBetweenMaxima(float minimum_distance_between_maxima)
Set minimum distance between maxima.
PersonCluster represents a class for representing information about a cluster containing a person.
pcl::PointIndices & getIndices()
Returns the indices of the point cloud points corresponding to the cluster.