41 #ifndef PCL_PEOPLE_GROUND_BASED_PEOPLE_DETECTION_APP_HPP_
42 #define PCL_PEOPLE_GROUND_BASED_PEOPLE_DETECTION_APP_HPP_
44 #include <pcl/people/ground_based_people_detection_app.h>
45 #include <pcl/filters/extract_indices.h>
46 #include <pcl/segmentation/extract_clusters.h>
47 #include <pcl/filters/voxel_grid.h>
49 template <
typename Po
intT>
58 head_centroid_ =
true;
65 updateMinMaxPoints ();
66 heads_minimum_distance_ = 0.3;
69 sqrt_ground_coeffs_ = std::numeric_limits<float>::quiet_NaN();
70 ground_coeffs_set_ =
false;
71 intrinsics_matrix_set_ =
false;
72 person_classifier_set_flag_ =
false;
75 transformation_set_ =
false;
78 template <
typename Po
intT>
void
84 template <
typename Po
intT>
void
87 if (!transformation.isUnitary())
89 PCL_ERROR (
"[pcl::people::GroundBasedPeopleDetectionApp::setCloudTransform] The cloud transformation matrix must be an orthogonal matrix!\n");
92 transformation_ = transformation;
93 transformation_set_ =
true;
94 applyTransformationGround();
95 applyTransformationIntrinsics();
98 template <
typename Po
intT>
void
101 ground_coeffs_ = ground_coeffs;
102 ground_coeffs_set_ =
true;
103 sqrt_ground_coeffs_ = (ground_coeffs - Eigen::Vector4f(0.0f, 0.0f, 0.0f, ground_coeffs(3))).norm();
104 applyTransformationGround();
107 template <
typename Po
intT>
void
110 sampling_factor_ = sampling_factor;
113 template <
typename Po
intT>
void
116 voxel_size_ = voxel_size;
117 updateMinMaxPoints ();
120 template <
typename Po
intT>
void
123 intrinsics_matrix_ = intrinsics_matrix;
124 intrinsics_matrix_set_ =
true;
125 applyTransformationIntrinsics();
128 template <
typename Po
intT>
void
131 person_classifier_ = person_classifier;
132 person_classifier_set_flag_ =
true;
135 template <
typename Po
intT>
void
142 template <
typename Po
intT>
void
145 vertical_ = vertical;
148 template<
typename Po
intT>
151 min_points_ =
static_cast<int> (min_height_ * min_width_ / voxel_size_ / voxel_size_);
152 max_points_ =
static_cast<int> (max_height_ * max_width_ / voxel_size_ / voxel_size_);
155 template <
typename Po
intT>
void
158 min_height_ = min_height;
159 max_height_ = max_height;
160 min_width_ = min_width;
161 max_width_ = max_width;
162 updateMinMaxPoints ();
165 template <
typename Po
intT>
void
168 heads_minimum_distance_= heads_minimum_distance;
171 template <
typename Po
intT>
void
174 head_centroid_ = head_centroid;
177 template <
typename Po
intT>
void
180 min_height = min_height_;
181 max_height = max_height_;
182 min_width = min_width_;
183 max_width = max_width_;
186 template <
typename Po
intT>
void
189 min_points = min_points_;
190 max_points = max_points_;
193 template <
typename Po
intT>
float
196 return (heads_minimum_distance_);
199 template <
typename Po
intT> Eigen::VectorXf
202 if (!ground_coeffs_set_)
204 PCL_ERROR (
"[pcl::people::GroundBasedPeopleDetectionApp::getGround] Floor parameters have not been set or they are not valid!\n");
206 return (ground_coeffs_);
212 return (cloud_filtered_);
218 return (no_ground_cloud_);
221 template <
typename Po
intT>
void
225 output_cloud->
points.resize(input_cloud->height*input_cloud->width);
226 output_cloud->
width = input_cloud->width;
227 output_cloud->
height = input_cloud->height;
230 for (std::uint32_t j = 0; j < input_cloud->width; j++)
232 for (std::uint32_t i = 0; i < input_cloud->height; i++)
234 rgb_point.r = (*input_cloud)(j,i).r;
235 rgb_point.g = (*input_cloud)(j,i).g;
236 rgb_point.b = (*input_cloud)(j,i).b;
237 (*output_cloud)(j,i) = rgb_point;
242 template <
typename Po
intT>
void
249 for (std::uint32_t i = 0; i < cloud->
width; i++)
251 for (std::uint32_t j = 0; j < cloud->
height; j++)
253 (*output_cloud)(j,i) = (*cloud)(cloud->
width - i - 1, j);
256 cloud = output_cloud;
259 template <
typename Po
intT>
void
262 if (transformation_set_)
264 Eigen::Transform<float, 3, Eigen::Affine> transform;
265 transform = transformation_;
270 template <
typename Po
intT>
void
273 if (transformation_set_ && ground_coeffs_set_)
275 Eigen::Transform<float, 3, Eigen::Affine> transform;
276 transform = transformation_;
277 ground_coeffs_transformed_ = transform.matrix() * ground_coeffs_;
281 ground_coeffs_transformed_ = ground_coeffs_;
285 template <
typename Po
intT>
void
288 if (transformation_set_ && intrinsics_matrix_set_)
290 intrinsics_matrix_transformed_ = intrinsics_matrix_ * transformation_.transpose();
294 intrinsics_matrix_transformed_ = intrinsics_matrix_;
298 template <
typename Po
intT>
void
304 grid.
setLeafSize(voxel_size_, voxel_size_, voxel_size_);
307 grid.
filter(*cloud_filtered_);
310 template <
typename Po
intT>
bool
314 if (!ground_coeffs_set_)
316 PCL_ERROR (
"[pcl::people::GroundBasedPeopleDetectionApp::compute] Floor parameters have not been set or they are not valid!\n");
319 if (cloud_ ==
nullptr)
321 PCL_ERROR (
"[pcl::people::GroundBasedPeopleDetectionApp::compute] Input cloud has not been set!\n");
324 if (!intrinsics_matrix_set_)
326 PCL_ERROR (
"[pcl::people::GroundBasedPeopleDetectionApp::compute] Camera intrinsic parameters have not been set!\n");
329 if (!person_classifier_set_flag_)
331 PCL_ERROR (
"[pcl::people::GroundBasedPeopleDetectionApp::compute] Person classifier has not been set!\n");
336 rgb_image_->points.clear();
337 extractRGBFromPointCloud(cloud_, rgb_image_);
340 if (sampling_factor_ != 1)
343 cloud_downsampled->width = (cloud_->width)/sampling_factor_;
344 cloud_downsampled->height = (cloud_->height)/sampling_factor_;
345 cloud_downsampled->points.resize(cloud_downsampled->height*cloud_downsampled->width);
346 cloud_downsampled->is_dense = cloud_->is_dense;
347 for (std::uint32_t j = 0; j < cloud_downsampled->width; j++)
349 for (std::uint32_t i = 0; i < cloud_downsampled->height; i++)
351 (*cloud_downsampled)(j,i) = (*cloud_)(sampling_factor_*j,sampling_factor_*i);
354 (*cloud_) = (*cloud_downsampled);
357 applyTransformationPointCloud();
370 extract.
filter(*no_ground_cloud_);
371 if (inliers->size () >= (300 * 0.06 / voxel_size_ / std::pow (
static_cast<double> (sampling_factor_), 2)))
374 PCL_INFO (
"No groundplane update!\n");
377 std::vector<pcl::PointIndices> cluster_indices;
391 subclustering.
setGround(ground_coeffs_transformed_);
401 swapDimensions(rgb_image_);
403 for(
auto it = clusters.begin(); it != clusters.end(); ++it)
406 Eigen::Vector3f centroid = intrinsics_matrix_transformed_ * (it->getTCenter());
407 centroid /= centroid(2);
408 Eigen::Vector3f top = intrinsics_matrix_transformed_ * (it->getTTop());
410 Eigen::Vector3f bottom = intrinsics_matrix_transformed_ * (it->getTBottom());
412 it->setPersonConfidence(person_classifier_.evaluate(rgb_image_, bottom, top, centroid, vertical_));
418 template <
typename Po
intT>
void filter(PointCloud &output)
Calls the filtering method and returns the filtered dataset in output.
void filter(Indices &indices)
Calls the filtering method and returns the filtered point cloud indices.
void setNegative(bool negative)
Set whether the regular conditions for points filtering should apply, or the inverted conditions.
virtual void setInputCloud(const PointCloudConstPtr &cloud)
Provide a pointer to the input dataset.
virtual void setIndices(const IndicesPtr &indices)
Provide a pointer to the vector of indices that represents the input data.
std::uint32_t width
The point cloud width (if organized as an image-structure).
std::uint32_t height
The point cloud height (if organized as an image-structure).
shared_ptr< PointCloud< PointT > > Ptr
std::vector< PointT, Eigen::aligned_allocator< PointT > > points
The point data.
SampleConsensusModelPlane defines a model for 3D plane segmentation.
void optimizeModelCoefficients(const Indices &inliers, const Eigen::VectorXf &model_coefficients, Eigen::VectorXf &optimized_coefficients) const override
Recompute the plane coefficients using the given inlier set and return them to the user.
void selectWithinDistance(const Eigen::VectorXf &model_coefficients, const double threshold, Indices &inliers) override
Select all the points which respect the given model coefficients as inliers.
shared_ptr< SampleConsensusModelPlane< PointT > > Ptr
VoxelGrid assembles a local 3D grid over a given PointCloud, and downsamples + filters the data.
void setFilterFieldName(const std::string &field_name)
Provide the name of the field to be used for filtering data.
void setLeafSize(const Eigen::Vector4f &leaf_size)
Set the voxel grid leaf size.
void setFilterLimits(const double &limit_min, const double &limit_max)
Set the field filter limits.
void getDimensionLimits(int &min_points, int &max_points)
Get minimum and maximum allowed number of points for a person cluster.
PointCloudPtr getNoGroundCloud()
Get pointcloud after voxel grid filtering and ground removal.
void filter()
Reduces the input cloud to one point per voxel and limits the field of view.
void applyTransformationIntrinsics()
Applies the transformation to the intrinsics matrix.
GroundBasedPeopleDetectionApp()
Constructor.
void setSamplingFactor(int sampling_factor)
Set sampling factor.
void extractRGBFromPointCloud(PointCloudPtr input_cloud, pcl::PointCloud< pcl::RGB >::Ptr &output_cloud)
Extract RGB information from a point cloud and output the corresponding RGB point cloud.
typename PointCloud::Ptr PointCloudPtr
void setMinimumDistanceBetweenHeads(float heads_minimum_distance)
Set minimum distance between persons' heads.
void setClassifier(pcl::people::PersonClassifier< pcl::RGB > person_classifier)
Set SVM-based person classifier.
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 setInputCloud(PointCloudPtr &cloud)
Set the pointer to the input cloud.
PointCloudPtr getFilteredCloud()
Get the filtered point cloud.
void setVoxelSize(float voxel_size)
Set voxel size.
void swapDimensions(pcl::PointCloud< pcl::RGB >::Ptr &cloud)
Swap rows/cols dimensions of a RGB point cloud (90 degrees counterclockwise rotation).
void setGround(Eigen::VectorXf &ground_coeffs)
Set the ground coefficients.
void updateMinMaxPoints()
Estimates min_points_ and max_points_ based on the minimal and maximal cluster size and the voxel siz...
void applyTransformationPointCloud()
Applies the transformation to the input point cloud.
void setIntrinsics(Eigen::Matrix3f intrinsics_matrix)
Set intrinsic parameters of the RGB camera.
void getPersonClusterLimits(float &min_height, float &max_height, float &min_width, float &max_width)
Get the minimum and maximum allowed height and width for a person cluster.
Eigen::VectorXf getGround()
Get floor coefficients.
void setFOV(float min, float max)
Set the field of view of the point cloud in z direction.
void setPersonClusterLimits(float min_height, float max_height, float min_width, float max_width)
Set minimum and maximum allowed height and width for a person cluster.
void setTransformation(const Eigen::Matrix3f &transformation)
Set the transformation matrix, which is used in order to transform the given point cloud,...
float getMinimumDistanceBetweenHeads()
Get minimum distance between persons' heads.
void applyTransformationGround()
Applies the transformation to the ground plane.
virtual ~GroundBasedPeopleDetectionApp()
Destructor.
bool compute(std::vector< pcl::people::PersonCluster< PointT > > &clusters)
Perform people detection on the input data and return people clusters information.
void setSensorPortraitOrientation(bool vertical)
Set sensor orientation (vertical = true means portrait mode, vertical = false means landscape mode).
HeadBasedSubclustering represents a class for searching for people inside a HeightMap2D based on a 3D...
void setGround(Eigen::VectorXf &ground_coeffs)
Set the ground coefficients.
void subcluster(std::vector< pcl::people::PersonCluster< PointT > > &clusters)
Compute subclusters and return them into a vector of PersonCluster.
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 setSensorPortraitOrientation(bool vertical)
Set sensor orientation to landscape mode (false) or portrait mode (true).
void setHeightLimits(float min_height, float max_height)
Set minimum and maximum allowed height for a person cluster.
void setInputCloud(PointCloudPtr &cloud)
Set input cloud.
PersonCluster represents a class for representing information about a cluster containing a person.
search::KdTree is a wrapper class which inherits the pcl::KdTree class for performing search function...
shared_ptr< KdTree< PointT, Tree > > Ptr
bool setInputCloud(const PointCloudConstPtr &cloud, const IndicesConstPtr &indices=IndicesConstPtr()) override
Provide a pointer to the input dataset.
void transformPointCloud(const pcl::PointCloud< PointT > &cloud_in, pcl::PointCloud< PointT > &cloud_out, const Eigen::Matrix< Scalar, 4, 4 > &transform, bool copy_all_fields)
Apply a rigid transform defined by a 4x4 matrix.
IndicesAllocator<> Indices
Type used for indices in PCL.
shared_ptr< Indices > IndicesPtr
A structure representing RGB color information.