Point Cloud Library (PCL)  1.15.1-dev
pyramidal_klt.h
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Point Cloud Library (PCL) - www.pointclouds.org
5  * Copyright (c) 2014-, Open Perception.
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/intensity.h>
41 #include <pcl/common/transformation_from_correspondences.h>
42 #include <pcl/tracking/tracker.h>
43 #include <pcl/memory.h>
44 #include <pcl/pcl_macros.h>
45 #include <pcl/point_types.h>
46 
47 namespace pcl {
48 namespace tracking {
49 /** Pyramidal Kanade Lucas Tomasi tracker.
50  * This is an implementation of the Pyramidal Kanade Lucas Tomasi tracker that
51  * operates on organized 3D keypoints with color/intensity information (this is
52  * the default behaviour but you can alternate it by providing another operator
53  * as second template argument). It is an affine tracker that iteratively
54  * computes the optical flow to find the best guess for a point p at t given its
55  * location at t-1. User is advised to respect the Tomasi condition: the
56  * response computed is the maximum eigenvalue of the second moment matrix but
57  * no restrictin are applied to points to track so you can use a detector of
58  * your choice to indicate points to track.
59  *
60  * \author Nizar Sallem
61  */
62 template <typename PointInT,
64 class PyramidalKLTTracker : public Tracker<PointInT, Eigen::Affine3f> {
65 public:
68  using PointCloudInPtr = typename PointCloudIn::Ptr;
69  using PointCloudInConstPtr = typename PointCloudIn::ConstPtr;
73  using Ptr = shared_ptr<PyramidalKLTTracker<PointInT, IntensityT>>;
74  using ConstPtr = shared_ptr<const PyramidalKLTTracker<PointInT, IntensityT>>;
75 
77  using TrackerBase::input_;
79 
80  /** Constructor */
81  PyramidalKLTTracker(int nb_levels = 5,
82  int tracking_window_width = 7,
83  int tracking_window_height = 7)
84  : ref_()
85  , nb_levels_(nb_levels)
86  , track_width_(tracking_window_width)
87  , track_height_(tracking_window_height)
88  {
89  tracker_name_ = "PyramidalKLTTracker";
90  accuracy_ = 0.1;
91  epsilon_ = 1e-3;
92  max_iterations_ = 10;
93  keypoints_nbr_ = 100;
95  kernel_ << 1.f / 16, 1.f / 4, 3.f / 8, 1.f / 4, 1.f / 16;
96  kernel_size_2_ = kernel_.size() / 2;
97  kernel_last_ = kernel_.size() - 1;
98  }
99 
100  /** Destructor */
101  ~PyramidalKLTTracker() override = default;
102 
103  /** \brief Set the number of pyramid levels
104  * \param levels desired number of pyramid levels
105  */
106  inline void
108  {
109  nb_levels_ = levels;
110  }
111 
112  /** \return the number of pyramid levels */
113  inline int
115  {
116  return (nb_levels_);
117  }
118 
119  /** Set accuracy
120  * \param[in] accuracy desired accuracy.
121  */
122  inline void
123  setAccuracy(float accuracy)
124  {
125  accuracy_ = accuracy;
126  }
127 
128  /** \return the accuracy */
129  inline float
130  getAccuracy() const
131  {
132  return (accuracy_);
133  }
134 
135  /** Set epsilon
136  * \param[in] epsilon desired epsilon.
137  */
138  inline void
139  setEpsilon(float epsilon)
140  {
141  epsilon_ = epsilon;
142  }
143 
144  /** \return the epsilon */
145  inline float
146  getEpsilon() const
147  {
148  return (epsilon_);
149  }
150 
151  /** \brief Set the maximum number of points to track after sorting detected keypoints
152  * according to their response measure.
153  * \param[in] number the desired number of points to detect.
154  */
155  inline void
156  setNumberOfKeypoints(std::size_t number)
157  {
158  keypoints_nbr_ = number;
159  }
160 
161  /** \return the maximum number of keypoints to keep */
162  inline std::size_t
164  {
165  return (keypoints_nbr_);
166  }
167 
168  /** \brief set the tracking window size
169  * \param[in] width the tracking window width
170  * \param[in] height the tracking window height
171  */
172  inline void
173  setTrackingWindowSize(int width, int height);
174 
175  /** \brief Set tracking window width */
176  inline void
178  {
179  track_width_ = width;
180  };
181 
182  /** \return the tracking window size */
183  inline int
185  {
186  return (track_width_);
187  }
188 
189  /** \brief Set tracking window height */
190  inline void
192  {
193  track_height_ = height;
194  };
195 
196  /** \return the tracking window size */
197  inline int
199  {
200  return (track_height_);
201  }
202 
203  /** \brief Initialize the scheduler and set the number of threads to use.
204  * \param nr_threads the number of hardware threads to use (0 sets the value
205  * back to automatic).
206  */
207  inline void
208  setNumberOfThreads(unsigned int nr_threads = 0)
209  {
210  threads_ = nr_threads;
211  }
212 
213  /** \brief Get a pointer of the cloud at t-1. */
214  inline PointCloudInConstPtr
216  {
217  return (ref_);
218  }
219 
220  /** \brief Set the maximum number of iterations in the Lucas Kanade loop.
221  * \param[in] max the desired maximum number of iterations
222  */
223  inline void
224  setMaxIterationsNumber(unsigned int max)
225  {
226  max_iterations_ = max;
227  }
228 
229  /** \return the maximum iterations number */
230  inline unsigned int
232  {
233  return (max_iterations_);
234  }
235 
236  /** \brief Provide a pointer to points to track.
237  * \param points the const boost shared pointer to a PointIndices message
238  */
239  inline void
241 
242  /** \brief Provide a pointer to points to track.
243  * \param points the const boost shared pointer to a PointIndices message
244  */
245  inline void
247 
248  /** \return a pointer to the points successfully tracked. */
251  {
252  return (keypoints_);
253  };
254 
255  /** \return the status of points to track.
256  * Status == 0 --> points successfully tracked;
257  * Status < 0 --> point is lost;
258  * Status == -1 --> point is out of bond;
259  * Status == -2 --> optical flow can not be computed for this point.
260  */
261  inline pcl::shared_ptr<const std::vector<int>>
263  {
264  return (keypoints_status_);
265  }
266 
267  /** \brief Return the computed transformation from tracked points. */
268  Eigen::Affine3f
269  getResult() const override
270  {
271  return (motion_);
272  }
273 
274  /** \return initialization state */
275  bool
277  {
278  return (initialized_);
279  }
280 
281 protected:
282  bool
283  initCompute() override;
284 
285  /** \brief compute Scharr derivatives of a source cloud.
286  * \param[in] src the image for which gradients are to be computed
287  * \param[out] grad_x image gradient along X direction
288  * \param[out] grad_y image gradient along Y direction
289  */
290  void
291  derivatives(const FloatImage& src, FloatImage& grad_x, FloatImage& grad_y) const;
292 
293  /** \brief downsample input
294  * \param[in] input the image to downsample
295  * \param[out] output the downsampled image
296  */
297  void
298  downsample(const FloatImageConstPtr& input, FloatImageConstPtr& output) const;
299 
300  /** \brief downsample input and compute output gradients.
301  * \param[in] input the image to downsample
302  * \param[out] output the downsampled image
303  * \param[out] output_grad_x downsampled image gradient along X direction
304  * \param[out] output_grad_y downsampled image gradient along Y direction
305  */
306  void
307  downsample(const FloatImageConstPtr& input,
308  FloatImageConstPtr& output,
309  FloatImageConstPtr& output_grad_x,
310  FloatImageConstPtr& output_grad_y) const;
311 
312  /** \brief Separately convolve image with decomposable convolution kernel.
313  * \param[in] input input the image to convolve
314  * \param[out] output output the convolved image
315  */
316  void
317  convolve(const FloatImageConstPtr& input, FloatImage& output) const;
318 
319  /** \brief Convolve image columns.
320  * \param[in] input input the image to convolve
321  * \param[out] output output the convolved image
322  */
323  void
324  convolveCols(const FloatImageConstPtr& input, FloatImage& output) const;
325 
326  /** \brief Convolve image rows.
327  * \param[in] input input the image to convolve
328  * \param[out] output output the convolved image
329  */
330  void
331  convolveRows(const FloatImageConstPtr& input, FloatImage& output) const;
332 
333  /** \brief extract the patch from the previous image, previous image gradients
334  * surrounding pixel allocation while interpolating image and gradients data
335  * and compute covariation matrix of derivatives.
336  * \param[in] img original image
337  * \param[in] grad_x original image gradient along X direction
338  * \param[in] grad_y original image gradient along Y direction
339  * \param[in] location pixel at the center of the patch
340  * \param[in] weights bilinear interpolation weights at this location computed from
341  * subpixel location
342  * \param[out] win patch with interpolated intensity values
343  * \param[out] grad_x_win patch with interpolated gradient along X values
344  * \param[out] grad_y_win patch with interpolated gradient along Y values
345  * \param[out] covariance covariance matrix coefficients
346  */
347  virtual void
348  spatialGradient(const FloatImage& img,
349  const FloatImage& grad_x,
350  const FloatImage& grad_y,
351  const Eigen::Array2i& location,
352  const Eigen::Array4f& weights,
353  Eigen::ArrayXXf& win,
354  Eigen::ArrayXXf& grad_x_win,
355  Eigen::ArrayXXf& grad_y_win,
356  Eigen::Array3f& covariance) const;
357  void
358  mismatchVector(const Eigen::ArrayXXf& prev,
359  const Eigen::ArrayXXf& prev_grad_x,
360  const Eigen::ArrayXXf& prev_grad_y,
361  const FloatImage& next,
362  const Eigen::Array2i& location,
363  const Eigen::Array4f& weights,
364  Eigen::Array2f& b) const;
365 
366  /** \brief Compute the pyramidal representation of an image.
367  * \param[in] input the input cloud
368  * \param[out] pyramid computed pyramid levels along with their respective
369  * gradients
370  * \param[in] border_type
371  */
372  virtual void
374  std::vector<FloatImageConstPtr>& pyramid,
375  pcl::InterpolationType border_type) const;
376 
377  virtual void
378  track(const PointCloudInConstPtr& previous_input,
379  const PointCloudInConstPtr& current_input,
380  const std::vector<FloatImageConstPtr>& previous_pyramid,
381  const std::vector<FloatImageConstPtr>& current_pyramid,
382  const pcl::PointCloud<pcl::PointUV>::ConstPtr& previous_keypoints,
383  pcl::PointCloud<pcl::PointUV>::Ptr& current_keypoints,
384  std::vector<int>& status,
385  Eigen::Affine3f& motion) const;
386 
387  void
388  computeTracking() override;
389 
390  /** \brief input pyranid at t-1 */
391  std::vector<FloatImageConstPtr> ref_pyramid_;
392  /** \brief point cloud at t-1 */
394  /** \brief number of pyramid levels */
396  /** \brief detected keypoints 2D coordinates */
398  /** \brief status of keypoints of t-1 at t */
399  pcl::shared_ptr<std::vector<int>> keypoints_status_;
400  /** \brief number of points to detect */
401  std::size_t keypoints_nbr_;
402  /** \brief tracking width */
404  /** \brief half of tracking window width */
406  /** \brief tracking height */
408  /** \brief half of tracking window height */
410  /** \brief maximum number of iterations */
411  unsigned int max_iterations_;
412  /** \brief accuracy criterion to stop iterating */
413  float accuracy_;
415  /** \brief epsilon for subpixel computation */
416  float epsilon_;
418  /** \brief number of hardware threads */
419  unsigned int threads_{0};
420  /** \brief intensity accessor */
421  IntensityT intensity_;
422  /** \brief is the tracker initialized ? */
423  bool initialized_{false};
424  /** \brief compute transformation from successfully tracked points */
426  /** \brief computed transformation between tracked points */
427  Eigen::Affine3f motion_;
428  /** \brief smoothing kernel */
429  Eigen::Array<float, 5, 1> kernel_;
430  /** \brief smoothing kernel half size */
432  /** \brief index of last element in kernel */
434 
435 public:
437 };
438 } // namespace tracking
439 } // namespace pcl
440 
441 #include <pcl/tracking/impl/pyramidal_klt.hpp>
PointCloudConstPtr input_
The input point cloud dataset.
Definition: pcl_base.h:147
IndicesPtr indices_
A pointer to the vector of point indices to use.
Definition: pcl_base.h:150
shared_ptr< PointCloud< float > > Ptr
Definition: point_cloud.h:414
shared_ptr< const PointCloud< float > > ConstPtr
Definition: point_cloud.h:415
Calculates a transformation based on corresponding 3D points.
Pyramidal Kanade Lucas Tomasi tracker.
Definition: pyramidal_klt.h:64
pcl::shared_ptr< std::vector< int > > keypoints_status_
status of keypoints of t-1 at t
void setMaxIterationsNumber(unsigned int max)
Set the maximum number of iterations in the Lucas Kanade loop.
unsigned int getMaxIterationsNumber() const
pcl::shared_ptr< const std::vector< int > > getStatusOfPointsToTrack() const
void mismatchVector(const Eigen::ArrayXXf &prev, const Eigen::ArrayXXf &prev_grad_x, const Eigen::ArrayXXf &prev_grad_y, const FloatImage &next, const Eigen::Array2i &location, const Eigen::Array4f &weights, Eigen::Array2f &b) const
int kernel_last_
index of last element in kernel
void derivatives(const FloatImage &src, FloatImage &grad_x, FloatImage &grad_y) const
compute Scharr derivatives of a source cloud.
void setNumberOfPyramidLevels(int levels)
Set the number of pyramid levels.
std::size_t keypoints_nbr_
number of points to detect
int track_width_2_
half of tracking window width
int track_height_2_
half of tracking window height
Eigen::Affine3f getResult() const override
Return the computed transformation from tracked points.
int kernel_size_2_
smoothing kernel half size
int nb_levels_
number of pyramid levels
~PyramidalKLTTracker() override=default
Destructor.
bool initCompute() override
This method should get called before starting the actual computation.
std::vector< FloatImageConstPtr > ref_pyramid_
input pyranid at t-1
void setNumberOfThreads(unsigned int nr_threads=0)
Initialize the scheduler and set the number of threads to use.
void setAccuracy(float accuracy)
Set accuracy.
pcl::PointCloud< pcl::PointUV >::ConstPtr getTrackedPoints() const
void setEpsilon(float epsilon)
Set epsilon.
Eigen::Affine3f motion_
computed transformation between tracked points
typename PointCloudIn::ConstPtr PointCloudInConstPtr
Definition: pyramidal_klt.h:69
PyramidalKLTTracker(int nb_levels=5, int tracking_window_width=7, int tracking_window_height=7)
Constructor.
Definition: pyramidal_klt.h:81
typename PointCloudIn::Ptr PointCloudInPtr
Definition: pyramidal_klt.h:68
float epsilon_
epsilon for subpixel computation
IntensityT intensity_
intensity accessor
void setPointsToTrack(const pcl::PointIndicesConstPtr &points)
Provide a pointer to points to track.
bool initialized_
is the tracker initialized ?
void computeTracking() override
Abstract tracking method.
void setTrackingWindowSize(int width, int height)
set the tracking window size
virtual void computePyramids(const PointCloudInConstPtr &input, std::vector< FloatImageConstPtr > &pyramid, pcl::InterpolationType border_type) const
Compute the pyramidal representation of an image.
shared_ptr< PyramidalKLTTracker< PointInT, IntensityT > > Ptr
Definition: pyramidal_klt.h:73
void downsample(const FloatImageConstPtr &input, FloatImageConstPtr &output) const
downsample input
void setTrackingWindowHeight(int height)
Set tracking window height.
virtual void track(const PointCloudInConstPtr &previous_input, const PointCloudInConstPtr &current_input, const std::vector< FloatImageConstPtr > &previous_pyramid, const std::vector< FloatImageConstPtr > &current_pyramid, const pcl::PointCloud< pcl::PointUV >::ConstPtr &previous_keypoints, pcl::PointCloud< pcl::PointUV >::Ptr &current_keypoints, std::vector< int > &status, Eigen::Affine3f &motion) const
virtual void spatialGradient(const FloatImage &img, const FloatImage &grad_x, const FloatImage &grad_y, const Eigen::Array2i &location, const Eigen::Array4f &weights, Eigen::ArrayXXf &win, Eigen::ArrayXXf &grad_x_win, Eigen::ArrayXXf &grad_y_win, Eigen::Array3f &covariance) const
extract the patch from the previous image, previous image gradients surrounding pixel allocation whil...
Eigen::Array< float, 5, 1 > kernel_
smoothing kernel
unsigned int max_iterations_
maximum number of iterations
typename TrackerBase::PointCloudIn PointCloudIn
Definition: pyramidal_klt.h:67
float accuracy_
accuracy criterion to stop iterating
void setTrackingWindowWidth(int width)
Set tracking window width.
FloatImage::ConstPtr FloatImageConstPtr
Definition: pyramidal_klt.h:72
unsigned int threads_
number of hardware threads
PointCloudInConstPtr getReferenceCloud() const
Get a pointer of the cloud at t-1.
void convolveRows(const FloatImageConstPtr &input, FloatImage &output) const
Convolve image rows.
pcl::TransformationFromCorrespondences transformation_computer_
compute transformation from successfully tracked points
void setNumberOfKeypoints(std::size_t number)
Set the maximum number of points to track after sorting detected keypoints according to their respons...
pcl::PointCloud< float > FloatImage
Definition: pyramidal_klt.h:70
void convolveCols(const FloatImageConstPtr &input, FloatImage &output) const
Convolve image columns.
shared_ptr< const PyramidalKLTTracker< PointInT, IntensityT > > ConstPtr
Definition: pyramidal_klt.h:74
void convolve(const FloatImageConstPtr &input, FloatImage &output) const
Separately convolve image with decomposable convolution kernel.
PointCloudInConstPtr ref_
point cloud at t-1
pcl::PointCloud< pcl::PointUV >::ConstPtr keypoints_
detected keypoints 2D coordinates
Tracker represents the base tracker class.
Definition: tracker.h:55
std::string tracker_name_
The tracker name.
Definition: tracker.h:90
pcl::PointCloud< PointInT > PointCloudIn
Definition: tracker.h:70
Defines all the PCL implemented PointT point type structures.
#define PCL_MAKE_ALIGNED_OPERATOR_NEW
Macro to signal a class requires a custom allocator.
Definition: memory.h:86
Defines functions, macros and traits for allocating and using memory.
InterpolationType
Definition: io.h:278
PointIndices::ConstPtr PointIndicesConstPtr
Definition: PointIndices.h:24
Defines all the PCL and non-PCL macros used.