|
Point Cloud Library (PCL)
1.4.0
|
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 00047 template <typename PointInT, typename PointOutT> void 00048 pcl::HarrisKeypoint3D<PointInT, PointOutT>::setMethod (ResponseMethod method) 00049 { 00050 method_ = method; 00051 } 00052 00053 template <typename PointInT, typename PointOutT> void 00054 pcl::HarrisKeypoint3D<PointInT, PointOutT>::setThreshold (float threshold) 00055 { 00056 threshold_= threshold; 00057 } 00058 00059 template <typename PointInT, typename PointOutT> void 00060 pcl::HarrisKeypoint3D<PointInT, PointOutT>::setRadius (float radius) 00061 { 00062 radius_ = radius; 00063 } 00064 00065 template <typename PointInT, typename PointOutT> void 00066 pcl::HarrisKeypoint3D<PointInT, PointOutT>::setRefine (bool do_refine) 00067 { 00068 refine_ = do_refine; 00069 } 00070 00071 template <typename PointInT, typename PointOutT> void 00072 pcl::HarrisKeypoint3D<PointInT, PointOutT>::setNonMaxSupression (bool nonmax) 00073 { 00074 nonmax_ = nonmax; 00075 } 00076 00078 template <typename PointInT, typename PointOutT> void 00079 pcl::HarrisKeypoint3D<PointInT, PointOutT>::detectKeypoints (PointCloudOut &output) 00080 { 00081 typename pcl::PointCloud<PointInT>::Ptr cloud (new pcl::PointCloud<PointInT>); 00082 pcl::PassThrough<PointInT> pass_; 00083 pass_.setInputCloud (input_); 00084 pass_.filter (*cloud); 00085 // typename pcl::PointCloud<PointInT>::ConstPtr cloud; 00086 // cloud = input_; 00087 boost::shared_ptr<pcl::PointCloud<pcl::Normal> > normals (new pcl::PointCloud<Normal> ()); 00088 pcl::NormalEstimation<PointInT, pcl::Normal> normal_estimation; 00089 normal_estimation.setInputCloud(cloud); 00090 normal_estimation.setRadiusSearch(radius_); 00091 normal_estimation.compute (*normals); 00092 00093 boost::shared_ptr<pcl::PointCloud<PointOutT> > response (new pcl::PointCloud<PointOutT> ()); 00094 switch (method_) 00095 { 00096 case HARRIS: 00097 responseHarris(cloud, normals, *response); 00098 break; 00099 case NOBLE: 00100 responseNoble(cloud, normals, *response); 00101 break; 00102 case LOWE: 00103 responseLowe(cloud, normals, *response); 00104 break; 00105 case CURVATURE: 00106 responseCurvature(cloud, normals, *response); 00107 break; 00108 case TOMASI: 00109 responseTomasi(cloud, normals, *response); 00110 break; 00111 } 00112 00113 // just return the response 00114 if (!nonmax_) 00115 output = *response; 00116 else 00117 { 00118 output.points.clear (); 00119 output.points.reserve (response->points.size()); 00120 std::vector<int> nn_indices; 00121 std::vector<float> nn_dists; 00122 pcl::search::KdTree<pcl::PointXYZI> response_search; 00123 response_search.setInputCloud(response); 00124 for (size_t idx = 0; idx < response->points.size(); ++idx) 00125 { 00126 if (response->points[idx].intensity < threshold_) 00127 continue; 00128 00129 response_search.radiusSearch (idx, radius_, nn_indices, nn_dists); 00130 bool is_maxima = true; 00131 for (std::vector<int>::const_iterator iIt = nn_indices.begin(); iIt != nn_indices.end(); ++iIt) 00132 { 00133 if (response->points[idx].intensity < response->points[*iIt].intensity) 00134 { 00135 is_maxima = false; 00136 break; 00137 } 00138 } 00139 if (is_maxima) 00140 output.points.push_back (response->points[idx]); 00141 } 00142 00143 if (refine_) 00144 refineCorners (cloud, normals, output); 00145 00146 output.height = 1; 00147 output.width = output.points.size(); 00148 } 00149 } 00150 00151 #if 0 00152 template <typename PointInT, typename PointOutT> void 00153 pcl::HarrisKeypoint3D<PointInT, PointOutT>::responseHarris (typename PointCloudIn::ConstPtr input, pcl::PointCloud<Normal>::ConstPtr normals, PointCloudOut &output) const 00154 { 00155 output.points.clear (); 00156 output.points.reserve (input->points.size()); 00157 00158 std::vector<int> nn_indices; 00159 std::vector<float> nn_dists; 00160 pcl::search::KdTree<PointInT> search; 00161 search.setInputCloud(input); 00162 00163 PointOutT point; 00164 float covar[6]; 00165 for (typename PointCloudIn::const_iterator pointIt = input->begin(); pointIt != input->end(); ++pointIt) 00166 { 00167 search.radiusSearch (*pointIt, radius_, nn_indices, nn_dists); 00168 00169 covar[0] = covar[1] = covar[2] = covar[3] = covar[4] = covar[5] = 0; 00170 for (std::vector<int>::const_iterator iIt = nn_indices.begin(); iIt != nn_indices.end(); ++iIt) 00171 { 00172 covar[0] += normals->points[*iIt].normal_x * normals->points[*iIt].normal_x; 00173 covar[1] += normals->points[*iIt].normal_x * normals->points[*iIt].normal_y; 00174 covar[2] += normals->points[*iIt].normal_x * normals->points[*iIt].normal_z; 00175 covar[3] += normals->points[*iIt].normal_y * normals->points[*iIt].normal_y; 00176 covar[4] += normals->points[*iIt].normal_y * normals->points[*iIt].normal_z; 00177 covar[5] += normals->points[*iIt].normal_z * normals->points[*iIt].normal_z; 00178 } 00179 point.x = pointIt->x; 00180 point.y = pointIt->y; 00181 point.z = pointIt->z; 00182 00183 float trace = covar[0] + covar[3] + covar[5]; 00184 point.intensity = covar[0] * covar[3] * covar[5] + 2 * covar[1] * covar[2] * covar[4] - covar[2] * covar[2] * covar[3] - 00185 covar[4] * covar[4] * covar[0] - covar[1] * covar[1] * covar[5] - 0.04 * trace * trace; 00186 output.points.push_back(point); 00187 } 00188 output.height = input->height; 00189 output.width = input->width; 00190 } 00191 #else 00192 template <typename PointInT, typename PointOutT> void 00193 pcl::HarrisKeypoint3D<PointInT, PointOutT>::responseHarris (typename PointCloudIn::ConstPtr input, pcl::PointCloud<Normal>::ConstPtr normals, PointCloudOut &output) const 00194 { 00195 output.points.clear (); 00196 output.points.reserve (input->points.size()); 00197 00198 std::vector<int> nn_indices; 00199 std::vector<float> nn_dists; 00200 pcl::search::KdTree<PointInT> search; 00201 search.setInputCloud(input); 00202 00203 PointOutT point; 00204 for (typename PointCloudIn::const_iterator pointIt = input->begin(); pointIt != input->end(); ++pointIt) 00205 //for (std::vector<int>::const_iterator idxIt = indices_->begin(); idxIt != indices_->end(); ++idxIt) 00206 { 00207 search.radiusSearch (*pointIt, radius_, nn_indices, nn_dists); 00208 00209 Eigen::Matrix3f covariance_matrix; 00210 covariance_matrix.setZero(); 00211 for (std::vector<int>::const_iterator iIt = nn_indices.begin(); iIt != nn_indices.end(); ++iIt) 00212 { 00213 const Eigen::Vector3f* vec = reinterpret_cast<const Eigen::Vector3f*> (&(normals->points[*iIt].normal_x)); 00214 covariance_matrix += (*vec) * (vec->transpose()); 00215 } 00216 point.x = pointIt->x; 00217 point.y = pointIt->y; 00218 point.z = pointIt->z; 00219 point.intensity = covariance_matrix.determinant () - 0.04 * covariance_matrix.trace () * covariance_matrix.trace (); 00220 output.points.push_back(point); 00221 } 00222 output.height = input->height; 00223 output.width = input->width; 00224 } 00225 #endif 00226 00227 template <typename PointInT, typename PointOutT> void 00228 pcl::HarrisKeypoint3D<PointInT, PointOutT>::responseNoble (typename PointCloudIn::ConstPtr input, pcl::PointCloud<Normal>::ConstPtr normals, PointCloudOut &output) const 00229 { 00230 output.points.clear (); 00231 output.points.reserve (input->points.size()); 00232 00233 std::vector<int> nn_indices; 00234 std::vector<float> nn_dists; 00235 pcl::search::KdTree<PointInT> search; 00236 search.setInputCloud(input); 00237 00238 PointOutT point; 00239 for (typename PointCloudIn::const_iterator pointIt = input->begin(); pointIt != input->end(); ++pointIt) 00240 { 00241 search.radiusSearch (*pointIt, radius_, nn_indices, nn_dists); 00242 00243 Eigen::Matrix3f covariance_matrix; 00244 covariance_matrix.setZero(); 00245 for (std::vector<int>::const_iterator iIt = nn_indices.begin(); iIt != nn_indices.end(); ++iIt) 00246 { 00247 const Eigen::Vector3f* vec = reinterpret_cast<const Eigen::Vector3f*> (&(normals->points[*iIt].normal_x)); 00248 covariance_matrix += (*vec) * (vec->transpose()); 00249 } 00250 point.x = pointIt->x; 00251 point.y = pointIt->y; 00252 point.z = pointIt->z; 00253 point.intensity = covariance_matrix.determinant () / covariance_matrix.trace (); 00254 output.points.push_back(point); 00255 } 00256 output.height = input->height; 00257 output.width = input->width; 00258 } 00259 00260 template <typename PointInT, typename PointOutT> void 00261 pcl::HarrisKeypoint3D<PointInT, PointOutT>::responseLowe (typename PointCloudIn::ConstPtr input, pcl::PointCloud<Normal>::ConstPtr normals, PointCloudOut &output) const 00262 { 00263 output.points.clear (); 00264 output.points.reserve (input->points.size()); 00265 00266 std::vector<int> nn_indices; 00267 std::vector<float> nn_dists; 00268 pcl::search::KdTree<PointInT> search; 00269 search.setInputCloud(input); 00270 00271 PointOutT point; 00272 for (typename PointCloudIn::const_iterator pointIt = input->begin(); pointIt != input->end(); ++pointIt) 00273 { 00274 search.radiusSearch (*pointIt, radius_, nn_indices, nn_dists); 00275 00276 Eigen::Matrix3f covariance_matrix; 00277 covariance_matrix.setZero(); 00278 for (std::vector<int>::const_iterator iIt = nn_indices.begin(); iIt != nn_indices.end(); ++iIt) 00279 { 00280 const Eigen::Vector3f* vec = reinterpret_cast<const Eigen::Vector3f*> (&(normals->points[*iIt].normal_x)); 00281 covariance_matrix += (*vec) * (vec->transpose()); 00282 } 00283 point.x = pointIt->x; 00284 point.y = pointIt->y; 00285 point.z = pointIt->z; 00286 point.intensity = covariance_matrix.determinant () / (covariance_matrix.trace () * covariance_matrix.trace ()); 00287 output.points.push_back(point); 00288 } 00289 output.height = input->height; 00290 output.width = input->width; 00291 } 00292 00293 template <typename PointInT, typename PointOutT> void 00294 pcl::HarrisKeypoint3D<PointInT, PointOutT>::responseCurvature (typename PointCloudIn::ConstPtr input, pcl::PointCloud<Normal>::ConstPtr normals, PointCloudOut &output) const 00295 { 00296 output.points.clear (); 00297 output.points.reserve (input->points.size()); 00298 00299 PointOutT point; 00300 for (unsigned idx = 0; idx < input->points.size(); ++idx) 00301 { 00302 point.x = input->points[idx].x; 00303 point.y = input->points[idx].y; 00304 point.z = input->points[idx].z; 00305 point.intensity = (*normals)[idx].curvature; 00306 output.points.push_back(point); 00307 } 00308 // does not change the order 00309 output.height = input->height; 00310 output.width = input->width; 00311 } 00312 00313 template <typename PointInT, typename PointOutT> void 00314 pcl::HarrisKeypoint3D<PointInT, PointOutT>::responseTomasi (typename PointCloudIn::ConstPtr input, pcl::PointCloud<Normal>::ConstPtr normals, PointCloudOut &output) const 00315 { 00316 output.points.clear (); 00317 output.points.reserve (input->points.size()); 00318 00319 std::vector<int> nn_indices; 00320 std::vector<float> nn_dists; 00321 pcl::search::KdTree<PointInT> search; 00322 search.setInputCloud(input); 00323 00324 PointOutT point; 00325 for (typename PointCloudIn::const_iterator pointIt = input->begin(); pointIt != input->end(); ++pointIt) 00326 { 00327 search.radiusSearch (*pointIt, radius_, nn_indices, nn_dists); 00328 00329 Eigen::Matrix3f covariance_matrix; 00330 covariance_matrix.setZero(); 00331 for (std::vector<int>::const_iterator iIt = nn_indices.begin(); iIt != nn_indices.end(); ++iIt) 00332 { 00333 if (pcl_isnan(normals->points[*iIt].normal_x + normals->points[*iIt].normal_y + normals->points[*iIt].normal_z)) 00334 continue; 00335 const Eigen::Vector3f* vec = reinterpret_cast<const Eigen::Vector3f*> (&(normals->points[*iIt].normal_x)); 00336 covariance_matrix += (*vec) * (vec->transpose()); 00337 } 00338 point.x = pointIt->x; 00339 point.y = pointIt->y; 00340 point.z = pointIt->z; 00341 00342 EIGEN_ALIGN16 Eigen::Vector3f eigen_values; 00343 EIGEN_ALIGN16 Eigen::Matrix3f eigen_vectors; 00344 pcl::eigen33(covariance_matrix, eigen_vectors, eigen_values); 00345 point.intensity = eigen_values[0]; 00346 output.points.push_back(point); 00347 } 00348 output.height = input->height; 00349 output.width = input->width; 00350 } 00351 00352 #if 0 00353 template <typename PointInT, typename PointOutT> void 00354 pcl::HarrisKeypoint3D<PointInT, PointOutT>::refineCorners (typename PointCloudIn::ConstPtr surface, pcl::PointCloud<Normal>::ConstPtr normals, PointCloudOut &corners) const 00355 { 00356 std::vector<int> nn_indices; 00357 std::vector<float> nn_dists; 00358 pcl::search::KdTree<PointInT> search; 00359 search.setInputCloud(surface); 00360 00361 float sumSqr[15]; 00362 float diff; 00363 const unsigned max_iterations = 10; 00364 for (typename PointCloudOut::iterator cornerIt = corners.begin(); cornerIt != corners.end(); ++cornerIt) 00365 { 00366 unsigned iterations = 0; 00367 do { 00368 memset (sumSqr, 0, sizeof(float) * 15); 00369 PointInT corner; 00370 corner.x = cornerIt->x; 00371 corner.y = cornerIt->y; 00372 corner.z = cornerIt->z; 00373 search.radiusSearch (corner, radius_, nn_indices, nn_dists); 00374 for (std::vector<int>::const_iterator iIt = nn_indices.begin(); iIt != nn_indices.end(); ++iIt) 00375 { 00376 float a = normals->points[*iIt].normal_x * normals->points[*iIt].normal_x; 00377 float b = normals->points[*iIt].normal_x * normals->points[*iIt].normal_y; 00378 float c = normals->points[*iIt].normal_x * normals->points[*iIt].normal_z; 00379 float d = normals->points[*iIt].normal_y * normals->points[*iIt].normal_y; 00380 float e = normals->points[*iIt].normal_y * normals->points[*iIt].normal_z; 00381 float f = normals->points[*iIt].normal_z * normals->points[*iIt].normal_z; 00382 00383 sumSqr[0] += a; 00384 sumSqr[1] += b; 00385 sumSqr[2] += c; 00386 sumSqr[3] += d; 00387 sumSqr[4] += e; 00388 sumSqr[5] += f; 00389 sumSqr[6] += a * surface->points[*iIt].x + b * surface->points[*iIt].y + c * surface->points[*iIt].z; 00390 sumSqr[7] += b * surface->points[*iIt].x + d * surface->points[*iIt].y + e * surface->points[*iIt].z; 00391 sumSqr[8] += c * surface->points[*iIt].x + e * surface->points[*iIt].y + f * surface->points[*iIt].z; 00392 } 00393 00394 float det = invert3x3SymMatrix (sumSqr, sumSqr + 9); 00395 if (det != 0) 00396 { 00397 cornerIt->x = sumSqr[ 9] * sumSqr[6] + sumSqr[10] * sumSqr[7] + sumSqr[11] * sumSqr[8]; 00398 cornerIt->y = sumSqr[10] * sumSqr[6] + sumSqr[12] * sumSqr[7] + sumSqr[13] * sumSqr[8]; 00399 cornerIt->z = sumSqr[11] * sumSqr[6] + sumSqr[13] * sumSqr[7] + sumSqr[14] * sumSqr[8]; 00400 } 00401 diff = (cornerIt->x - corner.x) * (cornerIt->x - corner.x) + 00402 (cornerIt->y - corner.y) * (cornerIt->y - corner.y) + 00403 (cornerIt->z - corner.z) * (cornerIt->z - corner.z); 00404 } while (diff > 1e-5 && ++iterations < max_iterations); 00405 } 00406 } 00407 #else 00408 template <typename PointInT, typename PointOutT> void 00409 pcl::HarrisKeypoint3D<PointInT, PointOutT>::refineCorners (typename PointCloudIn::ConstPtr surface, pcl::PointCloud<Normal>::ConstPtr normals, PointCloudOut &corners) const 00410 { 00411 std::vector<int> nn_indices; 00412 std::vector<float> nn_dists; 00413 pcl::search::KdTree<PointInT> search; 00414 search.setInputCloud(surface); 00415 00416 Eigen::Matrix3f nnT; 00417 Eigen::Matrix3f NNT; 00418 Eigen::Vector3f NNTp; 00419 const Eigen::Vector3f* normal; 00420 const Eigen::Vector3f* point; 00421 float diff; 00422 const unsigned max_iterations = 10; 00423 for (typename PointCloudOut::iterator cornerIt = corners.begin(); cornerIt != corners.end(); ++cornerIt) 00424 { 00425 unsigned iterations = 0; 00426 do { 00427 NNT.setZero(); 00428 NNTp.setZero(); 00429 PointInT corner; 00430 corner.x = cornerIt->x; 00431 corner.y = cornerIt->y; 00432 corner.z = cornerIt->z; 00433 search.radiusSearch (corner, radius_, nn_indices, nn_dists); 00434 for (std::vector<int>::const_iterator iIt = nn_indices.begin(); iIt != nn_indices.end(); ++iIt) 00435 { 00436 normal = reinterpret_cast<const Eigen::Vector3f*> (&(normals->points[*iIt].normal_x)); 00437 point = reinterpret_cast<const Eigen::Vector3f*> (&(surface->points[*iIt].x)); 00438 nnT = (*normal) * (normal->transpose()); 00439 NNT += nnT; 00440 NNTp += nnT * (*point); 00441 } 00442 if (NNT.determinant() != 0) 00443 *(reinterpret_cast<Eigen::Vector3f*>(&(cornerIt->x))) = NNT.inverse () * NNTp; 00444 00445 diff = (cornerIt->x - corner.x) * (cornerIt->x - corner.x) + 00446 (cornerIt->y - corner.y) * (cornerIt->y - corner.y) + 00447 (cornerIt->z - corner.z) * (cornerIt->z - corner.z); 00448 } while (diff > 1e-5 && ++iterations < max_iterations); 00449 } 00450 } 00451 #endif 00452 #define PCL_INSTANTIATE_HarrisKeypoint3D(T,U) template class PCL_EXPORTS pcl::HarrisKeypoint3D<T,U>; 00453 00454 #endif // #ifndef PCL_HARRIS_KEYPOINT_3D_IMPL_H_ 00455
1.7.6.1