Point Cloud Library (PCL) 1.15.1-dev
Loading...
Searching...
No Matches
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
47namespace pcl {
48namespace 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 */
62template <typename PointInT,
64class PyramidalKLTTracker : public Tracker<PointInT, Eigen::Affine3f> {
65public:
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
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
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
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. */
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
281protected:
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 */
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
435public:
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
shared_ptr< const PointCloud< float > > ConstPtr
Calculates a transformation based on corresponding 3D points.
Pyramidal Kanade Lucas Tomasi tracker.
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
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
pcl::PointCloud< pcl::PointUV >::ConstPtr getTrackedPoints() const
~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.
void setEpsilon(float epsilon)
Set epsilon.
Eigen::Affine3f motion_
computed transformation between tracked points
typename PointCloudIn::ConstPtr PointCloudInConstPtr
PyramidalKLTTracker(int nb_levels=5, int tracking_window_width=7, int tracking_window_height=7)
Constructor.
typename PointCloudIn::Ptr PointCloudInPtr
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
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
float accuracy_
accuracy criterion to stop iterating
void setTrackingWindowWidth(int width)
Set tracking window width.
FloatImage::ConstPtr FloatImageConstPtr
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::shared_ptr< const std::vector< int > > getStatusOfPointsToTrack() const
pcl::PointCloud< float > FloatImage
void convolveCols(const FloatImageConstPtr &input, FloatImage &output) const
Convolve image columns.
shared_ptr< const PyramidalKLTTracker< PointInT, IntensityT > > ConstPtr
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
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
Defines all the PCL and non-PCL macros used.