Point Cloud Library (PCL) 1.15.1-dev
Loading...
Searching...
No Matches
harris_2d.hpp
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 * $Id$
37 *
38 */
39
40
41#ifndef PCL_HARRIS_KEYPOINT_2D_IMPL_H_
42#define PCL_HARRIS_KEYPOINT_2D_IMPL_H_
43
44#include <pcl/common/point_tests.h>
45
46#include <cmath>
47
48namespace pcl
49{
50
51template <typename PointInT, typename PointOutT, typename IntensityT> void
56
57
58template <typename PointInT, typename PointOutT, typename IntensityT> void
60{
61 threshold_= threshold;
62}
63
64
65template <typename PointInT, typename PointOutT, typename IntensityT> void
67{
68 refine_ = do_refine;
69}
70
71
72template <typename PointInT, typename PointOutT, typename IntensityT> void
77
78
79template <typename PointInT, typename PointOutT, typename IntensityT> void
81{
82 window_width_= window_width;
83}
84
85
86template <typename PointInT, typename PointOutT, typename IntensityT> void
88{
89 window_height_= window_height;
90}
91
92
93template <typename PointInT, typename PointOutT, typename IntensityT> void
95{
96 skipped_pixels_= skipped_pixels;
97}
98
99
100template <typename PointInT, typename PointOutT, typename IntensityT> void
102{
103 min_distance_ = min_distance;
104}
105
106
107template <typename PointInT, typename PointOutT, typename IntensityT> void
109{
110 static const int width = static_cast<int> (input_->width);
111 static const int height = static_cast<int> (input_->height);
112
113 int x = static_cast<int> (index % input_->width);
114 int y = static_cast<int> (index / input_->width);
115 // indices 0 1 2
116 // coefficients: ixix ixiy iyiy
117 std::fill_n(coefficients, 3, 0);
118
119 int endx = std::min (width, x + half_window_width_);
120 int endy = std::min (height, y + half_window_height_);
121 for (int xx = std::max (0, x - half_window_width_); xx < endx; ++xx)
122 for (int yy = std::max (0, y - half_window_height_); yy < endy; ++yy)
123 {
124 const float& ix = derivatives_rows_ (xx,yy);
125 const float& iy = derivatives_cols_ (xx,yy);
126 coefficients[0]+= ix * ix;
127 coefficients[1]+= ix * iy;
128 coefficients[2]+= iy * iy;
129 }
130}
131
132
133template <typename PointInT, typename PointOutT, typename IntensityT> bool
135{
137 {
138 PCL_ERROR ("[pcl::%s::initCompute] init failed.!\n", name_.c_str ());
139 return (false);
140 }
141
142 if (!input_->isOrganized ())
143 {
144 PCL_ERROR ("[pcl::%s::initCompute] %s doesn't support non organized clouds!\n", name_.c_str ());
145 return (false);
146 }
147
148 if (indices_->size () != input_->size ())
149 {
150 PCL_ERROR ("[pcl::%s::initCompute] %s doesn't support setting indices!\n", name_.c_str ());
151 return (false);
152 }
153
154 if ((window_height_%2) == 0)
155 {
156 PCL_ERROR ("[pcl::%s::initCompute] Window height must be odd!\n", name_.c_str ());
157 return (false);
158 }
159
160 if ((window_width_%2) == 0)
161 {
162 PCL_ERROR ("[pcl::%s::initCompute] Window width must be odd!\n", name_.c_str ());
163 return (false);
164 }
165
166 if (window_height_ < 3 || window_width_ < 3)
167 {
168 PCL_ERROR ("[pcl::%s::initCompute] Window size must be >= 3x3!\n", name_.c_str ());
169 return (false);
170 }
171
172 half_window_width_ = window_width_ / 2;
173 half_window_height_ = window_height_ / 2;
174
175 return (true);
176}
177
178
179template <typename PointInT, typename PointOutT, typename IntensityT> void
181{
182 derivatives_cols_.resize (input_->width, input_->height);
183 derivatives_rows_.resize (input_->width, input_->height);
184 //Compute cloud intensities first derivatives along columns and rows
185 //!!! nsallem 20120220 : we don't test here for density so if one term is nan the result is nan
186 int w = static_cast<int> (input_->width) - 1;
187 int h = static_cast<int> (input_->height) - 1;
188 // j = 0 --> j-1 out of range ; use 0
189 // i = 0 --> i-1 out of range ; use 0
190 derivatives_cols_(0,0) = (intensity_ ((*input_) (0,1)) - intensity_ ((*input_) (0,0))) * 0.5;
191 derivatives_rows_(0,0) = (intensity_ ((*input_) (1,0)) - intensity_ ((*input_) (0,0))) * 0.5;
192
193 for(int i = 1; i < w; ++i)
194 {
195 derivatives_cols_(i,0) = (intensity_ ((*input_) (i,1)) - intensity_ ((*input_) (i,0))) * 0.5;
196 }
197
198 derivatives_rows_(w,0) = (intensity_ ((*input_) (w,0)) - intensity_ ((*input_) (w-1,0))) * 0.5;
199 derivatives_cols_(w,0) = (intensity_ ((*input_) (w,1)) - intensity_ ((*input_) (w,0))) * 0.5;
200
201 for(int j = 1; j < h; ++j)
202 {
203 // i = 0 --> i-1 out of range ; use 0
204 derivatives_rows_(0,j) = (intensity_ ((*input_) (1,j)) - intensity_ ((*input_) (0,j))) * 0.5;
205 for(int i = 1; i < w; ++i)
206 {
207 // derivative with respect to rows
208 derivatives_rows_(i,j) = (intensity_ ((*input_) (i+1,j)) - intensity_ ((*input_) (i-1,j))) * 0.5;
209
210 // derivative with respect to cols
211 derivatives_cols_(i,j) = (intensity_ ((*input_) (i,j+1)) - intensity_ ((*input_) (i,j-1))) * 0.5;
212 }
213 // i = w --> w+1 out of range ; use w
214 derivatives_rows_(w,j) = (intensity_ ((*input_) (w,j)) - intensity_ ((*input_) (w-1,j))) * 0.5;
215 }
216
217 // j = h --> j+1 out of range use h
218 derivatives_cols_(0,h) = (intensity_ ((*input_) (0,h)) - intensity_ ((*input_) (0,h-1))) * 0.5;
219 derivatives_rows_(0,h) = (intensity_ ((*input_) (1,h)) - intensity_ ((*input_) (0,h))) * 0.5;
220
221 for(int i = 1; i < w; ++i)
222 {
223 derivatives_cols_(i,h) = (intensity_ ((*input_) (i,h)) - intensity_ ((*input_) (i,h-1))) * 0.5;
224 }
225 derivatives_rows_(w,h) = (intensity_ ((*input_) (w,h)) - intensity_ ((*input_) (w-1,h))) * 0.5;
226 derivatives_cols_(w,h) = (intensity_ ((*input_) (w,h)) - intensity_ ((*input_) (w,h-1))) * 0.5;
227
228 switch (method_)
229 {
230 case HARRIS:
231 responseHarris(*response_);
232 break;
233 case NOBLE:
234 responseNoble(*response_);
235 break;
236 case LOWE:
237 responseLowe(*response_);
238 break;
239 case TOMASI:
240 responseTomasi(*response_);
241 break;
242 }
243
244 if (!nonmax_)
245 {
246 output = *response_;
247 for (std::size_t i = 0; i < response_->size (); ++i)
248 keypoints_indices_->indices.push_back (i);
249 }
250 else
251 {
252 std::sort (indices_->begin (), indices_->end (), [this] (int p1, int p2) { return greaterIntensityAtIndices (p1, p2); });
253 const float threshold = threshold_ * (*response_)[indices_->front ()].intensity;
254 output.clear ();
255 output.reserve (response_->size());
256 std::vector<bool> occupency_map (response_->size (), false);
257 int width (response_->width);
258 int height (response_->height);
259 const int occupency_map_size (occupency_map.size ());
260
261#if OPENMP_LEGACY_CONST_DATA_SHARING_RULE
262#pragma omp parallel for \
263 default(none) \
264 shared(occupency_map, output) \
265 firstprivate(width, height) \
266 num_threads(threads_)
267#else
268#pragma omp parallel for \
269 default(none) \
270 shared(occupency_map, occupency_map_size, output, threshold) \
271 firstprivate(width, height) \
272 num_threads(threads_)
273#endif
274 for (int i = 0; i < occupency_map_size; ++i)
275 {
276 int idx = indices_->at (i);
277 const PointOutT& point_out = response_->points [idx];
278 if (occupency_map[idx] || point_out.intensity < threshold || !isXYZFinite (point_out))
279 continue;
280
281#pragma omp critical
282 {
283 output.push_back (point_out);
284 keypoints_indices_->indices.push_back (idx);
285 }
286
287 int u_end = std::min (width, idx % width + min_distance_);
288 int v_end = std::min (height, idx / width + min_distance_);
289 for(int u = std::max (0, idx % width - min_distance_); u < u_end; ++u)
290 for(int v = std::max (0, idx / width - min_distance_); v < v_end; ++v)
291 occupency_map[v*input_->width+u] = true;
292 }
293
294 // if (refine_)
295 // refineCorners (output);
296
297 output.height = 1;
298 output.width = output.size();
299 }
300
301 // we don not change the denseness
302 output.is_dense = input_->is_dense;
303}
304
305
306template <typename PointInT, typename PointOutT, typename IntensityT> void
308{
309 PCL_ALIGN (16) float covar [3];
310 output.clear ();
311 output.resize (input_->size ());
312 const int output_size (output.size ());
313
314#if OPENMP_LEGACY_CONST_DATA_SHARING_RULE
315#pragma omp parallel for \
316 default(none) \
317 shared(output) \
318 firstprivate(covar) \
319 num_threads(threads_)
320#else
321#pragma omp parallel for \
322 default(none) \
323 shared(output, output_size) \
324 firstprivate(covar) \
325 num_threads(threads_)
326#endif
327 for (int index = 0; index < output_size; ++index)
328 {
329 PointOutT& out_point = output.points [index];
330 const PointInT &in_point = (*input_).points [index];
331 out_point.intensity = 0;
332 out_point.x = in_point.x;
333 out_point.y = in_point.y;
334 out_point.z = in_point.z;
335 if (isXYZFinite (in_point))
336 {
337 computeSecondMomentMatrix (index, covar);
338 float trace = covar [0] + covar [2];
339 if (trace != 0.f)
340 {
341 float det = covar[0] * covar[2] - covar[1] * covar[1];
342 out_point.intensity = 0.04f + det - 0.04f * trace * trace;
343 }
344 }
345 }
346
347 output.height = input_->height;
348 output.width = input_->width;
349}
350
351
352template <typename PointInT, typename PointOutT, typename IntensityT> void
354{
355 PCL_ALIGN (16) float covar [3];
356 output.clear ();
357 output.resize (input_->size ());
358 const int output_size (output.size ());
359
360#if OPENMP_LEGACY_CONST_DATA_SHARING_RULE
361#pragma omp parallel for \
362 default(none) \
363 shared(output) \
364 firstprivate(covar) \
365 num_threads(threads_)
366#else
367#pragma omp parallel for \
368 default(none) \
369 shared(output, output_size) \
370 firstprivate(covar) \
371 num_threads(threads_)
372#endif
373 for (int index = 0; index < output_size; ++index)
374 {
375 PointOutT &out_point = output.points [index];
376 const PointInT &in_point = input_->points [index];
377 out_point.x = in_point.x;
378 out_point.y = in_point.y;
379 out_point.z = in_point.z;
380 out_point.intensity = 0;
381 if (isXYZFinite (in_point))
382 {
383 computeSecondMomentMatrix (index, covar);
384 float trace = covar [0] + covar [2];
385 if (trace != 0)
386 {
387 float det = covar[0] * covar[2] - covar[1] * covar[1];
388 out_point.intensity = det / trace;
389 }
390 }
391 }
392
393 output.height = input_->height;
394 output.width = input_->width;
395}
396
397
398template <typename PointInT, typename PointOutT, typename IntensityT> void
400{
401 PCL_ALIGN (16) float covar [3];
402 output.clear ();
403 output.resize (input_->size ());
404 const int output_size (output.size ());
405
406#if OPENMP_LEGACY_CONST_DATA_SHARING_RULE
407#pragma omp parallel for \
408 default(none) \
409 shared(output) \
410 firstprivate(covar) \
411 num_threads(threads_)
412#else
413#pragma omp parallel for \
414 default(none) \
415 shared(output, output_size) \
416 firstprivate(covar) \
417 num_threads(threads_)
418#endif
419 for (int index = 0; index < output_size; ++index)
420 {
421 PointOutT &out_point = output.points [index];
422 const PointInT &in_point = input_->points [index];
423 out_point.x = in_point.x;
424 out_point.y = in_point.y;
425 out_point.z = in_point.z;
426 out_point.intensity = 0;
427 if (isXYZFinite (in_point))
428 {
429 computeSecondMomentMatrix (index, covar);
430 float trace = covar [0] + covar [2];
431 if (trace != 0)
432 {
433 float det = covar[0] * covar[2] - covar[1] * covar[1];
434 out_point.intensity = det / (trace * trace);
435 }
436 }
437 }
438
439 output.height = input_->height;
440 output.width = input_->width;
441}
442
443
444template <typename PointInT, typename PointOutT, typename IntensityT> void
446{
447 PCL_ALIGN (16) float covar [3];
448 output.clear ();
449 output.resize (input_->size ());
450 const int output_size (output.size ());
451
452#if OPENMP_LEGACY_CONST_DATA_SHARING_RULE
453#pragma omp parallel for \
454 default(none) \
455 shared(output) \
456 firstprivate(covar) \
457 num_threads(threads_)
458#else
459#pragma omp parallel for \
460 default(none) \
461 shared(output, output_size) \
462 firstprivate(covar) \
463 num_threads(threads_)
464#endif
465 for (int index = 0; index < output_size; ++index)
466 {
467 PointOutT &out_point = output.points [index];
468 const PointInT &in_point = input_->points [index];
469 out_point.x = in_point.x;
470 out_point.y = in_point.y;
471 out_point.z = in_point.z;
472 out_point.intensity = 0;
473 if (isXYZFinite (in_point))
474 {
475 computeSecondMomentMatrix (index, covar);
476 // min egenvalue
477 out_point.intensity = ((covar[0] + covar[2] - std::sqrt((covar[0] - covar[2])*(covar[0] - covar[2]) + 4 * covar[1] * covar[1])) /2.0f);
478 }
479 }
480
481 output.height = input_->height;
482 output.width = input_->width;
483}
484
485} // namespace pcl
486
487#define PCL_INSTANTIATE_HarrisKeypoint2D(T,U,I) template class PCL_EXPORTS pcl::HarrisKeypoint2D<T,U,I>;
488
489#endif // #ifndef PCL_HARRIS_KEYPOINT_2D_IMPL_H_
490
void setNonMaxSupression(bool=false)
whether non maxima suppression should be applied or the response for each point should be returned
Definition harris_2d.hpp:73
void setSkippedPixels(int skipped_pixels)
Set number of pixels to skip.
Definition harris_2d.hpp:94
void responseTomasi(PointCloudOut &output) const
void responseLowe(PointCloudOut &output) const
void setRefine(bool do_refine)
whether the detected key points should be refined or not.
Definition harris_2d.hpp:66
void detectKeypoints(PointCloudOut &output) override
void responseNoble(PointCloudOut &output) const
void setMinimalDistance(int min_distance)
Set minimal distance between candidate keypoints.
void setMethod(ResponseMethod type)
set the method of the response to be calculated.
Definition harris_2d.hpp:52
void computeSecondMomentMatrix(std::size_t pos, float *coefficients) const
calculates the upper triangular part of unnormalized covariance matrix over intensities given by the ...
void setWindowHeight(int window_height)
Set window height.
Definition harris_2d.hpp:87
void responseHarris(PointCloudOut &output) const
gets the corner response for valid input points
typename Keypoint< PointInT, PointOutT >::PointCloudOut PointCloudOut
Definition harris_2d.h:60
bool initCompute() override
void setThreshold(float threshold)
set the threshold value for detecting corners.
Definition harris_2d.hpp:59
void setWindowWidth(int window_width)
Set window width.
Definition harris_2d.hpp:80
Keypoint represents the base class for key points.
Definition keypoint.h:49
constexpr bool isXYZFinite(const PointT &) noexcept