38 #ifndef PCL_HARRIS_KEYPOINT_3D_IMPL_H_
39 #define PCL_HARRIS_KEYPOINT_3D_IMPL_H_
50 #include <xmmintrin.h>
54 template <
typename Po
intInT,
typename Po
intOutT,
typename NormalT>
void
61 template <
typename Po
intInT,
typename Po
intOutT,
typename NormalT>
void
64 threshold_= threshold;
68 template <
typename Po
intInT,
typename Po
intOutT,
typename NormalT>
void
71 search_radius_ = radius;
75 template <
typename Po
intInT,
typename Po
intOutT,
typename NormalT>
void
82 template <
typename Po
intInT,
typename Po
intOutT,
typename NormalT>
void
89 template <
typename Po
intInT,
typename Po
intOutT,
typename NormalT>
void
92 normals_.reset (normals.get ());
96 template <
typename Po
intInT,
typename Po
intOutT,
typename NormalT>
void
104 __m128 vec1 = _mm_setzero_ps();
106 __m128 vec2 = _mm_setzero_ps();
114 for (std::vector<int>::const_iterator iIt = neighbors.begin(); iIt != neighbors.end(); ++iIt)
119 norm1 = _mm_load_ps (&(normals_->points[*iIt].normal_x));
122 norm2 = _mm_set1_ps (normals_->points[*iIt].normal_x);
125 norm2 = _mm_mul_ps (norm1, norm2);
128 vec1 = _mm_add_ps (vec1, norm2);
131 norm2 = _mm_set1_ps (normals_->points[*iIt].normal_y);
134 norm2 = _mm_mul_ps (norm1, norm2);
137 vec2 = _mm_add_ps (vec2, norm2);
139 zz += normals_->points[*iIt].normal_z * normals_->points[*iIt].normal_z;
145 norm2 = _mm_set1_ps (
float(count));
146 vec1 = _mm_div_ps (vec1, norm2);
147 vec2 = _mm_div_ps (vec2, norm2);
148 _mm_store_ps (coefficients, vec1);
149 _mm_store_ps (coefficients + 4, vec2);
150 coefficients [7] = zz / float(count);
153 memset (coefficients, 0,
sizeof (
float) * 8);
155 memset (coefficients, 0,
sizeof (
float) * 8);
156 for (std::vector<int>::const_iterator iIt = neighbors.begin(); iIt != neighbors.end(); ++iIt)
160 coefficients[0] += normals_->points[*iIt].normal_x * normals_->points[*iIt].normal_x;
161 coefficients[1] += normals_->points[*iIt].normal_x * normals_->points[*iIt].normal_y;
162 coefficients[2] += normals_->points[*iIt].normal_x * normals_->points[*iIt].normal_z;
164 coefficients[5] += normals_->points[*iIt].normal_y * normals_->points[*iIt].normal_y;
165 coefficients[6] += normals_->points[*iIt].normal_y * normals_->points[*iIt].normal_z;
166 coefficients[7] += normals_->points[*iIt].normal_z * normals_->points[*iIt].normal_z;
173 float norm = 1.0 / float (count);
174 coefficients[0] *= norm;
175 coefficients[1] *= norm;
176 coefficients[2] *= norm;
177 coefficients[5] *= norm;
178 coefficients[6] *= norm;
179 coefficients[7] *= norm;
185 template <
typename Po
intInT,
typename Po
intOutT,
typename NormalT>
bool
188 if (!Keypoint<PointInT, PointOutT>::initCompute ())
190 PCL_ERROR (
"[pcl::%s::initCompute] init failed!\n", name_.c_str ());
194 if (method_ < 1 || method_ > 5)
196 PCL_ERROR (
"[pcl::%s::initCompute] method (%d) must be in [1..5]!\n", name_.c_str (), method_);
200 if (normals_->empty ())
202 normals_->reserve (surface_->size ());
203 if (input_->height == 1 )
208 normal_estimation.
compute (*normals_);
212 IntegralImageNormalEstimation<PointInT, NormalT> normal_estimation;
215 normal_estimation.setNormalSmoothingSize (5.0);
216 normal_estimation.compute (*normals_);
223 template <
typename Po
intInT,
typename Po
intOutT,
typename NormalT>
void
228 response->points.reserve (input_->points.size());
233 responseHarris(*response);
236 responseNoble(*response);
239 responseLowe(*response);
242 responseCurvature(*response);
245 responseTomasi(*response);
253 output.points.clear ();
254 output.points.reserve (response->points.size());
256 #if defined (HAVE_OPENMP) && (defined(_WIN32) || ((__GNUC__ > 4) && (__GNUC_MINOR__ > 2)))
257 #pragma omp parallel for shared (output) num_threads(threads_)
259 for (
int idx = 0; idx < static_cast<int> (response->points.size ()); ++idx)
261 if (!
isFinite (response->points[idx]) || response->points[idx].intensity < threshold_)
263 std::vector<int> nn_indices;
264 std::vector<float> nn_dists;
265 tree_->radiusSearch (idx, search_radius_, nn_indices, nn_dists);
266 bool is_maxima =
true;
267 for (std::vector<int>::const_iterator iIt = nn_indices.begin(); iIt != nn_indices.end(); ++iIt)
269 if (response->points[idx].intensity < response->points[*iIt].intensity)
276 #if defined (HAVE_OPENMP) && (defined(_WIN32) || ((__GNUC__ > 4) && (__GNUC_MINOR__ > 2)))
279 output.points.push_back (response->points[idx]);
283 refineCorners (output);
286 output.width =
static_cast<uint32_t
> (output.points.size());
290 output.is_dense = input_->is_dense;
294 template <
typename Po
intInT,
typename Po
intOutT,
typename NormalT>
void
297 PCL_ALIGN (16) float covar [8];
298 output.resize (input_->size ());
299 #if defined (HAVE_OPENMP) && (defined(_WIN32) || ((__GNUC__ > 4) && (__GNUC_MINOR__ > 2)))
300 #pragma omp parallel for shared (output) private (covar) num_threads(threads_)
302 for (
int pIdx = 0; pIdx < static_cast<int> (input_->size ()); ++pIdx)
304 const PointInT& pointIn = input_->points [pIdx];
305 output [pIdx].intensity = 0.0;
308 std::vector<int> nn_indices;
309 std::vector<float> nn_dists;
310 tree_->radiusSearch (pointIn, search_radius_, nn_indices, nn_dists);
311 calculateNormalCovar (nn_indices, covar);
313 float trace = covar [0] + covar [5] + covar [7];
316 float det = covar [0] * covar [5] * covar [7] + 2.0f * covar [1] * covar [2] * covar [6]
317 - covar [2] * covar [2] * covar [5]
318 - covar [1] * covar [1] * covar [7]
319 - covar [6] * covar [6] * covar [0];
321 output [pIdx].intensity = 0.04f + det - 0.04f * trace * trace;
324 output [pIdx].x = pointIn.x;
325 output [pIdx].y = pointIn.y;
326 output [pIdx].z = pointIn.z;
328 output.height = input_->height;
329 output.width = input_->width;
333 template <
typename Po
intInT,
typename Po
intOutT,
typename NormalT>
void
336 PCL_ALIGN (16) float covar [8];
337 output.resize (input_->size ());
338 #if defined (HAVE_OPENMP) && (defined(_WIN32) || ((__GNUC__ > 4) && (__GNUC_MINOR__ > 2)))
339 #pragma omp parallel for shared (output) private (covar) num_threads(threads_)
341 for (
int pIdx = 0; pIdx < static_cast<int> (input_->size ()); ++pIdx)
343 const PointInT& pointIn = input_->points [pIdx];
344 output [pIdx].intensity = 0.0;
347 std::vector<int> nn_indices;
348 std::vector<float> nn_dists;
349 tree_->radiusSearch (pointIn, search_radius_, nn_indices, nn_dists);
350 calculateNormalCovar (nn_indices, covar);
351 float trace = covar [0] + covar [5] + covar [7];
354 float det = covar [0] * covar [5] * covar [7] + 2.0f * covar [1] * covar [2] * covar [6]
355 - covar [2] * covar [2] * covar [5]
356 - covar [1] * covar [1] * covar [7]
357 - covar [6] * covar [6] * covar [0];
359 output [pIdx].intensity = det / trace;
362 output [pIdx].x = pointIn.x;
363 output [pIdx].y = pointIn.y;
364 output [pIdx].z = pointIn.z;
366 output.height = input_->height;
367 output.width = input_->width;
371 template <
typename Po
intInT,
typename Po
intOutT,
typename NormalT>
void
374 PCL_ALIGN (16) float covar [8];
375 output.resize (input_->size ());
376 #if defined (HAVE_OPENMP) && (defined(_WIN32) || ((__GNUC__ > 4) && (__GNUC_MINOR__ > 2)))
377 #pragma omp parallel for shared (output) private (covar) num_threads(threads_)
379 for (
int pIdx = 0; pIdx < static_cast<int> (input_->size ()); ++pIdx)
381 const PointInT& pointIn = input_->points [pIdx];
382 output [pIdx].intensity = 0.0;
385 std::vector<int> nn_indices;
386 std::vector<float> nn_dists;
387 tree_->radiusSearch (pointIn, search_radius_, nn_indices, nn_dists);
388 calculateNormalCovar (nn_indices, covar);
389 float trace = covar [0] + covar [5] + covar [7];
392 float det = covar [0] * covar [5] * covar [7] + 2.0f * covar [1] * covar [2] * covar [6]
393 - covar [2] * covar [2] * covar [5]
394 - covar [1] * covar [1] * covar [7]
395 - covar [6] * covar [6] * covar [0];
397 output [pIdx].intensity = det / (trace * trace);
400 output [pIdx].x = pointIn.x;
401 output [pIdx].y = pointIn.y;
402 output [pIdx].z = pointIn.z;
404 output.height = input_->height;
405 output.width = input_->width;
409 template <
typename Po
intInT,
typename Po
intOutT,
typename NormalT>
void
413 for (
unsigned idx = 0; idx < input_->points.size(); ++idx)
415 point.x = input_->points[idx].x;
416 point.y = input_->points[idx].y;
417 point.z = input_->points[idx].z;
418 point.intensity = normals_->points[idx].curvature;
419 output.points.push_back(point);
422 output.height = input_->height;
423 output.width = input_->width;
427 template <
typename Po
intInT,
typename Po
intOutT,
typename NormalT>
void
430 PCL_ALIGN (16) float covar [8];
431 Eigen::Matrix3f covariance_matrix;
432 output.resize (input_->size ());
433 #if defined (HAVE_OPENMP) && (defined(_WIN32) || ((__GNUC__ > 4) && (__GNUC_MINOR__ > 2)))
434 #pragma omp parallel for shared (output) private (covar, covariance_matrix) num_threads(threads_)
436 for (
int pIdx = 0; pIdx < static_cast<int> (input_->size ()); ++pIdx)
438 const PointInT& pointIn = input_->points [pIdx];
439 output [pIdx].intensity = 0.0;
442 std::vector<int> nn_indices;
443 std::vector<float> nn_dists;
444 tree_->radiusSearch (pointIn, search_radius_, nn_indices, nn_dists);
445 calculateNormalCovar (nn_indices, covar);
446 float trace = covar [0] + covar [5] + covar [7];
449 covariance_matrix.coeffRef (0) = covar [0];
450 covariance_matrix.coeffRef (1) = covariance_matrix.coeffRef (3) = covar [1];
451 covariance_matrix.coeffRef (2) = covariance_matrix.coeffRef (6) = covar [2];
452 covariance_matrix.coeffRef (4) = covar [5];
453 covariance_matrix.coeffRef (5) = covariance_matrix.coeffRef (7) = covar [6];
454 covariance_matrix.coeffRef (8) = covar [7];
458 output [pIdx].intensity = eigen_values[0];
461 output [pIdx].x = pointIn.x;
462 output [pIdx].y = pointIn.y;
463 output [pIdx].z = pointIn.z;
465 output.height = input_->height;
466 output.width = input_->width;
470 template <
typename Po
intInT,
typename Po
intOutT,
typename NormalT>
void
475 Eigen::Matrix3f NNTInv;
476 Eigen::Vector3f NNTp;
478 const unsigned max_iterations = 10;
479 #if defined (HAVE_OPENMP) && (defined(_WIN32) || ((__GNUC__ > 4) && (__GNUC_MINOR__ > 2)))
480 #pragma omp parallel for shared (corners) private (nnT, NNT, NNTInv, NNTp, diff) num_threads(threads_)
482 for (
int cIdx = 0; cIdx < static_cast<int> (corners.size ()); ++cIdx)
484 unsigned iterations = 0;
489 corner.x = corners[cIdx].x;
490 corner.y = corners[cIdx].y;
491 corner.z = corners[cIdx].z;
492 std::vector<int> nn_indices;
493 std::vector<float> nn_dists;
494 tree_->radiusSearch (corner, search_radius_, nn_indices, nn_dists);
495 for (std::vector<int>::const_iterator iIt = nn_indices.begin(); iIt != nn_indices.end(); ++iIt)
500 nnT = normals_->points[*iIt].getNormalVector3fMap () * normals_->points[*iIt].getNormalVector3fMap ().transpose();
502 NNTp += nnT * surface_->points[*iIt].getVector3fMap ();
505 corners[cIdx].getVector3fMap () = NNTInv * NNTp;
507 diff = (corners[cIdx].getVector3fMap () - corner.getVector3fMap()).squaredNorm ();
508 }
while (diff > 1e-6 && ++iterations < max_iterations);
512 #define PCL_INSTANTIATE_HarrisKeypoint3D(T,U,N) template class PCL_EXPORTS pcl::HarrisKeypoint3D<T,U,N>;
513 #endif // #ifndef PCL_HARRIS_KEYPOINT_3D_IMPL_H_