10 #include "pcl/recognition/face_detection/face_common.h"
11 #include <pcl/ml/feature_handler.h>
12 #include <pcl/ml/stats_estimator.h>
13 #include <pcl/ml/branch_estimator.h>
17 namespace face_detection
19 template<
class FT,
class DataSet,
class ExampleIndex>
27 float min_valid_small_patch_depth_;
35 min_valid_small_patch_depth_ = 0.5f;
96 srand (static_cast<unsigned int>(time (
nullptr)));
98 float range_d = 0.05f;
101 std::vector < FT > windows_and_functions;
103 for (std::size_t i = 0; i < num_of_features; i++)
107 f.row1_ = rand () % (wsize_ - max_patch_size_ - 1);
108 f.col1_ = rand () % (wsize_ / 2 - max_patch_size_ - 1);
109 f.wsizex1_ = min_s + (rand () % (max_patch_size_ - min_s - 1));
110 f.wsizey1_ = min_s + (rand () % (max_patch_size_ - min_s - 1));
112 f.row2_ = rand () % (wsize_ - max_patch_size_ - 1);
113 f.col2_ = wsize_ / 2 + rand () % (wsize_ / 2 - max_patch_size_ - 1);
114 f.wsizex2_ = min_s + (rand () % (max_patch_size_ - 1 - min_s));
115 f.wsizey2_ = min_s + (rand () % (max_patch_size_ - 1 - min_s));
118 if (num_channels_ > 1)
119 f.used_ii_ = rand () % num_channels_;
121 windows_and_functions.push_back (f);
124 for (std::size_t i = 0; i < windows_and_functions.size (); i++)
126 FT f = windows_and_functions[i];
127 for (std::size_t j = 0; j <= 10; j++)
129 f.threshold_ = -range_d +
static_cast<float> (j) * incr_d;
130 features.push_back (f);
142 void evaluateFeature(
const FT & feature, DataSet & data_set, std::vector<ExampleIndex> & examples, std::vector<float> & results,
143 std::vector<unsigned char> & flags)
const override
145 results.resize (examples.size ());
146 for (std::size_t i = 0; i < examples.size (); i++)
148 evaluateFeature (feature, data_set, examples[i], results[i], flags[i]);
159 void evaluateFeature(
const FT & feature, DataSet & data_set,
const ExampleIndex & example,
float & result,
unsigned char & flag)
const override
162 int el_f1 = te.
iimages_[feature.used_ii_]->getFiniteElementsCount (te.
col_ + feature.col1_, te.
row_ + feature.row1_, feature.wsizex1_,
164 int el_f2 = te.
iimages_[feature.used_ii_]->getFiniteElementsCount (te.
col_ + feature.col2_, te.
row_ + feature.row2_, feature.wsizex2_,
167 float sum_f1 =
static_cast<float>(te.
iimages_[feature.used_ii_]->getFirstOrderSum (te.
col_ + feature.col1_, te.
row_ + feature.row1_, feature.wsizex1_, feature.wsizey1_));
168 float sum_f2 =
static_cast<float>(te.
iimages_[feature.used_ii_]->getFirstOrderSum (te.
col_ + feature.col2_, te.
row_ + feature.row2_, feature.wsizex2_, feature.wsizey2_));
170 float f = min_valid_small_patch_depth_;
171 if (el_f1 == 0 || el_f2 == 0 || (el_f1 <= static_cast<int> (f * static_cast<float>(feature.wsizex1_ * feature.wsizey1_)))
172 || (el_f2 <= static_cast<int> (f *
static_cast<float>(feature.wsizex2_ * feature.wsizey2_))))
174 result =
static_cast<float> (pcl_round (static_cast<float>(rand ()) / static_cast<float> (RAND_MAX)));
178 result =
static_cast<float> ((sum_f1 /
static_cast<float>(el_f1) - sum_f2 / static_cast<float>(el_f2)) > feature.threshold_);
195 template<
class LabelDataType,
class NodeType,
class DataSet,
class ExampleIndex>
202 branch_estimator_ (branch_estimator)
230 Eigen::Vector3d & centroid)
const
232 Eigen::Matrix<double, 1, 9, Eigen::RowMajor> accu = Eigen::Matrix<double, 1, 9, Eigen::RowMajor>::Zero ();
233 auto point_count =
static_cast<unsigned int> (examples.size ());
235 for (std::size_t i = 0; i < point_count; ++i)
249 if (point_count != 0)
251 accu /=
static_cast<double> (point_count);
252 centroid.head<3> ().matrix () = accu.tail<3> ();
253 covariance_matrix.coeffRef (0) = accu[0] - accu[6] * accu[6];
254 covariance_matrix.coeffRef (1) = accu[1] - accu[6] * accu[7];
255 covariance_matrix.coeffRef (2) = accu[2] - accu[6] * accu[8];
256 covariance_matrix.coeffRef (4) = accu[3] - accu[7] * accu[7];
257 covariance_matrix.coeffRef (5) = accu[4] - accu[7] * accu[8];
258 covariance_matrix.coeffRef (8) = accu[5] - accu[8] * accu[8];
259 covariance_matrix.coeffRef (3) = covariance_matrix.coeff (1);
260 covariance_matrix.coeffRef (6) = covariance_matrix.coeff (2);
261 covariance_matrix.coeffRef (7) = covariance_matrix.coeff (5);
274 Eigen::Vector3d & centroid)
const
276 Eigen::Matrix<double, 1, 9, Eigen::RowMajor> accu = Eigen::Matrix<double, 1, 9, Eigen::RowMajor>::Zero ();
277 auto point_count =
static_cast<unsigned int> (examples.size ());
279 for (std::size_t i = 0; i < point_count; ++i)
288 accu[6] += te.
rot_[0];
289 accu[7] += te.
rot_[1];
290 accu[8] += te.
rot_[2];
293 if (point_count != 0)
295 accu /=
static_cast<double> (point_count);
296 centroid.head<3> ().matrix () = accu.tail<3> ();
297 covariance_matrix.coeffRef (0) = accu[0] - accu[6] * accu[6];
298 covariance_matrix.coeffRef (1) = accu[1] - accu[6] * accu[7];
299 covariance_matrix.coeffRef (2) = accu[2] - accu[6] * accu[8];
300 covariance_matrix.coeffRef (4) = accu[3] - accu[7] * accu[7];
301 covariance_matrix.coeffRef (5) = accu[4] - accu[7] * accu[8];
302 covariance_matrix.coeffRef (8) = accu[5] - accu[8] * accu[8];
303 covariance_matrix.coeffRef (3) = covariance_matrix.coeff (1);
304 covariance_matrix.coeffRef (6) = covariance_matrix.coeff (2);
305 covariance_matrix.coeffRef (7) = covariance_matrix.coeff (5);
319 float computeInformationGain(DataSet & data_set, std::vector<ExampleIndex> & examples, std::vector<LabelDataType> & label_data,
320 std::vector<float> & results, std::vector<unsigned char> & flags,
const float threshold)
const override
322 const std::size_t num_of_examples = examples.size ();
326 std::vector < LabelDataType > sums (num_of_branches + 1, 0.f);
327 std::vector < LabelDataType > sqr_sums (num_of_branches + 1, 0.f);
328 std::vector < std::size_t > branch_element_count (num_of_branches + 1, 0.f);
330 for (std::size_t branch_index = 0; branch_index < num_of_branches; ++branch_index)
332 branch_element_count[branch_index] = 1;
333 ++branch_element_count[num_of_branches];
336 for (std::size_t example_index = 0; example_index < num_of_examples; ++example_index)
338 unsigned char branch_index;
339 computeBranchIndex (results[example_index], flags[example_index], threshold, branch_index);
341 LabelDataType label = label_data[example_index];
343 ++branch_element_count[branch_index];
344 ++branch_element_count[num_of_branches];
346 sums[branch_index] += label;
347 sums[num_of_branches] += label;
350 std::vector<float> hp (num_of_branches + 1, 0.f);
351 for (std::size_t branch_index = 0; branch_index < (num_of_branches + 1); ++branch_index)
353 float pf = sums[branch_index] /
static_cast<float> (branch_element_count[branch_index]);
354 float pnf = (
static_cast<LabelDataType
>(branch_element_count[branch_index]) - sums[branch_index] + 1.f)
355 /
static_cast<LabelDataType
> (branch_element_count[branch_index]);
356 hp[branch_index] -=
static_cast<float>(pf * std::log (pf) + pnf * std::log (pnf));
360 float purity = sums[num_of_branches] /
static_cast<LabelDataType
>(branch_element_count[num_of_branches]);
367 std::vector < std::size_t > branch_element_count (num_of_branches + 1, 0);
368 std::vector < std::vector<ExampleIndex> > positive_examples;
369 positive_examples.resize (num_of_branches + 1);
371 for (std::size_t example_index = 0; example_index < num_of_examples; ++example_index)
373 unsigned char branch_index;
374 computeBranchIndex (results[example_index], flags[example_index], threshold, branch_index);
376 LabelDataType label = label_data[example_index];
380 ++branch_element_count[branch_index];
381 ++branch_element_count[num_of_branches];
383 positive_examples[branch_index].push_back (examples[example_index]);
384 positive_examples[num_of_branches].push_back (examples[example_index]);
389 std::vector < Eigen::Matrix3d > offset_covariances;
390 std::vector < Eigen::Matrix3d > angle_covariances;
392 std::vector < Eigen::Vector3d > offset_centroids;
393 std::vector < Eigen::Vector3d > angle_centroids;
395 offset_covariances.resize (num_of_branches + 1);
396 angle_covariances.resize (num_of_branches + 1);
397 offset_centroids.resize (num_of_branches + 1);
398 angle_centroids.resize (num_of_branches + 1);
400 for (std::size_t branch_index = 0; branch_index < (num_of_branches + 1); ++branch_index)
403 offset_centroids[branch_index]);
405 angle_centroids[branch_index]);
409 std::vector<float> hr (num_of_branches + 1, 0.f);
410 for (std::size_t branch_index = 0; branch_index < (num_of_branches + 1); ++branch_index)
412 hr[branch_index] =
static_cast<float>(0.5f * std::log (std::pow (2 * M_PI, 3)
413 * offset_covariances[branch_index].determinant ())
414 + 0.5f * std::log (std::pow (2 * M_PI, 3)
415 * angle_covariances[branch_index].determinant ()));
418 for (std::size_t branch_index = 0; branch_index < (num_of_branches + 1); ++branch_index)
420 hp[branch_index] += std::max (sums[branch_index] / static_cast<float> (branch_element_count[branch_index]) - tp, 0.f) * hr[branch_index];
424 float information_gain = hp[num_of_branches + 1];
425 for (std::size_t branch_index = 0; branch_index < (num_of_branches); ++branch_index)
427 information_gain -=
static_cast<float> (branch_element_count[branch_index]) / static_cast<float> (branch_element_count[num_of_branches])
431 return information_gain;
440 void computeBranchIndices(std::vector<float> & results, std::vector<unsigned char> & flags,
const float threshold,
441 std::vector<unsigned char> & branch_indices)
const override
443 const std::size_t num_of_results = results.size ();
445 branch_indices.resize (num_of_results);
446 for (std::size_t result_index = 0; result_index < num_of_results; ++result_index)
448 unsigned char branch_index;
449 computeBranchIndex (results[result_index], flags[result_index], threshold, branch_index);
450 branch_indices[result_index] = branch_index;
460 inline void computeBranchIndex(
const float result,
const unsigned char flag,
const float threshold,
unsigned char & branch_index)
const override
471 void computeAndSetNodeStats(DataSet & data_set, std::vector<ExampleIndex> & examples, std::vector<LabelDataType> & label_data, NodeType & node)
const override
473 const std::size_t num_of_examples = examples.size ();
475 LabelDataType sum = 0.0f;
476 LabelDataType sqr_sum = 0.0f;
477 for (std::size_t example_index = 0; example_index < num_of_examples; ++example_index)
479 const LabelDataType label = label_data[example_index];
482 sqr_sum += label * label;
485 sum /=
static_cast<float>(num_of_examples);
486 sqr_sum /=
static_cast<float>(num_of_examples);
488 const float variance = sqr_sum - sum * sum;
491 node.variance = variance;
494 std::vector < ExampleIndex > positive_examples;
496 for (std::size_t example_index = 0; example_index < num_of_examples; ++example_index)
498 LabelDataType label = label_data[example_index];
501 positive_examples.push_back (examples[example_index]);
516 stream <<
"ERROR: RegressionVarianceStatsEstimator does not implement generateCodeForBranchIndex(...)";
525 stream <<
"ERROR: RegressionVarianceStatsEstimator does not implement generateCodeForBranchIndex(...)";
std::vector< pcl::IntegralImage2D< float, 1 >::Ptr > iimages_
void setMaxPatchSize(int w)
Create a set of random tests to evaluate examples.
virtual std::size_t getNumOfBranches() const =0
Returns the number of branches the corresponding tree has.
unsigned int computeMeanAndCovarianceOffset(DataSet &data_set, std::vector< ExampleIndex > &examples, Eigen::Matrix3d &covariance_matrix, Eigen::Vector3d ¢roid) const
Computes the covariance matrix for translation offsets.
void evaluateFeature(const FT &feature, DataSet &data_set, const ExampleIndex &example, float &result, unsigned char &flag) const override
Evaluates a feature on the specified example.
void generateCodeForEvaluation(const FT &,::std::ostream &) const override
Generates evaluation code for the specified feature and writes it to the specified stream...
void createRandomFeatures(const std::size_t num_of_features, std::vector< FT > &features) override
Create a set of random tests to evaluate examples.
void setWSize(int w)
Sets the size of the window to extract features.
LabelDataType getLabelOfNode(NodeType &node) const override
Returns the label of the specified node.
PoseClassRegressionVarianceStatsEstimator(BranchEstimator *branch_estimator)
Constructor.
std::size_t getNumOfBranches() const override
Returns the number of branches the corresponding tree has.
void evaluateFeature(const FT &feature, DataSet &data_set, std::vector< ExampleIndex > &examples, std::vector< float > &results, std::vector< unsigned char > &flags) const override
Evaluates a feature on the specified set of examples.
void generateCodeForOutput(NodeType &, std::ostream &stream) const override
Generates code for label output.
Class interface for gathering statistics for decision tree learning.
virtual void computeBranchIndex(const float result, const unsigned char flag, const float threshold, unsigned char &branch_index) const =0
Computes the branch index for the specified result.
float computeInformationGain(DataSet &data_set, std::vector< ExampleIndex > &examples, std::vector< LabelDataType > &label_data, std::vector< float > &results, std::vector< unsigned char > &flags, const float threshold) const override
Computes the information gain obtained by the specified threshold.
unsigned int computeMeanAndCovarianceAngles(DataSet &data_set, std::vector< ExampleIndex > &examples, Eigen::Matrix3d &covariance_matrix, Eigen::Vector3d ¢roid) const
Computes the covariance matrix for rotation values.
Statistics estimator for regression trees which optimizes information gain and pose parameters error...
void computeBranchIndices(std::vector< float > &results, std::vector< unsigned char > &flags, const float threshold, std::vector< unsigned char > &branch_indices) const override
Computes the branch indices for all supplied results.
FeatureHandlerDepthAverage()
void computeBranchIndex(const float result, const unsigned char flag, const float threshold, unsigned char &branch_index) const override
Computes the branch index for the specified result.
void setNumChannels(int nf)
Sets the number of channels a feature has (i.e.
~PoseClassRegressionVarianceStatsEstimator() override=default
Destructor.
void computeAndSetNodeStats(DataSet &data_set, std::vector< ExampleIndex > &examples, std::vector< LabelDataType > &label_data, NodeType &node) const override
Computes and sets the statistics for a node.
Interface for branch estimators.
Utility class interface which is used for creating and evaluating features.
void generateCodeForBranchIndexComputation(NodeType &, std::ostream &stream) const override
Generates code for branch index computation.