Point Cloud Library (PCL)  1.4.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
harris_keypoint3D.hpp
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines