Point Cloud Library (PCL)  1.10.0-dev
multi_channel_2d_comparison_feature_handler.h
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Point Cloud Library (PCL) - www.pointclouds.org
5  * Copyright (c) 2010-2011, Willow Garage, Inc.
6  *
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * * Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * * Redistributions in binary form must reproduce the above
16  * copyright notice, this list of conditions and the following
17  * disclaimer in the documentation and/or other materials provided
18  * with the distribution.
19  * * Neither the name of Willow Garage, Inc. nor the names of its
20  * contributors may be used to endorse or promote products derived
21  * from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  *
36  */
37 
38 #pragma once
39 
40 #include <pcl/common/common.h>
41 
42 #include <pcl/ml/feature_handler.h>
43 #include <pcl/ml/multi_channel_2d_comparison_feature.h>
44 #include <pcl/ml/multi_channel_2d_data_set.h>
45 #include <pcl/ml/multiple_data_2d_example_index.h>
46 #include <pcl/ml/point_xy_32f.h>
47 #include <pcl/ml/point_xy_32i.h>
48 
49 #include <istream>
50 #include <ostream>
51 
52 namespace pcl {
53 
54 /** Feature utility class that handles the creation and evaluation of RGBD
55  * comparison features. */
56 template <class DATA_TYPE, std::size_t NUM_OF_CHANNELS>
58 : public pcl::FeatureHandler<pcl::MultiChannel2DComparisonFeature<pcl::PointXY32i>,
59  pcl::MultiChannel2DDataSet<DATA_TYPE, NUM_OF_CHANNELS>,
60  pcl::MultipleData2DExampleIndex> {
61 
62 public:
63  /** Constructor. */
64  MultiChannel2DComparisonFeatureHandler(const int feature_window_width,
65  const int feature_window_height)
66  : feature_window_width_(feature_window_width)
67  , feature_window_height_(feature_window_height)
68  {}
69 
70  /** Destructor. */
72 
73  /** Sets the feature window size.
74  *
75  * \param[in] width the width of the feature window
76  * \param[in] height the height of the feature window
77  */
78  inline void
79  setFeatureWindowSize(int width, int height)
80  {
81  feature_window_width_ = width;
82  feature_window_height_ = height;
83  }
84 
85  /** Creates random features.
86  *
87  * \param[in] num_of_features the number of random features to create
88  * \param[out] features the destination for the created random features
89  */
90  inline void
92  const std::size_t num_of_features,
93  std::vector<MultiChannel2DComparisonFeature<PointXY32i>>& features)
94  {
95  features.resize(num_of_features);
96  for (std::size_t feature_index = 0; feature_index < num_of_features;
97  ++feature_index) {
98  features[feature_index].p1 = PointXY32i::randomPoint(-feature_window_width_ / 2,
99  feature_window_width_ / 2,
100  -feature_window_height_ / 2,
101  feature_window_height_ / 2);
102  features[feature_index].p2 = PointXY32i::randomPoint(-feature_window_width_ / 2,
103  feature_window_width_ / 2,
104  -feature_window_height_ / 2,
105  feature_window_height_ / 2);
106  features[feature_index].channel = static_cast<unsigned char>(
107  NUM_OF_CHANNELS * (static_cast<float>(rand()) / (RAND_MAX + 1)));
108  }
109  }
110 
111  /** Evaluates a feature for a set of examples on the specified data set.
112  *
113  * \param[in] feature the feature to evaluate
114  * \param[in] data_set the data set the feature is evaluated on
115  * \param[in] examples the examples the feature is evaluated for
116  * \param[out] results the destination for the evaluation results
117  * \param[out] flags the destination for the flags corresponding to the evaluation
118  * results
119  */
120  inline void
123  std::vector<MultipleData2DExampleIndex>& examples,
124  std::vector<float>& results,
125  std::vector<unsigned char>& flags) const
126  {
127  results.resize(examples.size());
128  flags.resize(examples.size());
129  for (int example_index = 0; example_index < examples.size(); ++example_index) {
130  const MultipleData2DExampleIndex& example = examples[example_index];
131 
132  evaluateFeature(
133  feature, data_set, example, results[example_index], flags[example_index]);
134  }
135  }
136 
137  /** Evaluates a feature for one examples on the specified data set.
138  *
139  * \param[in] feature the feature to evaluate
140  * \param[in] data_set the data set the feature is evaluated on
141  * \param[in] example the example the feature is evaluated for
142  * \param[out] result the destination for the evaluation result
143  * \param[out] flag the destination for the flag corresponding to the evaluation
144  * result
145  */
146  inline void
149  const MultipleData2DExampleIndex& example,
150  float& result,
151  unsigned char& flag) const
152  {
153  const int center_col_index = example.x;
154  const int center_row_index = example.y;
155 
156  const std::size_t p1_col =
157  static_cast<std::size_t>(feature.p1.x + center_col_index);
158  const std::size_t p1_row =
159  static_cast<std::size_t>(feature.p1.y + center_row_index);
160 
161  const std::size_t p2_col =
162  static_cast<std::size_t>(feature.p2.x + center_col_index);
163  const std::size_t p2_row =
164  static_cast<std::size_t>(feature.p2.y + center_row_index);
165 
166  const unsigned char channel = feature.channel;
167 
168  const float value1 =
169  static_cast<float>(data_set(example.data_set_id, p1_col, p1_row)[channel]);
170  const float value2 =
171  static_cast<float>(data_set(example.data_set_id, p2_col, p2_row)[channel]);
172 
173  result = value1 - value2;
174  flag = (std::isfinite(value1) && std::isfinite(value2)) ? 0 : 1;
175  }
176 
177  /** Generates code for feature evaluation.
178  *
179  * \param[in] feature the feature for which code is generated
180  * \param[out] stream the destination for the generated code
181  */
182  void
184  std::ostream& stream) const
185  {
186  stream << "ERROR: RegressionVarianceStatsEstimator does not implement "
187  "generateCodeForBranchIndex(...)";
188  // stream << "const float value = ( (*dataSet)(dataSetId, centerY+" << feature.p1.y
189  // << ", centerX+" << feature.p1.x << ")[" << static_cast<int>(feature.colorChannel)
190  // << "]"
191  // << " - " << "(*dataSet)(dataSetId, centerY+" << feature.p2.y << ", centerX+" <<
192  // feature.p2.x << ")[" << static_cast<int>(feature.colorChannel) << "] );" <<
193  // ::std::endl;
194  }
195 
196 private:
197  /** The width of the feature window. */
198  int feature_window_width_;
199  /** The height of the feature window. */
200  int feature_window_height_;
201 };
202 
203 /** Feature utility class that handles the creation and evaluation of RGBD
204  * comparison features. */
205 template <class DATA_TYPE,
206  std::size_t NUM_OF_CHANNELS,
207  std::size_t SCALE_CHANNEL,
208  bool INVERT_SCALE>
210 : public pcl::FeatureHandler<pcl::MultiChannel2DComparisonFeature<pcl::PointXY32f>,
211  pcl::MultiChannel2DDataSet<DATA_TYPE, NUM_OF_CHANNELS>,
212  pcl::MultipleData2DExampleIndex> {
213 
214 public:
215  /** Constructor. */
216  ScaledMultiChannel2DComparisonFeatureHandler(const int feature_window_width,
217  const int feature_window_height)
218  : feature_window_width_(feature_window_width)
219  , feature_window_height_(feature_window_height)
220  {}
221 
222  /** Destructor. */
224 
225  /** Sets the feature window size.
226  *
227  * \param[in] width the width of the feature window
228  * \param[in] height the height of the feature window
229  */
230  inline void
231  setFeatureWindowSize(int width, int height)
232  {
233  feature_window_width_ = width;
234  feature_window_height_ = height;
235  }
236 
237  /** Creates random features.
238  *
239  * \param[in] num_of_features the number of random features to create
240  * \param[out] features the destination for the created random features
241  */
242  inline void
244  const std::size_t num_of_features,
245  std::vector<MultiChannel2DComparisonFeature<PointXY32f>>& features)
246  {
247  features.resize(num_of_features);
248  for (std::size_t feature_index = 0; feature_index < num_of_features;
249  ++feature_index) {
250  features[feature_index].p1 = PointXY32f::randomPoint(-feature_window_width_ / 2,
251  feature_window_width_ / 2,
252  -feature_window_height_ / 2,
253  feature_window_height_ / 2);
254  features[feature_index].p2 = PointXY32f::randomPoint(-feature_window_width_ / 2,
255  feature_window_width_ / 2,
256  -feature_window_height_ / 2,
257  feature_window_height_ / 2);
258  features[feature_index].channel = static_cast<unsigned char>(
259  NUM_OF_CHANNELS * (static_cast<float>(rand()) / (RAND_MAX + 1)));
260  }
261  }
262 
263  /** Evaluates a feature for a set of examples on the specified data set.
264  *
265  * \param[in] feature the feature to evaluate
266  * \param[in] data_set the data set the feature is evaluated on
267  * \param[in] examples the examples the feature is evaluated for
268  * \param[out] results the destination for the evaluation results
269  * \param[out] flags the destination for the flags corresponding to the evaluation
270  * results
271  */
272  inline void
275  std::vector<MultipleData2DExampleIndex>& examples,
276  std::vector<float>& results,
277  std::vector<unsigned char>& flags) const
278  {
279  results.resize(examples.size());
280  flags.resize(examples.size());
281  for (int example_index = 0; example_index < examples.size(); ++example_index) {
282  const MultipleData2DExampleIndex& example = examples[example_index];
283 
284  evaluateFeature(
285  feature, data_set, example, results[example_index], flags[example_index]);
286  }
287  }
288 
289  /** Evaluates a feature for one examples on the specified data set.
290  *
291  * \param[in] feature the feature to evaluate
292  * \param[in] data_set the data set the feature is evaluated on
293  * \param[in] example the example the feature is evaluated for
294  * \param[out] result the destination for the evaluation result
295  * \param[out] flag the destination for the flag corresponding to the evaluation
296  * result
297  */
298  inline void
301  const MultipleData2DExampleIndex& example,
302  float& result,
303  unsigned char& flag) const
304  {
305  const int center_col_index = example.x;
306  const int center_row_index = example.y;
307 
308  float scale;
309  if (INVERT_SCALE)
310  scale = 1.0f / static_cast<float>(data_set(example.data_set_id,
311  center_col_index,
312  center_row_index)[SCALE_CHANNEL]);
313  else
314  scale = static_cast<float>(data_set(
315  example.data_set_id, center_col_index, center_row_index)[SCALE_CHANNEL]);
316 
317  const std::size_t p1_col =
318  static_cast<std::size_t>(scale * feature.p1.x + center_col_index);
319  const std::size_t p1_row =
320  static_cast<std::size_t>(scale * feature.p1.y + center_row_index);
321 
322  const std::size_t p2_col =
323  static_cast<std::size_t>(scale * feature.p2.x + center_col_index);
324  const std::size_t p2_row =
325  static_cast<std::size_t>(scale * feature.p2.y + center_row_index);
326 
327  const unsigned char channel = feature.channel;
328 
329  const float value1 =
330  static_cast<float>(data_set(example.data_set_id, p1_col, p1_row)[channel]);
331  const float value2 =
332  static_cast<float>(data_set(example.data_set_id, p2_col, p2_row)[channel]);
333 
334  result = value1 - value2;
335  flag = (std::isfinite(value1) && std::isfinite(value2)) ? 0 : 1;
336  }
337 
338  /** Generates code for feature evaluation.
339  *
340  * \param[in] feature the feature for which code is generated
341  * \param[out] stream the destination for the generated code
342  */
343  void
345  std::ostream& stream) const
346  {
347  stream << "ERROR: ScaledMultiChannel2DComparisonFeatureHandler does not implement "
348  "generateCodeForBranchIndex(...)"
349  << std::endl;
350 
351  // pcl::PointXY32f p1 = feature.p1;
352  // pcl::PointXY32f p2 = feature.p2;
353 
354  // stream << "const float eval_value = data_ptr + " << p1.x << " + " << p1.y << " *
355  // width;
356 
357  // stream << "const float value = ( (*dataSet)(dataSetId, centerY+" << feature.p1.y
358  // << ", centerX+" << feature.p1.x << ")[" << static_cast<int>(feature.colorChannel)
359  // << "]"
360  // << " - " << "(*dataSet)(dataSetId, centerY+" << feature.p2.y << ", centerX+" <<
361  // feature.p2.x << ")[" << static_cast<int>(feature.colorChannel) << "] );" <<
362  // ::std::endl;
363  }
364 
365 private:
366  /** The width of the feature window. */
367  int feature_window_width_;
368  /** The height of the feature window. */
369  int feature_window_height_;
370 };
371 
372 template <class DATA_TYPE,
373  std::size_t NUM_OF_CHANNELS,
374  std::size_t SCALE_CHANNEL,
375  bool INVERT_SCALE>
377 : public pcl::FeatureHandlerCodeGenerator<
378  pcl::MultiChannel2DComparisonFeature<pcl::PointXY32f>,
379  pcl::MultiChannel2DDataSet<DATA_TYPE, NUM_OF_CHANNELS>,
380  pcl::MultipleData2DExampleIndex> {
381 public:
384 
385  void
386  generateEvalFunctionCode(std::ostream& stream) const;
387 
388  void
389  generateEvalCode(const MultiChannel2DComparisonFeature<PointXY32f>& feature,
390  std::ostream& stream) const;
391 };
392 
393 template <class DATA_TYPE,
394  std::size_t NUM_OF_CHANNELS,
395  std::size_t SCALE_CHANNEL,
396  bool INVERT_SCALE>
397 void
399  DATA_TYPE,
400  NUM_OF_CHANNELS,
401  SCALE_CHANNEL,
402  INVERT_SCALE>::generateEvalFunctionCode(std::ostream& stream) const
403 {
404  if (NUM_OF_CHANNELS == 1 && SCALE_CHANNEL == 0 && INVERT_SCALE) {
405  stream << "const float scale = 1.0f / static_cast<float> (*data_ptr);"
406  << std::endl;
407  stream << "" << std::endl;
408  stream << "struct LocalFeatureHandler" << std::endl;
409  stream << "{" << std::endl;
410  stream << " static inline void eval (" << typeid(DATA_TYPE).name()
411  << " * a_ptr, const float a_x1, const float a_y1, const float a_x2, const "
412  "float a_y2, const float a_scale, const int a_width, float & a_result, "
413  "unsigned char & a_flags)"
414  << std::endl;
415  stream << " {" << std::endl;
416  stream << " a_result = *(a_ptr + static_cast<int> (a_scale*a_x1) + "
417  "(static_cast<int> (a_scale*a_y1)*a_width)) - *(a_ptr + static_cast<int> "
418  "(a_scale*a_x2) + (static_cast<int> (a_scale*a_y2)*a_width));"
419  << std::endl;
420  stream << " }" << std::endl;
421  stream << "};" << std::endl;
422  }
423  else {
424  stream << "ERROR: generateEvalFunctionCode not implemented" << std::endl;
425  }
426 }
427 
428 template <class DATA_TYPE,
429  std::size_t NUM_OF_CHANNELS,
430  std::size_t SCALE_CHANNEL,
431  bool INVERT_SCALE>
432 void
434  NUM_OF_CHANNELS,
435  SCALE_CHANNEL,
436  INVERT_SCALE>::
437  generateEvalCode(const MultiChannel2DComparisonFeature<PointXY32f>& feature,
438  std::ostream& stream) const
439 {
440  stream << "LocalFeatureHandler::eval (data_ptr, " << feature.p1.x << ", "
441  << feature.p1.y << ", " << feature.p2.x << ", " << feature.p2.y << ", "
442  << "scale, width, result, flags);" << std::endl;
443 }
444 
451 
458 
461 
462 } // namespace pcl
void evaluateFeature(const MultiChannel2DComparisonFeature< PointXY32f > &feature, MultiChannel2DDataSet< DATA_TYPE, NUM_OF_CHANNELS > &data_set, std::vector< MultipleData2DExampleIndex > &examples, std::vector< float > &results, std::vector< unsigned char > &flags) const
Evaluates a feature for a set of examples on the specified data set.
This file defines compatibility wrappers for low level I/O functions.
Definition: convolution.h:45
ScaledMultiChannel2DComparisonFeatureHandler(const int feature_window_width, const int feature_window_height)
Constructor.
Feature utility class that handles the creation and evaluation of RGBD comparison features...
void generateCodeForEvaluation(const MultiChannel2DComparisonFeature< PointXY32i > &feature, std::ostream &stream) const
Generates code for feature evaluation.
Example index for a set of 2D data blocks.
void createRandomFeatures(const std::size_t num_of_features, std::vector< MultiChannel2DComparisonFeature< PointXY32f >> &features)
Creates random features.
Feature for comparing two sample points in 2D multi-channel data.
void evaluateFeature(const MultiChannel2DComparisonFeature< PointXY32f > &feature, MultiChannel2DDataSet< DATA_TYPE, NUM_OF_CHANNELS > &data_set, const MultipleData2DExampleIndex &example, float &result, unsigned char &flag) const
Evaluates a feature for one examples on the specified data set.
Define standard C methods and C++ classes that are common to all methods.
void createRandomFeatures(const std::size_t num_of_features, std::vector< MultiChannel2DComparisonFeature< PointXY32i >> &features)
Creates random features.
MultiChannel2DComparisonFeatureHandler(const int feature_window_width, const int feature_window_height)
Constructor.
Holds a set of two-dimensional multi-channel data.
unsigned char channel
Specifies which channel is used for comparison.
void setFeatureWindowSize(int width, int height)
Sets the feature window size.
Feature utility class that handles the creation and evaluation of RGBD comparison features...
static PointXY32f randomPoint(const int min_x, const int max_x, const int min_y, const int max_y)
Creates a random point within the specified window.
void evaluateFeature(const MultiChannel2DComparisonFeature< PointXY32i > &feature, MultiChannel2DDataSet< DATA_TYPE, NUM_OF_CHANNELS > &data_set, std::vector< MultipleData2DExampleIndex > &examples, std::vector< float > &results, std::vector< unsigned char > &flags) const
Evaluates a feature for a set of examples on the specified data set.
static PointXY32i randomPoint(const int min_x, const int max_x, const int min_y, const int max_y)
Creates a random point within the specified window.
void setFeatureWindowSize(int width, int height)
Sets the feature window size.
void generateCodeForEvaluation(const MultiChannel2DComparisonFeature< PointXY32f > &feature, std::ostream &stream) const
Generates code for feature evaluation.
void evaluateFeature(const MultiChannel2DComparisonFeature< PointXY32i > &feature, MultiChannel2DDataSet< DATA_TYPE, NUM_OF_CHANNELS > &data_set, const MultipleData2DExampleIndex &example, float &result, unsigned char &flag) const
Evaluates a feature for one examples on the specified data set.
#define PCL_EXPORTS
Definition: pcl_macros.h:253
Utility class interface which is used for creating and evaluating features.