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 unsigned int 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 unsigned int 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);
372 for (std::size_t example_index = 0; example_index < num_of_examples; ++example_index)
374 unsigned char branch_index;
375 computeBranchIndex (results[example_index], flags[example_index], threshold, branch_index);
377 LabelDataType label = label_data[example_index];
381 ++branch_element_count[branch_index];
382 ++branch_element_count[num_of_branches];
384 positive_examples[branch_index].push_back (examples[example_index]);
385 positive_examples[num_of_branches].push_back (examples[example_index]);
391 std::vector < Eigen::Matrix3d > offset_covariances;
392 std::vector < Eigen::Matrix3d > angle_covariances;
394 std::vector < Eigen::Vector3d > offset_centroids;
395 std::vector < Eigen::Vector3d > angle_centroids;
397 offset_covariances.resize (num_of_branches + 1);
398 angle_covariances.resize (num_of_branches + 1);
399 offset_centroids.resize (num_of_branches + 1);
400 angle_centroids.resize (num_of_branches + 1);
402 for (std::size_t branch_index = 0; branch_index < (num_of_branches + 1); ++branch_index)
405 offset_centroids[branch_index]);
407 angle_centroids[branch_index]);
411 std::vector<float> hr (num_of_branches + 1, 0.f);
412 for (std::size_t branch_index = 0; branch_index < (num_of_branches + 1); ++branch_index)
414 hr[branch_index] =
static_cast<float>(0.5f * std::log (std::pow (2 *
M_PI, 3)
415 * offset_covariances[branch_index].determinant ())
416 + 0.5f * std::log (std::pow (2 *
M_PI, 3)
417 * angle_covariances[branch_index].determinant ()));
420 for (std::size_t branch_index = 0; branch_index < (num_of_branches + 1); ++branch_index)
422 hp[branch_index] += std::max (sums[branch_index] /
static_cast<float> (branch_element_count[branch_index]) - tp, 0.f) * hr[branch_index];
426 float information_gain = hp[num_of_branches + 1];
427 for (std::size_t branch_index = 0; branch_index < (num_of_branches); ++branch_index)
429 information_gain -=
static_cast<float> (branch_element_count[branch_index]) /
static_cast<float> (branch_element_count[num_of_branches])
433 return information_gain;
442 void computeBranchIndices(std::vector<float> & results, std::vector<unsigned char> & flags,
const float threshold,
443 std::vector<unsigned char> & branch_indices)
const override
445 const std::size_t num_of_results = results.size ();
447 branch_indices.resize (num_of_results);
448 for (std::size_t result_index = 0; result_index < num_of_results; ++result_index)
450 unsigned char branch_index;
451 computeBranchIndex (results[result_index], flags[result_index], threshold, branch_index);
452 branch_indices[result_index] = branch_index;
462 inline void computeBranchIndex(
const float result,
const unsigned char flag,
const float threshold,
unsigned char & branch_index)
const override
473 void computeAndSetNodeStats(DataSet & data_set, std::vector<ExampleIndex> & examples, std::vector<LabelDataType> & label_data, NodeType & node)
const override
475 const std::size_t num_of_examples = examples.size ();
477 LabelDataType sum = 0.0f;
478 LabelDataType sqr_sum = 0.0f;
479 for (std::size_t example_index = 0; example_index < num_of_examples; ++example_index)
481 const LabelDataType label = label_data[example_index];
484 sqr_sum += label * label;
487 sum /=
static_cast<float>(num_of_examples);
488 sqr_sum /=
static_cast<float>(num_of_examples);
490 const float variance = sqr_sum - sum * sum;
493 node.variance = variance;
496 std::vector < ExampleIndex > positive_examples;
498 for (std::size_t example_index = 0; example_index < num_of_examples; ++example_index)
500 LabelDataType label = label_data[example_index];
503 positive_examples.push_back (examples[example_index]);
518 stream <<
"ERROR: RegressionVarianceStatsEstimator does not implement generateCodeForBranchIndex(...)";
527 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.