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)
232 Eigen::Vector3d & centroid)
const
234 Eigen::Matrix<double, 1, 9, Eigen::RowMajor> accu = Eigen::Matrix<double, 1, 9, Eigen::RowMajor>::Zero ();
235 unsigned int point_count =
static_cast<unsigned int> (examples.size ());
237 for (std::size_t i = 0; i < point_count; ++i)
251 if (point_count != 0)
253 accu /=
static_cast<double> (point_count);
254 centroid.head<3> ().matrix () = accu.tail<3> ();
255 covariance_matrix.coeffRef (0) = accu[0] - accu[6] * accu[6];
256 covariance_matrix.coeffRef (1) = accu[1] - accu[6] * accu[7];
257 covariance_matrix.coeffRef (2) = accu[2] - accu[6] * accu[8];
258 covariance_matrix.coeffRef (4) = accu[3] - accu[7] * accu[7];
259 covariance_matrix.coeffRef (5) = accu[4] - accu[7] * accu[8];
260 covariance_matrix.coeffRef (8) = accu[5] - accu[8] * accu[8];
261 covariance_matrix.coeffRef (3) = covariance_matrix.coeff (1);
262 covariance_matrix.coeffRef (6) = covariance_matrix.coeff (2);
263 covariance_matrix.coeffRef (7) = covariance_matrix.coeff (5);
276 Eigen::Vector3d & centroid)
const
278 Eigen::Matrix<double, 1, 9, Eigen::RowMajor> accu = Eigen::Matrix<double, 1, 9, Eigen::RowMajor>::Zero ();
279 unsigned int point_count =
static_cast<unsigned int> (examples.size ());
281 for (std::size_t i = 0; i < point_count; ++i)
290 accu[6] += te.
rot_[0];
291 accu[7] += te.
rot_[1];
292 accu[8] += te.
rot_[2];
295 if (point_count != 0)
297 accu /=
static_cast<double> (point_count);
298 centroid.head<3> ().matrix () = accu.tail<3> ();
299 covariance_matrix.coeffRef (0) = accu[0] - accu[6] * accu[6];
300 covariance_matrix.coeffRef (1) = accu[1] - accu[6] * accu[7];
301 covariance_matrix.coeffRef (2) = accu[2] - accu[6] * accu[8];
302 covariance_matrix.coeffRef (4) = accu[3] - accu[7] * accu[7];
303 covariance_matrix.coeffRef (5) = accu[4] - accu[7] * accu[8];
304 covariance_matrix.coeffRef (8) = accu[5] - accu[8] * accu[8];
305 covariance_matrix.coeffRef (3) = covariance_matrix.coeff (1);
306 covariance_matrix.coeffRef (6) = covariance_matrix.coeff (2);
307 covariance_matrix.coeffRef (7) = covariance_matrix.coeff (5);
321 float computeInformationGain(DataSet & data_set, std::vector<ExampleIndex> & examples, std::vector<LabelDataType> & label_data,
322 std::vector<float> & results, std::vector<unsigned char> & flags,
const float threshold)
const override
324 const std::size_t num_of_examples = examples.size ();
328 std::vector < LabelDataType > sums (num_of_branches + 1, 0.f);
329 std::vector < LabelDataType > sqr_sums (num_of_branches + 1, 0.f);
330 std::vector < std::size_t > branch_element_count (num_of_branches + 1, 0.f);
332 for (std::size_t branch_index = 0; branch_index < num_of_branches; ++branch_index)
334 branch_element_count[branch_index] = 1;
335 ++branch_element_count[num_of_branches];
338 for (std::size_t example_index = 0; example_index < num_of_examples; ++example_index)
340 unsigned char branch_index;
341 computeBranchIndex (results[example_index], flags[example_index], threshold, branch_index);
343 LabelDataType label = label_data[example_index];
345 ++branch_element_count[branch_index];
346 ++branch_element_count[num_of_branches];
348 sums[branch_index] += label;
349 sums[num_of_branches] += label;
352 std::vector<float> hp (num_of_branches + 1, 0.f);
353 for (std::size_t branch_index = 0; branch_index < (num_of_branches + 1); ++branch_index)
355 float pf = sums[branch_index] /
static_cast<float> (branch_element_count[branch_index]);
356 float pnf = (
static_cast<LabelDataType
>(branch_element_count[branch_index]) - sums[branch_index] + 1.f)
357 /
static_cast<LabelDataType
> (branch_element_count[branch_index]);
358 hp[branch_index] -=
static_cast<float>(pf * std::log (pf) + pnf * std::log (pnf));
362 float purity = sums[num_of_branches] /
static_cast<LabelDataType
>(branch_element_count[num_of_branches]);
369 std::vector < std::size_t > branch_element_count (num_of_branches + 1, 0);
370 std::vector < std::vector<ExampleIndex> > positive_examples;
371 positive_examples.resize (num_of_branches + 1);
374 for (std::size_t example_index = 0; example_index < num_of_examples; ++example_index)
376 unsigned char branch_index;
377 computeBranchIndex (results[example_index], flags[example_index], threshold, branch_index);
379 LabelDataType label = label_data[example_index];
383 ++branch_element_count[branch_index];
384 ++branch_element_count[num_of_branches];
386 positive_examples[branch_index].push_back (examples[example_index]);
387 positive_examples[num_of_branches].push_back (examples[example_index]);
393 std::vector < Eigen::Matrix3d > offset_covariances;
394 std::vector < Eigen::Matrix3d > angle_covariances;
396 std::vector < Eigen::Vector3d > offset_centroids;
397 std::vector < Eigen::Vector3d > angle_centroids;
399 offset_covariances.resize (num_of_branches + 1);
400 angle_covariances.resize (num_of_branches + 1);
401 offset_centroids.resize (num_of_branches + 1);
402 angle_centroids.resize (num_of_branches + 1);
404 for (std::size_t branch_index = 0; branch_index < (num_of_branches + 1); ++branch_index)
407 offset_centroids[branch_index]);
409 angle_centroids[branch_index]);
413 std::vector<float> hr (num_of_branches + 1, 0.f);
414 for (std::size_t branch_index = 0; branch_index < (num_of_branches + 1); ++branch_index)
416 hr[branch_index] =
static_cast<float>(0.5f * std::log (std::pow (2 *
M_PI, 3)
417 * offset_covariances[branch_index].determinant ())
418 + 0.5f * std::log (std::pow (2 *
M_PI, 3)
419 * angle_covariances[branch_index].determinant ()));
422 for (std::size_t branch_index = 0; branch_index < (num_of_branches + 1); ++branch_index)
424 hp[branch_index] += std::max (sums[branch_index] /
static_cast<float> (branch_element_count[branch_index]) - tp, 0.f) * hr[branch_index];
428 float information_gain = hp[num_of_branches + 1];
429 for (std::size_t branch_index = 0; branch_index < (num_of_branches); ++branch_index)
431 information_gain -=
static_cast<float> (branch_element_count[branch_index]) /
static_cast<float> (branch_element_count[num_of_branches])
435 return information_gain;
444 void computeBranchIndices(std::vector<float> & results, std::vector<unsigned char> & flags,
const float threshold,
445 std::vector<unsigned char> & branch_indices)
const override
447 const std::size_t num_of_results = results.size ();
449 branch_indices.resize (num_of_results);
450 for (std::size_t result_index = 0; result_index < num_of_results; ++result_index)
452 unsigned char branch_index;
453 computeBranchIndex (results[result_index], flags[result_index], threshold, branch_index);
454 branch_indices[result_index] = branch_index;
464 inline void computeBranchIndex(
const float result,
const unsigned char flag,
const float threshold,
unsigned char & branch_index)
const override
475 void computeAndSetNodeStats(DataSet & data_set, std::vector<ExampleIndex> & examples, std::vector<LabelDataType> & label_data, NodeType & node)
const override
477 const std::size_t num_of_examples = examples.size ();
479 LabelDataType sum = 0.0f;
480 LabelDataType sqr_sum = 0.0f;
481 for (std::size_t example_index = 0; example_index < num_of_examples; ++example_index)
483 const LabelDataType label = label_data[example_index];
486 sqr_sum += label * label;
489 sum /=
static_cast<float>(num_of_examples);
490 sqr_sum /=
static_cast<float>(num_of_examples);
492 const float variance = sqr_sum - sum * sum;
495 node.variance = variance;
498 std::vector < ExampleIndex > positive_examples;
500 for (std::size_t example_index = 0; example_index < num_of_examples; ++example_index)
502 LabelDataType label = label_data[example_index];
505 positive_examples.push_back (examples[example_index]);
520 stream <<
"ERROR: RegressionVarianceStatsEstimator does not implement generateCodeForBranchIndex(...)";
529 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.
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.
~PoseClassRegressionVarianceStatsEstimator()
Destructor.
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.