|
Point Cloud Library (PCL)
1.5.1
|
00001 /* 00002 * Software License Agreement (BSD License) 00003 * 00004 * Point Cloud Library (PCL) - www.pointclouds.org 00005 * Copyright (c) 2010-2011, Willow Garage, Inc. 00006 * 00007 * All rights reserved. 00008 * 00009 * Redistribution and use in source and binary forms, with or without 00010 * modification, are permitted provided that the following conditions 00011 * are met: 00012 * 00013 * * Redistributions of source code must retain the above copyright 00014 * notice, this list of conditions and the following disclaimer. 00015 * * Redistributions in binary form must reproduce the above 00016 * copyright notice, this list of conditions and the following 00017 * disclaimer in the documentation and/or other materials provided 00018 * with the distribution. 00019 * * Neither the name of Willow Garage, Inc. nor the names of its 00020 * contributors may be used to endorse or promote products derived 00021 * from this software without specific prior written permission. 00022 * 00023 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00024 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00025 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00026 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00027 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00028 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00029 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00030 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00031 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00032 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00033 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00034 * POSSIBILITY OF SUCH DAMAGE. 00035 * 00036 */ 00037 00038 #ifndef PCL_HARRIS_KEYPOINT_3D_IMPL_H_ 00039 #define PCL_HARRIS_KEYPOINT_3D_IMPL_H_ 00040 00041 #include "pcl/keypoints/harris_keypoint3D.h" 00042 #include <pcl/common/io.h> 00043 #include <pcl/filters/passthrough.h> 00044 #include <pcl/filters/extract_indices.h> 00045 #include <pcl/features/normal_3d.h> 00046 #include <pcl/features/integral_image_normal.h> 00047 #include <pcl/common/time.h> 00048 #include <pcl/common/centroid.h> 00049 #ifdef __SSE__ 00050 #include <xmmintrin.h> 00051 #endif 00052 00054 template <typename PointInT, typename PointOutT, typename NormalT> void 00055 pcl::HarrisKeypoint3D<PointInT, PointOutT, NormalT>::setMethod (ResponseMethod method) 00056 { 00057 method_ = method; 00058 } 00059 00061 template <typename PointInT, typename PointOutT, typename NormalT> void 00062 pcl::HarrisKeypoint3D<PointInT, PointOutT, NormalT>::setThreshold (float threshold) 00063 { 00064 threshold_= threshold; 00065 } 00066 00068 template <typename PointInT, typename PointOutT, typename NormalT> void 00069 pcl::HarrisKeypoint3D<PointInT, PointOutT, NormalT>::setRadius (float radius) 00070 { 00071 search_radius_ = radius; 00072 } 00073 00075 template <typename PointInT, typename PointOutT, typename NormalT> void 00076 pcl::HarrisKeypoint3D<PointInT, PointOutT, NormalT>::setRefine (bool do_refine) 00077 { 00078 refine_ = do_refine; 00079 } 00080 00082 template <typename PointInT, typename PointOutT, typename NormalT> void 00083 pcl::HarrisKeypoint3D<PointInT, PointOutT, NormalT>::setNonMaxSupression (bool nonmax) 00084 { 00085 nonmax_ = nonmax; 00086 } 00087 00089 template <typename PointInT, typename PointOutT, typename NormalT> void 00090 pcl::HarrisKeypoint3D<PointInT, PointOutT, NormalT>::setNormals (boost::shared_ptr<pcl::PointCloud<NormalT> > normals ) const 00091 { 00092 normals_.reset (normals); 00093 } 00094 00096 template <typename PointInT, typename PointOutT, typename NormalT> void 00097 pcl::HarrisKeypoint3D<PointInT, PointOutT, NormalT>::calculateNormalCovar (const std::vector<int>& neighbors, float* coefficients) const 00098 { 00099 unsigned count = 0; 00100 // indices 0 1 2 3 4 5 6 7 00101 // coefficients: xx xy xz ?? yx yy yz ?? 00102 #ifdef __SSE__ 00103 // accumulator for xx, xy, xz 00104 __m128 vec1 = _mm_setzero_ps(); 00105 // accumulator for yy, yz, zz 00106 __m128 vec2 = _mm_setzero_ps(); 00107 00108 __m128 norm1; 00109 00110 __m128 norm2; 00111 00112 float zz = 0; 00113 00114 for (std::vector<int>::const_iterator iIt = neighbors.begin(); iIt != neighbors.end(); ++iIt) 00115 { 00116 if (pcl_isfinite (normals_->points[*iIt].normal_x)) 00117 { 00118 // nx, ny, nz, h 00119 norm1 = _mm_load_ps (&(normals_->points[*iIt].normal_x)); 00120 00121 // nx, nx, nx, nx 00122 norm2 = _mm_set1_ps (normals_->points[*iIt].normal_x); 00123 00124 // nx * nx, nx * ny, nx * nz, nx * h 00125 norm2 = _mm_mul_ps (norm1, norm2); 00126 00127 // accumulate 00128 vec1 = _mm_add_ps (vec1, norm2); 00129 00130 // ny, ny, ny, ny 00131 norm2 = _mm_set1_ps (normals_->points[*iIt].normal_y); 00132 00133 // ny * nx, ny * ny, ny * nz, ny * h 00134 norm2 = _mm_mul_ps (norm1, norm2); 00135 00136 // accumulate 00137 vec2 = _mm_add_ps (vec2, norm2); 00138 00139 zz += normals_->points[*iIt].normal_z * normals_->points[*iIt].normal_z; 00140 ++count; 00141 } 00142 } 00143 if (count > 0) 00144 { 00145 norm2 = _mm_set1_ps (float(count)); 00146 vec1 = _mm_div_ps (vec1, norm2); 00147 vec2 = _mm_div_ps (vec2, norm2); 00148 _mm_store_ps (coefficients, vec1); 00149 _mm_store_ps (coefficients + 4, vec2); 00150 coefficients [7] = zz / float(count); 00151 } 00152 else 00153 memset (coefficients, 0, sizeof (float) * 8); 00154 #else 00155 memset (coefficients, 0, sizeof (float) * 8); 00156 for (std::vector<int>::const_iterator iIt = neighbors.begin(); iIt != neighbors.end(); ++iIt) 00157 { 00158 if (pcl_isfinite (normals_->points[*iIt].normal_x)) 00159 { 00160 coefficients[0] += normals_->points[*iIt].normal_x * normals_->points[*iIt].normal_x; 00161 coefficients[1] += normals_->points[*iIt].normal_x * normals_->points[*iIt].normal_y; 00162 coefficients[2] += normals_->points[*iIt].normal_x * normals_->points[*iIt].normal_z; 00163 00164 coefficients[5] += normals_->points[*iIt].normal_y * normals_->points[*iIt].normal_y; 00165 coefficients[6] += normals_->points[*iIt].normal_y * normals_->points[*iIt].normal_z; 00166 coefficients[7] += normals_->points[*iIt].normal_z * normals_->points[*iIt].normal_z; 00167 00168 ++count; 00169 } 00170 } 00171 if (count > 0) 00172 { 00173 float norm = 1.0 / float (count); 00174 coefficients[0] *= norm; 00175 coefficients[1] *= norm; 00176 coefficients[2] *= norm; 00177 coefficients[5] *= norm; 00178 coefficients[6] *= norm; 00179 coefficients[7] *= norm; 00180 } 00181 #endif 00182 } 00183 00185 template <typename PointInT, typename PointOutT, typename NormalT> void 00186 pcl::HarrisKeypoint3D<PointInT, PointOutT, NormalT>::detectKeypoints (PointCloudOut &output) 00187 { 00188 if (normals_->empty ()) 00189 { 00190 normals_->reserve (surface_->size ()); 00191 if (input_->height == 1 ) // not organized 00192 { 00193 pcl::NormalEstimation<PointInT, NormalT> normal_estimation; 00194 normal_estimation.setInputCloud(surface_); 00195 normal_estimation.setRadiusSearch(search_radius_); 00196 normal_estimation.compute (*normals_); 00197 } 00198 else 00199 { 00200 IntegralImageNormalEstimation<PointInT, NormalT> normal_estimation; 00201 normal_estimation.setNormalEstimationMethod (pcl::IntegralImageNormalEstimation<PointInT, NormalT>::SIMPLE_3D_GRADIENT); 00202 normal_estimation.setInputCloud(surface_); 00203 normal_estimation.setNormalSmoothingSize (5.0); 00204 normal_estimation.compute (*normals_); 00205 } 00206 } 00207 00208 boost::shared_ptr<pcl::PointCloud<PointOutT> > response (new pcl::PointCloud<PointOutT> ()); 00209 00210 response->points.reserve (input_->points.size()); 00211 00212 switch (method_) 00213 { 00214 case HARRIS: 00215 responseHarris(*response); 00216 break; 00217 case NOBLE: 00218 responseNoble(*response); 00219 break; 00220 case LOWE: 00221 responseLowe(*response); 00222 break; 00223 case CURVATURE: 00224 responseCurvature(*response); 00225 break; 00226 case TOMASI: 00227 responseTomasi(*response); 00228 break; 00229 } 00230 00231 if (!nonmax_) 00232 output = *response; 00233 else 00234 { 00235 output.points.clear (); 00236 output.points.reserve (response->points.size()); 00237 std::vector<int> nn_indices; 00238 std::vector<float> nn_dists; 00239 00240 #if defined __GNUC__ 00241 # if __GNUC__ == 4 && __GNUC_MINOR__ > 3 00242 # pragma omp parallel for shared (output) private (nn_indices, nn_dists) num_threads(threads_) 00243 # endif 00244 #endif 00245 for (int idx = 0; idx < (int) response->points.size (); ++idx) 00246 { 00247 if (!isFinite (response->points[idx]) || response->points[idx].intensity < threshold_) 00248 continue; 00249 tree_->radiusSearch (idx, search_radius_, nn_indices, nn_dists); 00250 bool is_maxima = true; 00251 for (std::vector<int>::const_iterator iIt = nn_indices.begin(); iIt != nn_indices.end(); ++iIt) 00252 { 00253 if (response->points[idx].intensity < response->points[*iIt].intensity) 00254 { 00255 is_maxima = false; 00256 break; 00257 } 00258 } 00259 if (is_maxima) 00260 #pragma omp critical 00261 output.points.push_back (response->points[idx]); 00262 } 00263 00264 if (refine_) 00265 refineCorners (output); 00266 00267 output.height = 1; 00268 output.width = output.points.size(); 00269 } 00270 00271 // we don not change the denseness 00272 output.is_dense = input_->is_dense; 00273 } 00274 00276 template <typename PointInT, typename PointOutT, typename NormalT> void 00277 pcl::HarrisKeypoint3D<PointInT, PointOutT, NormalT>::responseHarris (PointCloudOut &output) const 00278 { 00279 PCL_ALIGN (16) float covar [8]; 00280 std::vector<int> nn_indices; 00281 std::vector<float> nn_dists; 00282 output.resize (input_->size ()); 00283 #if defined __GNUC__ 00284 # if __GNUC__ == 4 && __GNUC_MINOR__ > 3 00285 # pragma omp parallel for shared (output) private (covar, nn_indices, nn_dists) num_threads(threads_) 00286 # endif 00287 #endif 00288 for (int pIdx = 0; pIdx < (int) input_->size (); ++pIdx) 00289 { 00290 const PointInT& pointIn = input_->points [pIdx]; 00291 output [pIdx].intensity = 0.0; //std::numeric_limits<float>::quiet_NaN (); 00292 if (isFinite (pointIn)) 00293 { 00294 tree_->radiusSearch (pointIn, search_radius_, nn_indices, nn_dists); 00295 calculateNormalCovar (nn_indices, covar); 00296 00297 float trace = covar [0] + covar [5] + covar [7]; 00298 if (trace != 0) 00299 { 00300 float det = covar [0] * covar [5] * covar [7] + 2.0 * covar [1] * covar [2] * covar [6] 00301 - covar [2] * covar [2] * covar [5] 00302 - covar [1] * covar [1] * covar [7] 00303 - covar [6] * covar [6] * covar [0]; 00304 00305 output [pIdx].intensity = 0.04 + det - 0.04 * trace * trace; 00306 } 00307 } 00308 output [pIdx].x = pointIn.x; 00309 output [pIdx].y = pointIn.y; 00310 output [pIdx].z = pointIn.z; 00311 } 00312 output.height = input_->height; 00313 output.width = input_->width; 00314 } 00315 00317 template <typename PointInT, typename PointOutT, typename NormalT> void 00318 pcl::HarrisKeypoint3D<PointInT, PointOutT, NormalT>::responseNoble (PointCloudOut &output) const 00319 { 00320 std::vector<int> nn_indices; 00321 std::vector<float> nn_dists; 00322 PCL_ALIGN (16) float covar [8]; 00323 output.resize (input_->size ()); 00324 #if defined __GNUC__ 00325 # if __GNUC__ == 4 && __GNUC_MINOR__ > 3 00326 # pragma omp parallel for shared (output) private (covar, nn_indices, nn_dists) num_threads(threads_) 00327 # endif 00328 #endif 00329 for (int pIdx = 0; pIdx < (int) input_->size (); ++pIdx) 00330 { 00331 const PointInT& pointIn = input_->points [pIdx]; 00332 output [pIdx].intensity = 0.0; 00333 if (isFinite (pointIn)) 00334 { 00335 tree_->radiusSearch (pointIn, search_radius_, nn_indices, nn_dists); 00336 calculateNormalCovar (nn_indices, covar); 00337 float trace = covar [0] + covar [5] + covar [7]; 00338 if (trace != 0) 00339 { 00340 float det = covar [0] * covar [5] * covar [7] + 2.0 * covar [1] * covar [2] * covar [6] 00341 - covar [2] * covar [2] * covar [5] 00342 - covar [1] * covar [1] * covar [7] 00343 - covar [6] * covar [6] * covar [0]; 00344 00345 output [pIdx].intensity = det / trace; 00346 } 00347 } 00348 output [pIdx].x = pointIn.x; 00349 output [pIdx].y = pointIn.y; 00350 output [pIdx].z = pointIn.z; 00351 } 00352 output.height = input_->height; 00353 output.width = input_->width; 00354 } 00355 00357 template <typename PointInT, typename PointOutT, typename NormalT> void 00358 pcl::HarrisKeypoint3D<PointInT, PointOutT, NormalT>::responseLowe (PointCloudOut &output) const 00359 { 00360 std::vector<int> nn_indices; 00361 std::vector<float> nn_dists; 00362 PCL_ALIGN (16) float covar [8]; 00363 output.resize (input_->size ()); 00364 #if defined __GNUC__ 00365 # if __GNUC__ == 4 && __GNUC_MINOR__ > 3 00366 # pragma omp parallel for shared (output) private (covar, nn_indices, nn_dists) num_threads(threads_) 00367 # endif 00368 #endif 00369 for (int pIdx = 0; pIdx < (int) input_->size (); ++pIdx) 00370 { 00371 const PointInT& pointIn = input_->points [pIdx]; 00372 output [pIdx].intensity = 0.0; 00373 if (isFinite (pointIn)) 00374 { 00375 tree_->radiusSearch (pointIn, search_radius_, nn_indices, nn_dists); 00376 calculateNormalCovar (nn_indices, covar); 00377 float trace = covar [0] + covar [5] + covar [7]; 00378 if (trace != 0) 00379 { 00380 float det = covar [0] * covar [5] * covar [7] + 2.0 * covar [1] * covar [2] * covar [6] 00381 - covar [2] * covar [2] * covar [5] 00382 - covar [1] * covar [1] * covar [7] 00383 - covar [6] * covar [6] * covar [0]; 00384 00385 output [pIdx].intensity = det / (trace * trace); 00386 } 00387 } 00388 output [pIdx].x = pointIn.x; 00389 output [pIdx].y = pointIn.y; 00390 output [pIdx].z = pointIn.z; 00391 } 00392 output.height = input_->height; 00393 output.width = input_->width; 00394 } 00395 00397 template <typename PointInT, typename PointOutT, typename NormalT> void 00398 pcl::HarrisKeypoint3D<PointInT, PointOutT, NormalT>::responseCurvature (PointCloudOut &output) const 00399 { 00400 PointOutT point; 00401 for (unsigned idx = 0; idx < input_->points.size(); ++idx) 00402 { 00403 point.x = input_->points[idx].x; 00404 point.y = input_->points[idx].y; 00405 point.z = input_->points[idx].z; 00406 point.intensity = normals_->points[idx].curvature; 00407 output.points.push_back(point); 00408 } 00409 // does not change the order 00410 output.height = input_->height; 00411 output.width = input_->width; 00412 } 00413 00415 template <typename PointInT, typename PointOutT, typename NormalT> void 00416 pcl::HarrisKeypoint3D<PointInT, PointOutT, NormalT>::responseTomasi (PointCloudOut &output) const 00417 { 00418 std::vector<int> nn_indices; 00419 std::vector<float> nn_dists; 00420 PCL_ALIGN (16) float covar [8]; 00421 Eigen::Matrix3f covariance_matrix; 00422 output.resize (input_->size ()); 00423 #if defined __GNUC__ 00424 # if __GNUC__ == 4 && __GNUC_MINOR__ > 3 00425 # pragma omp parallel for shared (output) private (covar, nn_indices, nn_dists, covariance_matrix) num_threads(threads_) 00426 # endif 00427 #endif 00428 for (int pIdx = 0; pIdx < (int) input_->size (); ++pIdx) 00429 { 00430 const PointInT& pointIn = input_->points [pIdx]; 00431 output [pIdx].intensity = 0.0; 00432 if (isFinite (pointIn)) 00433 { 00434 tree_->radiusSearch (pointIn, search_radius_, nn_indices, nn_dists); 00435 calculateNormalCovar (nn_indices, covar); 00436 float trace = covar [0] + covar [5] + covar [7]; 00437 if (trace != 0) 00438 { 00439 covariance_matrix.coeffRef (0) = covar [0]; 00440 covariance_matrix.coeffRef (1) = covariance_matrix.coeffRef (3) = covar [1]; 00441 covariance_matrix.coeffRef (2) = covariance_matrix.coeffRef (6) = covar [2]; 00442 covariance_matrix.coeffRef (4) = covar [5]; 00443 covariance_matrix.coeffRef (5) = covariance_matrix.coeffRef (7) = covar [6]; 00444 covariance_matrix.coeffRef (8) = covar [7]; 00445 00446 EIGEN_ALIGN16 Eigen::Vector3f eigen_values; 00447 pcl::eigen33(covariance_matrix, eigen_values); 00448 output [pIdx].intensity = eigen_values[0]; 00449 } 00450 } 00451 output [pIdx].x = pointIn.x; 00452 output [pIdx].y = pointIn.y; 00453 output [pIdx].z = pointIn.z; 00454 } 00455 output.height = input_->height; 00456 output.width = input_->width; 00457 } 00458 00460 template <typename PointInT, typename PointOutT, typename NormalT> void 00461 pcl::HarrisKeypoint3D<PointInT, PointOutT, NormalT>::refineCorners (PointCloudOut &corners) const 00462 { 00463 std::vector<int> nn_indices; 00464 std::vector<float> nn_dists; 00465 00466 Eigen::Matrix3f nnT; 00467 Eigen::Matrix3f NNT; 00468 Eigen::Matrix3f NNTInv; 00469 Eigen::Vector3f NNTp; 00470 float diff; 00471 const unsigned max_iterations = 10; 00472 #if defined __GNUC__ 00473 # if __GNUC__ == 4 && __GNUC_MINOR__ > 3 00474 # pragma omp parallel for shared (corners) private (nnT, NNT, NNTInv, NNTp, diff, nn_indices, nn_dists) num_threads(threads_) 00475 # endif 00476 #endif 00477 //for (typename PointCloudOut::iterator cornerIt = corners.begin(); cornerIt != corners.end(); ++cornerIt) 00478 for (int cIdx = 0; cIdx < (int) corners.size (); ++cIdx) 00479 { 00480 unsigned iterations = 0; 00481 do { 00482 NNT.setZero(); 00483 NNTp.setZero(); 00484 PointInT corner; 00485 corner.x = corners[cIdx].x; 00486 corner.y = corners[cIdx].y; 00487 corner.z = corners[cIdx].z; 00488 tree_->radiusSearch (corner, search_radius_, nn_indices, nn_dists); 00489 for (std::vector<int>::const_iterator iIt = nn_indices.begin(); iIt != nn_indices.end(); ++iIt) 00490 { 00491 if (!pcl_isfinite (normals_->points[*iIt].normal_x)) 00492 continue; 00493 00494 nnT = normals_->points[*iIt].getNormalVector3fMap () * normals_->points[*iIt].getNormalVector3fMap ().transpose(); 00495 NNT += nnT; 00496 NNTp += nnT * surface_->points[*iIt].getVector3fMap (); 00497 } 00498 if (invert3x3SymMatrix (NNT, NNTInv) != 0) 00499 corners[cIdx].getVector3fMap () = NNTInv * NNTp; 00500 00501 diff = (corners[cIdx].getVector3fMap () - corner.getVector3fMap()).squaredNorm (); 00502 // diff = (cornerIt->x - corner.x) * (cornerIt->x - corner.x) + 00503 // (cornerIt->y - corner.y) * (cornerIt->y - corner.y) + 00504 // (cornerIt->z - corner.z) * (cornerIt->z - corner.z); 00505 } while (diff > 1e-6 && ++iterations < max_iterations); 00506 } 00507 } 00508 00509 #define PCL_INSTANTIATE_HarrisKeypoint3D(T,U,N) template class PCL_EXPORTS pcl::HarrisKeypoint3D<T,U,N>; 00510 #endif // #ifndef PCL_HARRIS_KEYPOINT_3D_IMPL_H_ 00511
1.8.0