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(...)";
Interface for branch estimators.
virtual std::size_t getNumOfBranches() const =0
Returns the number of branches the corresponding tree has.
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.
Utility class interface which is used for creating and evaluating features.
Class interface for gathering statistics for decision tree learning.
void setWSize(int w)
Sets the size of the window to extract features.
void setMaxPatchSize(int w)
Create a set of random tests to evaluate examples.
FeatureHandlerDepthAverage()
void createRandomFeatures(const std::size_t num_of_features, std::vector< FT > &features) override
Create a set of random tests to evaluate examples.
void generateCodeForEvaluation(const FT &, ::std::ostream &) const override
Generates evaluation code for the specified feature and writes it to the specified stream.
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 setNumChannels(int nf)
Sets the number of channels a feature has (i.e.
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.
Statistics estimator for regression trees which optimizes information gain and pose parameters error.
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.
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.
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.
LabelDataType getLabelOfNode(NodeType &node) const override
Returns the label of the specified node.
PoseClassRegressionVarianceStatsEstimator(BranchEstimator *branch_estimator)
Constructor.
~PoseClassRegressionVarianceStatsEstimator() override=default
Destructor.
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 generateCodeForBranchIndexComputation(NodeType &, std::ostream &stream) const override
Generates code for branch index computation.
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 generateCodeForOutput(NodeType &, std::ostream &stream) const override
Generates code for label output.
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.
std::size_t getNumOfBranches() const override
Returns the number of branches the corresponding tree has.
std::vector< pcl::IntegralImage2D< float, 1 >::Ptr > iimages_
__inline double pcl_round(double number)
Win32 doesn't seem to have rounding functions.