8 #ifndef PCL_RF_FACE_UTILS_H_ 9 #define PCL_RF_FACE_UTILS_H_ 11 #include "pcl/recognition/face_detection/face_common.h" 12 #include <pcl/ml/feature_handler.h> 13 #include <pcl/ml/stats_estimator.h> 14 #include <pcl/ml/branch_estimator.h> 18 namespace face_detection
20 template<
class FT,
class DataSet,
class ExampleIndex>
28 float min_valid_small_patch_depth_;
36 min_valid_small_patch_depth_ = 0.5f;
97 srand (static_cast<unsigned int>(time (NULL)));
99 float range_d = 0.05f;
100 float incr_d = 0.01f;
102 std::vector < FT > windows_and_functions;
104 for (
size_t i = 0; i < num_of_features; i++)
108 f.row1_ = rand () % (wsize_ - max_patch_size_ - 1);
109 f.col1_ = rand () % (wsize_ / 2 - max_patch_size_ - 1);
110 f.wsizex1_ = min_s + (rand () % (max_patch_size_ - min_s - 1));
111 f.wsizey1_ = min_s + (rand () % (max_patch_size_ - min_s - 1));
113 f.row2_ = rand () % (wsize_ - max_patch_size_ - 1);
114 f.col2_ = wsize_ / 2 + rand () % (wsize_ / 2 - max_patch_size_ - 1);
115 f.wsizex2_ = min_s + (rand () % (max_patch_size_ - 1 - min_s));
116 f.wsizey2_ = min_s + (rand () % (max_patch_size_ - 1 - min_s));
119 if (num_channels_ > 1)
120 f.used_ii_ = rand () % num_channels_;
122 windows_and_functions.push_back (f);
125 for (
size_t i = 0; i < windows_and_functions.size (); i++)
127 FT f = windows_and_functions[i];
128 for (
size_t j = 0; j <= 10; j++)
130 f.threshold_ = -range_d + static_cast<float> (j) * incr_d;
131 features.push_back (f);
143 void evaluateFeature(
const FT & feature, DataSet & data_set, std::vector<ExampleIndex> & examples, std::vector<float> & results,
144 std::vector<unsigned char> & flags)
const 146 results.resize (examples.size ());
147 for (
size_t i = 0; i < examples.size (); i++)
149 evaluateFeature (feature, data_set, examples[i], results[i], flags[i]);
160 void evaluateFeature(
const FT & feature, DataSet & data_set,
const ExampleIndex & example,
float & result,
unsigned char & flag)
const 163 int el_f1 = te.
iimages_[feature.used_ii_]->getFiniteElementsCount (te.
col_ + feature.col1_, te.
row_ + feature.row1_, feature.wsizex1_,
165 int el_f2 = te.
iimages_[feature.used_ii_]->getFiniteElementsCount (te.
col_ + feature.col2_, te.
row_ + feature.row2_, feature.wsizex2_,
168 float sum_f1 = static_cast<float>(te.
iimages_[feature.used_ii_]->getFirstOrderSum (te.
col_ + feature.col1_, te.
row_ + feature.row1_, feature.wsizex1_, feature.wsizey1_));
169 float sum_f2 = static_cast<float>(te.
iimages_[feature.used_ii_]->getFirstOrderSum (te.
col_ + feature.col2_, te.
row_ + feature.row2_, feature.wsizex2_, feature.wsizey2_));
171 float f = min_valid_small_patch_depth_;
172 if (el_f1 == 0 || el_f2 == 0 || (el_f1 <= static_cast<int> (f * static_cast<float>(feature.wsizex1_ * feature.wsizey1_)))
173 || (el_f2 <= static_cast<int> (f * static_cast<float>(feature.wsizex2_ * feature.wsizey2_))))
175 result = static_cast<float> (pcl_round (static_cast<float>(rand ()) / static_cast<float> (RAND_MAX)));
179 result = static_cast<float> ((sum_f1 / static_cast<float>(el_f1) - sum_f2 / static_cast<float>(el_f2)) > feature.threshold_);
196 template<
class LabelDataType,
class NodeType,
class DataSet,
class ExampleIndex>
203 branch_estimator_ (branch_estimator)
233 Eigen::Vector3d & centroid)
const 235 Eigen::Matrix<double, 1, 9, Eigen::RowMajor> accu = Eigen::Matrix<double, 1, 9, Eigen::RowMajor>::Zero ();
236 unsigned int point_count = static_cast<unsigned int> (examples.size ());
238 for (
size_t i = 0; i < point_count; ++i)
252 if (point_count != 0)
254 accu /= static_cast<double> (point_count);
255 centroid.head<3> ().matrix () = accu.tail<3> ();
256 covariance_matrix.coeffRef (0) = accu[0] - accu[6] * accu[6];
257 covariance_matrix.coeffRef (1) = accu[1] - accu[6] * accu[7];
258 covariance_matrix.coeffRef (2) = accu[2] - accu[6] * accu[8];
259 covariance_matrix.coeffRef (4) = accu[3] - accu[7] * accu[7];
260 covariance_matrix.coeffRef (5) = accu[4] - accu[7] * accu[8];
261 covariance_matrix.coeffRef (8) = accu[5] - accu[8] * accu[8];
262 covariance_matrix.coeffRef (3) = covariance_matrix.coeff (1);
263 covariance_matrix.coeffRef (6) = covariance_matrix.coeff (2);
264 covariance_matrix.coeffRef (7) = covariance_matrix.coeff (5);
277 Eigen::Vector3d & centroid)
const 279 Eigen::Matrix<double, 1, 9, Eigen::RowMajor> accu = Eigen::Matrix<double, 1, 9, Eigen::RowMajor>::Zero ();
280 unsigned int point_count = static_cast<unsigned int> (examples.size ());
282 for (
size_t i = 0; i < point_count; ++i)
291 accu[6] += te.
rot_[0];
292 accu[7] += te.
rot_[1];
293 accu[8] += te.
rot_[2];
296 if (point_count != 0)
298 accu /= static_cast<double> (point_count);
299 centroid.head<3> ().matrix () = accu.tail<3> ();
300 covariance_matrix.coeffRef (0) = accu[0] - accu[6] * accu[6];
301 covariance_matrix.coeffRef (1) = accu[1] - accu[6] * accu[7];
302 covariance_matrix.coeffRef (2) = accu[2] - accu[6] * accu[8];
303 covariance_matrix.coeffRef (4) = accu[3] - accu[7] * accu[7];
304 covariance_matrix.coeffRef (5) = accu[4] - accu[7] * accu[8];
305 covariance_matrix.coeffRef (8) = accu[5] - accu[8] * accu[8];
306 covariance_matrix.coeffRef (3) = covariance_matrix.coeff (1);
307 covariance_matrix.coeffRef (6) = covariance_matrix.coeff (2);
308 covariance_matrix.coeffRef (7) = covariance_matrix.coeff (5);
322 float computeInformationGain(DataSet & data_set, std::vector<ExampleIndex> & examples, std::vector<LabelDataType> & label_data,
323 std::vector<float> & results, std::vector<unsigned char> & flags,
const float threshold)
const 325 const size_t num_of_examples = examples.size ();
329 std::vector < LabelDataType > sums (num_of_branches + 1, 0.f);
330 std::vector < LabelDataType > sqr_sums (num_of_branches + 1, 0.f);
331 std::vector < size_t > branch_element_count (num_of_branches + 1, 0.f);
333 for (
size_t branch_index = 0; branch_index < num_of_branches; ++branch_index)
335 branch_element_count[branch_index] = 1;
336 ++branch_element_count[num_of_branches];
339 for (
size_t example_index = 0; example_index < num_of_examples; ++example_index)
341 unsigned char branch_index;
342 computeBranchIndex (results[example_index], flags[example_index], threshold, branch_index);
344 LabelDataType label = label_data[example_index];
346 ++branch_element_count[branch_index];
347 ++branch_element_count[num_of_branches];
349 sums[branch_index] += label;
350 sums[num_of_branches] += label;
353 std::vector<float> hp (num_of_branches + 1, 0.f);
354 for (
size_t branch_index = 0; branch_index < (num_of_branches + 1); ++branch_index)
356 float pf = sums[branch_index] / static_cast<float> (branch_element_count[branch_index]);
357 float pnf = (static_cast<LabelDataType>(branch_element_count[branch_index]) - sums[branch_index] + 1.f)
358 / static_cast<LabelDataType> (branch_element_count[branch_index]);
359 hp[branch_index] -= static_cast<float>(pf * log (pf) + pnf * log (pnf));
363 float purity = sums[num_of_branches] / static_cast<LabelDataType>(branch_element_count[num_of_branches]);
370 std::vector < size_t > branch_element_count (num_of_branches + 1, 0);
371 std::vector < std::vector<ExampleIndex> > positive_examples;
372 positive_examples.resize (num_of_branches + 1);
375 for (
size_t example_index = 0; example_index < num_of_examples; ++example_index)
377 unsigned char branch_index;
378 computeBranchIndex (results[example_index], flags[example_index], threshold, branch_index);
380 LabelDataType label = label_data[example_index];
384 ++branch_element_count[branch_index];
385 ++branch_element_count[num_of_branches];
387 positive_examples[branch_index].push_back (examples[example_index]);
388 positive_examples[num_of_branches].push_back (examples[example_index]);
394 std::vector < Eigen::Matrix3d > offset_covariances;
395 std::vector < Eigen::Matrix3d > angle_covariances;
397 std::vector < Eigen::Vector3d > offset_centroids;
398 std::vector < Eigen::Vector3d > angle_centroids;
400 offset_covariances.resize (num_of_branches + 1);
401 angle_covariances.resize (num_of_branches + 1);
402 offset_centroids.resize (num_of_branches + 1);
403 angle_centroids.resize (num_of_branches + 1);
405 for (
size_t branch_index = 0; branch_index < (num_of_branches + 1); ++branch_index)
408 offset_centroids[branch_index]);
410 angle_centroids[branch_index]);
414 std::vector<float> hr (num_of_branches + 1, 0.f);
415 for (
size_t branch_index = 0; branch_index < (num_of_branches + 1); ++branch_index)
417 hr[branch_index] = static_cast<float>(0.5f * log (std::pow (2 * M_PI, 3)
418 * offset_covariances[branch_index].determinant ())
419 + 0.5f * log (std::pow (2 * M_PI, 3)
420 * angle_covariances[branch_index].determinant ()));
423 for (
size_t branch_index = 0; branch_index < (num_of_branches + 1); ++branch_index)
425 hp[branch_index] += std::max (sums[branch_index] / static_cast<float> (branch_element_count[branch_index]) - tp, 0.f) * hr[branch_index];
429 float information_gain = hp[num_of_branches + 1];
430 for (
size_t branch_index = 0; branch_index < (num_of_branches); ++branch_index)
432 information_gain -= static_cast<float> (branch_element_count[branch_index]) / static_cast<float> (branch_element_count[num_of_branches])
436 return information_gain;
445 void computeBranchIndices(std::vector<float> & results, std::vector<unsigned char> & flags,
const float threshold,
446 std::vector<unsigned char> & branch_indices)
const 448 const size_t num_of_results = results.size ();
450 branch_indices.resize (num_of_results);
451 for (
size_t result_index = 0; result_index < num_of_results; ++result_index)
453 unsigned char branch_index;
454 computeBranchIndex (results[result_index], flags[result_index], threshold, branch_index);
455 branch_indices[result_index] = branch_index;
465 inline void computeBranchIndex(
const float result,
const unsigned char flag,
const float threshold,
unsigned char & branch_index)
const 476 void computeAndSetNodeStats(DataSet & data_set, std::vector<ExampleIndex> & examples, std::vector<LabelDataType> & label_data, NodeType & node)
const 478 const size_t num_of_examples = examples.size ();
480 LabelDataType sum = 0.0f;
481 LabelDataType sqr_sum = 0.0f;
482 for (
size_t example_index = 0; example_index < num_of_examples; ++example_index)
484 const LabelDataType label = label_data[example_index];
487 sqr_sum += label * label;
490 sum /= static_cast<float>(num_of_examples);
491 sqr_sum /= static_cast<float>(num_of_examples);
493 const float variance = sqr_sum - sum * sum;
496 node.variance = variance;
499 std::vector < ExampleIndex > positive_examples;
501 for (
size_t example_index = 0; example_index < num_of_examples; ++example_index)
503 LabelDataType label = label_data[example_index];
506 positive_examples.push_back (examples[example_index]);
521 stream <<
"ERROR: RegressionVarianceStatsEstimator does not implement generateCodeForBranchIndex(...)";
530 stream <<
"ERROR: RegressionVarianceStatsEstimator does not implement generateCodeForBranchIndex(...)";
void setMaxPatchSize(int w)
Create a set of random tests to evaluate examples.
void computeAndSetNodeStats(DataSet &data_set, std::vector< ExampleIndex > &examples, std::vector< LabelDataType > &label_data, NodeType &node) const
Computes and sets the statistics for a node.
virtual size_t getNumOfBranches() const =0
Returns the number of branches the corresponding tree has.
std::vector< boost::shared_ptr< pcl::IntegralImage2D< float, 1 > > > iimages_
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 generateCodeForOutput(NodeType &, std::ostream &stream) const
Generates code for label output.
void generateCodeForEvaluation(const FT &, ::std::ostream &) const
Generates evaluation code for the specified feature and writes it to the specified stream.
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.
void generateCodeForBranchIndexComputation(NodeType &, std::ostream &stream) const
Generates code for branch index computation.
void computeBranchIndices(std::vector< float > &results, std::vector< unsigned char > &flags, const float threshold, std::vector< unsigned char > &branch_indices) const
Computes the branch indices for all supplied results.
size_t getNumOfBranches() const
Returns the number of branches the corresponding tree has.
LabelDataType getLabelOfNode(NodeType &node) const
Returns the label of the specified node.
void setWSize(int w)
Sets the size of the window to extract features.
void computeBranchIndex(const float result, const unsigned char flag, const float threshold, unsigned char &branch_index) const
Computes the branch index for the specified result.
void evaluateFeature(const FT &feature, DataSet &data_set, std::vector< ExampleIndex > &examples, std::vector< float > &results, std::vector< unsigned char > &flags) const
Evaluates a feature on the specified set of examples.
PoseClassRegressionVarianceStatsEstimator(BranchEstimator *branch_estimator)
Constructor.
Class interface for gathering statistics for decision tree learning.
void evaluateFeature(const FT &feature, DataSet &data_set, const ExampleIndex &example, float &result, unsigned char &flag) const
Evaluates a feature on the specified example.
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.
FeatureHandlerDepthAverage()
virtual ~PoseClassRegressionVarianceStatsEstimator()
Destructor.
void setNumChannels(int nf)
Sets the number of channels a feature has (i.e.
void createRandomFeatures(const size_t num_of_features, std::vector< FT > &features)
Create a set of random tests to evaluate examples.
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
Computes the information gain obtained by the specified threshold.
Interface for branch estimators.
Utility class interface which is used for creating and evaluating features.