Point Cloud Library (PCL)  1.14.1-dev
brisk_2d.h
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Point Cloud Library (PCL) - www.pointclouds.org
5  * Copyright (C) 2011, The Autonomous Systems Lab (ASL), ETH Zurich,
6  * Stefan Leutenegger, Simon Lynen and Margarita Chli.
7  * Copyright (c) 2012-, Open Perception, Inc.
8  *
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  *
15  * * Redistributions of source code must retain the above copyright
16  * notice, this list of conditions and the following disclaimer.
17  * * Redistributions in binary form must reproduce the above
18  * copyright notice, this list of conditions and the following
19  * disclaimer in the documentation and/or other materials provided
20  * with the distribution.
21  * * Neither the name of the copyright holder(s) nor the names of its
22  * contributors may be used to endorse or promote products derived
23  * from this software without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
28  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
29  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
30  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
31  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  *
38  */
39 
40 #pragma once
41 
42 #include <pcl/common/point_tests.h> // for pcl::isFinite
43 #include <pcl/keypoints/agast_2d.h>
44 
45 
46 namespace pcl
47 {
48  /** \brief Detects BRISK interest points based on the original code and paper
49  * reference by
50  *
51  * \par
52  * Stefan Leutenegger,Margarita Chli and Roland Siegwart,
53  * BRISK: Binary Robust Invariant Scalable Keypoints,
54  * in Proceedings of the IEEE International Conference on Computer Vision (ICCV2011).
55  *
56  * Code example:
57  *
58  * \code
59  * pcl::PointCloud<pcl::PointXYZRGBA> cloud;
60  * pcl::BriskKeypoint2D<pcl::PointXYZRGBA> brisk;
61  * brisk.setThreshold (60);
62  * brisk.setOctaves (4);
63  * brisk.setInputCloud (cloud);
64  *
65  * PointCloud<pcl::PointWithScale> keypoints;
66  * brisk.compute (keypoints);
67  * \endcode
68  *
69  * \author Radu B. Rusu, Stefan Holzer
70  * \ingroup keypoints
71  */
72  template <typename PointInT, typename PointOutT = pcl::PointWithScale, typename IntensityT = pcl::common::IntensityFieldAccessor<PointInT> >
73  class BriskKeypoint2D: public Keypoint<PointInT, PointOutT>
74  {
75  public:
76  using Ptr = shared_ptr<BriskKeypoint2D<PointInT, PointOutT, IntensityT> >;
77  using ConstPtr = shared_ptr<const BriskKeypoint2D<PointInT, PointOutT, IntensityT> >;
78 
82  using PointCloudInConstPtr = typename PointCloudIn::ConstPtr;
83 
88 
89  /** \brief Constructor */
90  BriskKeypoint2D (int octaves = 4, int threshold = 60)
91  : threshold_ (threshold)
92  , octaves_ (octaves)
93  {
94  k_ = 1;
95  name_ = "BriskKeypoint2D";
96  }
97 
98  /** \brief Destructor. */
99  ~BriskKeypoint2D () override = default;
100 
101  /** \brief Sets the threshold for corner detection.
102  * \param[in] threshold the threshold used for corner detection.
103  */
104  inline void
105  setThreshold (const int threshold)
106  {
107  threshold_ = threshold;
108  }
109 
110  /** \brief Get the threshold for corner detection, as set by the user. */
111  inline std::size_t
113  {
114  return (threshold_);
115  }
116 
117  /** \brief Set the number of octaves to use
118  * \param[in] octaves the number of octaves to use
119  */
120  inline void
121  setOctaves (const int octaves)
122  {
123  octaves_ = octaves;
124  }
125 
126  /** \brief Returns the number of octaves used. */
127  inline int
129  {
130  return (octaves_);
131  }
132 
133  /** \brief Specify whether we should do a 2nd pass through the list of keypoints
134  * found, and remove the ones that do not have a valid 3D (x-y-z) position
135  * (i.e., are NaN or Inf).
136  * \param[in] remove set to true whether we want the invalid 3D keypoints removed
137  */
138  inline void
140  {
141  remove_invalid_3D_keypoints_ = remove;
142  }
143 
144  /** \brief Specify whether the keypoints that do not have a valid 3D position are
145  * kept (false) or removed (true).
146  */
147  inline bool
149  {
150  return (remove_invalid_3D_keypoints_);
151  }
152 
153  /////////////////////////////////////////////////////////////////////////
154  inline void
156  float x, float y,
157  PointOutT &pt)
158  {
159  int u = static_cast<int>(x);
160  int v = static_cast<int>(y);
161 
162  pt.x = pt.y = pt.z = 0;
163 
164  const PointInT &p1 = (*cloud)(u, v);
165  const PointInT &p2 = (*cloud)(u+1, v);
166  const PointInT &p3 = (*cloud)(u, v+1);
167  const PointInT &p4 = (*cloud)(u+1, v+1);
168 
169  float fx = x - static_cast<float>(u), fy = y - static_cast<float>(v);
170  float fx1 = 1.0f - fx, fy1 = 1.0f - fy;
171 
172  float w1 = fx1 * fy1, w2 = fx * fy1, w3 = fx1 * fy, w4 = fx * fy;
173  float weight = 0;
174 
175  if (pcl::isFinite (p1))
176  {
177  pt.x += p1.x * w1;
178  pt.y += p1.y * w1;
179  pt.z += p1.z * w1;
180  weight += w1;
181  }
182  if (pcl::isFinite (p2))
183  {
184  pt.x += p2.x * w2;
185  pt.y += p2.y * w2;
186  pt.z += p2.z * w2;
187  weight += w2;
188  }
189  if (pcl::isFinite (p3))
190  {
191  pt.x += p3.x * w3;
192  pt.y += p3.y * w3;
193  pt.z += p3.z * w3;
194  weight += w3;
195  }
196  if (pcl::isFinite (p4))
197  {
198  pt.x += p4.x * w4;
199  pt.y += p4.y * w4;
200  pt.z += p4.z * w4;
201  weight += w4;
202  }
203 
204  if (weight == 0)
205  pt.x = pt.y = pt.z = std::numeric_limits<float>::quiet_NaN ();
206  else
207  {
208  weight = 1.0f / weight;
209  pt.x *= weight; pt.y *= weight; pt.z *= weight;
210  }
211  }
212 
213  protected:
214  /** \brief Initializes everything and checks whether input data is fine. */
215  bool
216  initCompute () override;
217 
218  /** \brief Detects the keypoints. */
219  void
220  detectKeypoints (PointCloudOut &output) override;
221 
222  private:
223  /** \brief Intensity field accessor. */
224  IntensityT intensity_;
225 
226  /** \brief Threshold for corner detection. */
227  int threshold_;
228 
229  int octaves_;
230 
231  /** \brief Specify whether the keypoints that do not have a valid 3D position are
232  * kept (false) or removed (true).
233  */
234  bool remove_invalid_3D_keypoints_{false};
235  };
236 
237  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
238  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
239  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
240  namespace keypoints
241  {
242  namespace brisk
243  {
244  /** \brief A layer in the BRISK detector pyramid. */
246  {
247  public:
248  // constructor arguments
250  {
251  static const int HALFSAMPLE;
252  static const int TWOTHIRDSAMPLE;
253  };
254 
255  /** \brief Constructor.
256  * \param[in] img input image
257  * \param[in] width image width
258  * \param[in] height image height
259  * \param[in] scale scale
260  * \param[in] offset offset
261  */
262  Layer (const std::vector<unsigned char>& img,
263  int width, int height,
264  float scale = 1.0f, float offset = 0.0f);
265 
266  /** \brief Copy constructor for deriving a layer.
267  * \param[in] layer layer to derive from
268  * \param[in] mode deriving mode
269  */
270  Layer (const Layer& layer, int mode);
271 
272  /** \brief AGAST keypoints without non-max suppression.
273  * \param[in] threshold the keypoints threshold
274  * \param[out] keypoints the AGAST keypoints
275  */
276  void
277  getAgastPoints (std::uint8_t threshold, std::vector<pcl::PointUV, Eigen::aligned_allocator<pcl::PointUV> > &keypoints);
278 
279  // get scores - attention, this is in layer coordinates, not scale=1 coordinates!
280  /** \brief Get the AGAST keypoint score for a given pixel using a threshold
281  * \param[in] x the U coordinate of the pixel
282  * \param[in] y the V coordinate of the pixel
283  * \param[in] threshold the threshold to use for cutting the response
284  */
285  std::uint8_t
286  getAgastScore (int x, int y, std::uint8_t threshold);
287  /** \brief Get the AGAST keypoint score for a given pixel using a threshold
288  * \param[in] x the U coordinate of the pixel
289  * \param[in] y the V coordinate of the pixel
290  * \param[in] threshold the threshold to use for cutting the response
291  */
292  std::uint8_t
293  getAgastScore_5_8 (int x, int y, std::uint8_t threshold);
294  /** \brief Get the AGAST keypoint score for a given pixel using a threshold
295  * \param[in] xf the X coordinate of the pixel
296  * \param[in] yf the Y coordinate of the pixel
297  * \param[in] threshold the threshold to use for cutting the response
298  * \param[in] scale the scale
299  */
300  std::uint8_t
301  getAgastScore (float xf, float yf, std::uint8_t threshold, float scale = 1.0f);
302 
303  /** \brief Access gray values (smoothed/interpolated)
304  * \param[in] mat the image
305  * \param[in] width the image width
306  * \param[in] height the image height
307  * \param[in] xf the x coordinate
308  * \param[in] yf the y coordinate
309  * \param[in] scale the scale
310  */
311  std::uint8_t
312  getValue (const std::vector<unsigned char>& mat,
313  int width, int height, float xf, float yf, float scale);
314 
315  /** \brief Get the image used. */
316  const std::vector<unsigned char>&
317  getImage () const
318  {
319  return (img_);
320  }
321 
322  /** \brief Get the width of the image used. */
323  int
324  getImageWidth () const
325  {
326  return (img_width_);
327  }
328 
329  /** \brief Get the height of the image used. */
330  int
331  getImageHeight () const
332  {
333  return (img_height_);
334  }
335 
336  /** \brief Get the scale used. */
337  float
338  getScale () const
339  {
340  return (scale_);
341  }
342 
343  /** \brief Get the offset used. */
344  inline float
345  getOffset () const
346  {
347  return (offset_);
348  }
349 
350  /** \brief Get the scores obtained. */
351  inline const std::vector<unsigned char>&
352  getScores () const
353  {
354  return (scores_);
355  }
356 
357  private:
358  // half sampling
359  inline void
360  halfsample (const std::vector<unsigned char>& srcimg,
361  int srcwidth, int srcheight,
362  std::vector<unsigned char>& dstimg,
363  int dstwidth, int dstheight);
364 
365  // two third sampling
366  inline void
367  twothirdsample (const std::vector<unsigned char>& srcimg,
368  int srcwidth, int srcheight,
369  std::vector<unsigned char>& dstimg,
370  int dstwidth, int dstheight);
371 
372  /** the image */
373  std::vector<unsigned char> img_;
374  int img_width_;
375  int img_height_;
376 
377  /** its Fast scores */
378  std::vector<unsigned char> scores_;
379 
380  /** coordinate transformation */
381  float scale_;
382  float offset_;
383 
384  /** agast */
387  };
388 
389  /** BRISK Scale Space helper. */
391  {
392  public:
393  /** \brief Constructor. Specify the number of octaves.
394  * \param[in] octaves the number of octaves (default: 3)
395  */
396  ScaleSpace (int octaves = 3);
398 
399  /** \brief Construct the image pyramids.
400  * \param[in] image the image to construct pyramids for
401  * \param[in] width the image width
402  * \param[in] height the image height
403  */
404  void
405  constructPyramid (const std::vector<unsigned char>& image,
406  int width, int height);
407 
408  /** \brief Get the keypoints for the associated image and threshold.
409  * \param[in] threshold the threshold for the keypoints
410  * \param[out] keypoints the resultant list of keypoints
411  */
412  void
413  getKeypoints (const int threshold,
414  std::vector<pcl::PointWithScale, Eigen::aligned_allocator<pcl::PointWithScale> > &keypoints);
415 
416  protected:
417  /** Nonmax suppression. */
418  inline bool
419  isMax2D (const std::uint8_t layer, const int x_layer, const int y_layer);
420 
421  /** 1D (scale axis) refinement: around octave */
422  inline float
423  refine1D (const float s_05, const float s0, const float s05, float& max);
424 
425  /** 1D (scale axis) refinement: around intra */
426  inline float
427  refine1D_1 (const float s_05, const float s0, const float s05, float& max);
428 
429  /** 1D (scale axis) refinement: around octave 0 only */
430  inline float
431  refine1D_2 (const float s_05, const float s0, const float s05, float& max);
432 
433  /** 2D maximum refinement */
434  inline float
435  subpixel2D (const int s_0_0, const int s_0_1, const int s_0_2,
436  const int s_1_0, const int s_1_1, const int s_1_2,
437  const int s_2_0, const int s_2_1, const int s_2_2,
438  float& delta_x, float& delta_y);
439 
440  /** 3D maximum refinement centered around (x_layer,y_layer) */
441  inline float
442  refine3D (const std::uint8_t layer,
443  const int x_layer, const int y_layer,
444  float& x, float& y, float& scale, bool& ismax);
445 
446  /** interpolated score access with recalculation when needed */
447  inline int
448  getScoreAbove (const std::uint8_t layer, const int x_layer, const int y_layer);
449 
450  inline int
451  getScoreBelow (const std::uint8_t layer, const int x_layer, const int y_layer);
452 
453  /** return the maximum of score patches above or below */
454  inline float
455  getScoreMaxAbove (const std::uint8_t layer,
456  const int x_layer, const int y_layer,
457  const int threshold, bool& ismax,
458  float& dx, float& dy);
459 
460  inline float
461  getScoreMaxBelow (const std::uint8_t layer,
462  const int x_layer, const int y_layer,
463  const int threshold, bool& ismax,
464  float& dx, float& dy);
465 
466  // the image pyramids
467  std::uint8_t layers_;
468  std::vector<pcl::keypoints::brisk::Layer> pyramid_;
469 
470  // Agast
471  std::uint8_t threshold_;
472  std::uint8_t safe_threshold_;
473 
474  // some constant parameters
475  float safety_factor_{1.0};
476  float basic_size_{12.0};
477  };
478  } // namespace brisk
479  } // namespace keypoints
480 
481 }
482 
483 #include <pcl/keypoints/impl/brisk_2d.hpp>
Detects BRISK interest points based on the original code and paper reference by.
Definition: brisk_2d.h:74
~BriskKeypoint2D() override=default
Destructor.
void setThreshold(const int threshold)
Sets the threshold for corner detection.
Definition: brisk_2d.h:105
void detectKeypoints(PointCloudOut &output) override
Detects the keypoints.
Definition: brisk_2d.hpp:69
typename Keypoint< PointInT, PointOutT >::PointCloudIn PointCloudIn
Definition: brisk_2d.h:79
typename Keypoint< PointInT, PointOutT >::PointCloudOut PointCloudOut
Definition: brisk_2d.h:80
shared_ptr< const BriskKeypoint2D< PointInT, PointOutT, IntensityT > > ConstPtr
Definition: brisk_2d.h:77
typename Keypoint< PointInT, PointOutT >::KdTree KdTree
Definition: brisk_2d.h:81
bool getRemoveInvalid3DKeypoints()
Specify whether the keypoints that do not have a valid 3D position are kept (false) or removed (true)...
Definition: brisk_2d.h:148
std::size_t getThreshold()
Get the threshold for corner detection, as set by the user.
Definition: brisk_2d.h:112
BriskKeypoint2D(int octaves=4, int threshold=60)
Constructor.
Definition: brisk_2d.h:90
void setOctaves(const int octaves)
Set the number of octaves to use.
Definition: brisk_2d.h:121
int getOctaves()
Returns the number of octaves used.
Definition: brisk_2d.h:128
void bilinearInterpolation(const PointCloudInConstPtr &cloud, float x, float y, PointOutT &pt)
Definition: brisk_2d.h:155
shared_ptr< BriskKeypoint2D< PointInT, PointOutT, IntensityT > > Ptr
Definition: brisk_2d.h:76
bool initCompute() override
Initializes everything and checks whether input data is fine.
Definition: brisk_2d.hpp:50
typename PointCloudIn::ConstPtr PointCloudInConstPtr
Definition: brisk_2d.h:82
void setRemoveInvalid3DKeypoints(bool remove)
Specify whether we should do a 2nd pass through the list of keypoints found, and remove the ones that...
Definition: brisk_2d.h:139
Keypoint represents the base class for key points.
Definition: keypoint.h:49
int k_
The number of K nearest neighbors to use for each point.
Definition: keypoint.h:188
std::string name_
The key point detection method's name.
Definition: keypoint.h:167
shared_ptr< AgastDetector5_8 > Ptr
Definition: agast_2d.h:340
shared_ptr< OastDetector9_16 > Ptr
Definition: agast_2d.h:411
A layer in the BRISK detector pyramid.
Definition: brisk_2d.h:246
Layer(const Layer &layer, int mode)
Copy constructor for deriving a layer.
float getOffset() const
Get the offset used.
Definition: brisk_2d.h:345
std::uint8_t getAgastScore(int x, int y, std::uint8_t threshold)
Get the AGAST keypoint score for a given pixel using a threshold.
const std::vector< unsigned char > & getImage() const
Get the image used.
Definition: brisk_2d.h:317
const std::vector< unsigned char > & getScores() const
Get the scores obtained.
Definition: brisk_2d.h:352
std::uint8_t getAgastScore_5_8(int x, int y, std::uint8_t threshold)
Get the AGAST keypoint score for a given pixel using a threshold.
int getImageWidth() const
Get the width of the image used.
Definition: brisk_2d.h:324
int getImageHeight() const
Get the height of the image used.
Definition: brisk_2d.h:331
float getScale() const
Get the scale used.
Definition: brisk_2d.h:338
Layer(const std::vector< unsigned char > &img, int width, int height, float scale=1.0f, float offset=0.0f)
Constructor.
std::uint8_t getAgastScore(float xf, float yf, std::uint8_t threshold, float scale=1.0f)
Get the AGAST keypoint score for a given pixel using a threshold.
std::uint8_t getValue(const std::vector< unsigned char > &mat, int width, int height, float xf, float yf, float scale)
Access gray values (smoothed/interpolated)
void getAgastPoints(std::uint8_t threshold, std::vector< pcl::PointUV, Eigen::aligned_allocator< pcl::PointUV > > &keypoints)
AGAST keypoints without non-max suppression.
BRISK Scale Space helper.
Definition: brisk_2d.h:391
float refine1D_1(const float s_05, const float s0, const float s05, float &max)
1D (scale axis) refinement: around intra
float getScoreMaxAbove(const std::uint8_t layer, const int x_layer, const int y_layer, const int threshold, bool &ismax, float &dx, float &dy)
return the maximum of score patches above or below
int getScoreAbove(const std::uint8_t layer, const int x_layer, const int y_layer)
interpolated score access with recalculation when needed
float subpixel2D(const int s_0_0, const int s_0_1, const int s_0_2, const int s_1_0, const int s_1_1, const int s_1_2, const int s_2_0, const int s_2_1, const int s_2_2, float &delta_x, float &delta_y)
2D maximum refinement
float refine1D_2(const float s_05, const float s0, const float s05, float &max)
1D (scale axis) refinement: around octave 0 only
float getScoreMaxBelow(const std::uint8_t layer, const int x_layer, const int y_layer, const int threshold, bool &ismax, float &dx, float &dy)
ScaleSpace(int octaves=3)
Constructor.
int getScoreBelow(const std::uint8_t layer, const int x_layer, const int y_layer)
void constructPyramid(const std::vector< unsigned char > &image, int width, int height)
Construct the image pyramids.
float refine3D(const std::uint8_t layer, const int x_layer, const int y_layer, float &x, float &y, float &scale, bool &ismax)
3D maximum refinement centered around (x_layer,y_layer)
float refine1D(const float s_05, const float s0, const float s05, float &max)
1D (scale axis) refinement: around octave
std::vector< pcl::keypoints::brisk::Layer > pyramid_
Definition: brisk_2d.h:468
bool isMax2D(const std::uint8_t layer, const int x_layer, const int y_layer)
Nonmax suppression.
void getKeypoints(const int threshold, std::vector< pcl::PointWithScale, Eigen::aligned_allocator< pcl::PointWithScale > > &keypoints)
Get the keypoints for the associated image and threshold.
bool isFinite(const PointT &pt)
Tests if the 3D components of a point are all finite param[in] pt point to be tested return true if f...
Definition: point_tests.h:55
#define PCL_EXPORTS
Definition: pcl_macros.h:323
A 2D point structure representing pixel image coordinates.
A point structure representing a 3-D position and scale.