00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 #ifndef PCL_HARRIS_KEYPOINT_2D_IMPL_H_
00041 #define PCL_HARRIS_KEYPOINT_2D_IMPL_H_
00042 
00044 template <typename PointInT, typename PointOutT, typename IntensityT> void
00045 pcl::HarrisKeypoint2D<PointInT, PointOutT, IntensityT>::setMethod (ResponseMethod method)
00046 {
00047   method_ = method;
00048 }
00049 
00051 template <typename PointInT, typename PointOutT, typename IntensityT> void
00052 pcl::HarrisKeypoint2D<PointInT, PointOutT, IntensityT>::setThreshold (float threshold)
00053 {
00054   threshold_= threshold;
00055 }
00056 
00058 template <typename PointInT, typename PointOutT, typename IntensityT> void
00059 pcl::HarrisKeypoint2D<PointInT, PointOutT, IntensityT>::setRefine (bool do_refine)
00060 {
00061   refine_ = do_refine;
00062 }
00063 
00065 template <typename PointInT, typename PointOutT, typename IntensityT> void
00066 pcl::HarrisKeypoint2D<PointInT, PointOutT, IntensityT>::setNonMaxSupression (bool nonmax)
00067 {
00068   nonmax_ = nonmax;
00069 }
00070 
00072 template <typename PointInT, typename PointOutT, typename IntensityT> void
00073 pcl::HarrisKeypoint2D<PointInT, PointOutT, IntensityT>::setWindowWidth (int window_width)
00074 {
00075   window_width_= window_width;
00076 }
00077 
00079 template <typename PointInT, typename PointOutT, typename IntensityT> void
00080 pcl::HarrisKeypoint2D<PointInT, PointOutT, IntensityT>::setWindowHeight (int window_height)
00081 {
00082   window_height_= window_height;
00083 }
00084 
00086 template <typename PointInT, typename PointOutT, typename IntensityT> void
00087 pcl::HarrisKeypoint2D<PointInT, PointOutT, IntensityT>::setSkippedPixels (int skipped_pixels)
00088 {
00089   skipped_pixels_= skipped_pixels;
00090 }
00091 
00093 template <typename PointInT, typename PointOutT, typename IntensityT> void
00094 pcl::HarrisKeypoint2D<PointInT, PointOutT, IntensityT>::setMinimalDistance (int min_distance)
00095 {
00096   min_distance_ = min_distance;
00097 }
00098 
00100 template <typename PointInT, typename PointOutT, typename IntensityT> void
00101 pcl::HarrisKeypoint2D<PointInT, PointOutT, IntensityT>::computeSecondMomentMatrix (std::size_t index, float* coefficients) const
00102 {
00103   static const int width = static_cast<int> (input_->width);
00104   static const int height = static_cast<int> (input_->height);
00105   
00106   int x = static_cast<int> (index % input_->width);
00107   int y = static_cast<int> (index / input_->width);
00108   unsigned count = 0;
00109   
00110   
00111   memset (coefficients, 0, sizeof (float) * 3);
00112 
00113   int endx = std::min (width, x + half_window_width_);
00114   int endy = std::min (height, y + half_window_height_);
00115   for (int xx = std::max (0, x - half_window_width_); xx < endx; ++xx)
00116     for (int yy = std::max (0, y - half_window_height_); yy < endy; ++yy)
00117     {
00118       const float& ix = derivatives_rows_ (xx,yy);
00119       const float& iy = derivatives_cols_ (xx,yy);
00120       coefficients[0]+= ix * ix;
00121       coefficients[1]+= ix * iy;
00122       coefficients[2]+= iy * iy;
00123     }
00124 }
00125 
00127 template <typename PointInT, typename PointOutT, typename IntensityT> bool
00128 pcl::HarrisKeypoint2D<PointInT, PointOutT, IntensityT>::initCompute ()
00129 {
00130   if (!pcl::Keypoint<PointInT, PointOutT>::initCompute ())
00131   {
00132     PCL_ERROR ("[pcl::%s::initCompute] init failed.!\n", name_.c_str ());
00133     return (false);
00134   }
00135 
00136   if (!input_->isOrganized ())
00137   {    
00138     PCL_ERROR ("[pcl::%s::initCompute] %s doesn't support non organized clouds!\n", name_.c_str ());
00139     return (false);
00140   }
00141   
00142   if (indices_->size () != input_->size ())
00143   {
00144     PCL_ERROR ("[pcl::%s::initCompute] %s doesn't support setting indices!\n", name_.c_str ());
00145     return (false);
00146   }
00147   
00148   if ((window_height_%2) == 0)
00149   {
00150     PCL_ERROR ("[pcl::%s::initCompute] Window height must be odd!\n", name_.c_str ());
00151     return (false);
00152   }
00153 
00154   if ((window_width_%2) == 0)
00155   {
00156     PCL_ERROR ("[pcl::%s::initCompute] Window width must be odd!\n", name_.c_str ());
00157     return (false);
00158   }
00159 
00160   if (window_height_ < 3 || window_width_ < 3)
00161   {
00162     PCL_ERROR ("[pcl::%s::initCompute] Window size must be >= 3x3!\n", name_.c_str ());
00163     return (false);
00164   }
00165   
00166   half_window_width_ = window_width_ / 2;
00167   half_window_height_ = window_height_ / 2;
00168 
00169   return (true);
00170 }
00171 
00173 template <typename PointInT, typename PointOutT, typename IntensityT> void
00174 pcl::HarrisKeypoint2D<PointInT, PointOutT, IntensityT>::detectKeypoints (PointCloudOut &output)
00175 {
00176   derivatives_cols_.resize (input_->width, input_->height);
00177   derivatives_rows_.resize (input_->width, input_->height);
00178   
00180   int w = static_cast<int> (input_->width) - 1;
00181   int h = static_cast<int> (input_->height) - 1;
00182   
00183   
00184   derivatives_cols_(0,0) = (intensity_ ((*input_) (0,1)) - intensity_ ((*input_) (0,0))) * 0.5;
00185   derivatives_rows_(0,0) = (intensity_ ((*input_) (1,0)) - intensity_ ((*input_) (0,0))) * 0.5;
00186 
00187 
00188 
00189 
00190 
00191   for(int i = 1; i < w; ++i)
00192         {
00193                 derivatives_cols_(i,0) = (intensity_ ((*input_) (i,1)) - intensity_ ((*input_) (i,0))) * 0.5;
00194         }
00195 
00196   derivatives_rows_(w,0) = (intensity_ ((*input_) (w,0)) - intensity_ ((*input_) (w-1,0))) * 0.5;
00197   derivatives_cols_(w,0) = (intensity_ ((*input_) (w,1)) - intensity_ ((*input_) (w,0))) * 0.5;
00198 
00199 
00200 
00201 
00202 
00203   for(int j = 1; j < h; ++j)
00204   {
00205     
00206                 derivatives_rows_(0,j) = (intensity_ ((*input_) (1,j)) - intensity_ ((*input_) (0,j))) * 0.5;
00207     for(int i = 1; i < w; ++i)
00208     {
00209       
00210       derivatives_rows_(i,j) = (intensity_ ((*input_) (i+1,j)) - intensity_ ((*input_) (i-1,j))) * 0.5;
00211 
00212       
00213       derivatives_cols_(i,j) = (intensity_ ((*input_) (i,j+1)) - intensity_ ((*input_) (i,j-1))) * 0.5;
00214     }
00215     
00216     derivatives_rows_(w,j) = (intensity_ ((*input_) (w,j)) - intensity_ ((*input_) (w-1,j))) * 0.5;
00217   }
00218 
00219   
00220   derivatives_cols_(0,h) = (intensity_ ((*input_) (0,h)) - intensity_ ((*input_) (0,h-1))) * 0.5;
00221   derivatives_rows_(0,h) = (intensity_ ((*input_) (1,h)) - intensity_ ((*input_) (0,h))) * 0.5;
00222 
00223 
00224 
00225 
00226 
00227   for(int i = 1; i < w; ++i)
00228         {
00229     derivatives_cols_(i,h) = (intensity_ ((*input_) (i,h)) - intensity_ ((*input_) (i,h-1))) * 0.5;
00230         }
00231   derivatives_rows_(w,h) = (intensity_ ((*input_) (w,h)) - intensity_ ((*input_) (w-1,h))) * 0.5;
00232   derivatives_cols_(w,h) = (intensity_ ((*input_) (w,h)) - intensity_ ((*input_) (w,h-1))) * 0.5;
00233 
00234   float highest_response_;
00235   
00236   switch (method_)
00237   {
00238     case HARRIS:
00239       responseHarris(*response_, highest_response_);
00240       break;
00241     case NOBLE:
00242       responseNoble(*response_, highest_response_);
00243       break;
00244     case LOWE:
00245       responseLowe(*response_, highest_response_);
00246       break;
00247     case TOMASI:
00248       responseTomasi(*response_, highest_response_);
00249       break;
00250   }
00251   
00252   if (!nonmax_)
00253     output = *response_;
00254   else
00255   {    
00256     threshold_*= highest_response_;
00257 
00258     std::sort (indices_->begin (), indices_->end (), 
00259                boost::bind (&HarrisKeypoint2D::greaterIntensityAtIndices, this, _1, _2));
00260     
00261     output.clear ();
00262     output.reserve (response_->size());
00263     std::vector<bool> occupency_map (response_->size (), false);    
00264     int width (response_->width);
00265     int height (response_->height);
00266     const int occupency_map_size (occupency_map.size ());
00267 
00268 #ifdef _OPENMP
00269 #pragma omp parallel for shared (output, occupency_map) private (width, height) num_threads(threads_)   
00270 #endif
00271     for (int idx = 0; idx < occupency_map_size; ++idx)
00272     {
00273       if (occupency_map[idx] || response_->points [indices_->at (idx)].intensity < threshold_ || !isFinite (response_->points[idx]))
00274         continue;
00275         
00276 #ifdef _OPENMP
00277 #pragma omp critical
00278 #endif
00279       output.push_back (response_->at (indices_->at (idx)));
00280       
00281                         int u_end = std::min (width, indices_->at (idx) % width + min_distance_);
00282                         int v_end = std::min (height, indices_->at (idx) / width + min_distance_);
00283       for(int u = std::max (0, indices_->at (idx) % width - min_distance_); u < u_end; ++u)
00284         for(int v = std::max (0, indices_->at (idx) / width - min_distance_); v < v_end; ++v)
00285           occupency_map[v*input_->width+u] = true;
00286     }
00287 
00288     
00289     
00290 
00291     output.height = 1;
00292     output.width = static_cast<uint32_t> (output.size());
00293   }
00294 
00295   
00296   output.is_dense = input_->is_dense;
00297 }
00298 
00300 template <typename PointInT, typename PointOutT, typename IntensityT> void
00301 pcl::HarrisKeypoint2D<PointInT, PointOutT, IntensityT>::responseHarris (PointCloudOut &output, float& highest_response) const
00302 {
00303   PCL_ALIGN (16) float covar [3];
00304   output.clear ();
00305   output.resize (input_->size ());
00306   highest_response = - std::numeric_limits<float>::max ();
00307   const int output_size (output.size ());
00308 
00309 #ifdef _OPENMP
00310 #pragma omp parallel for shared (output, highest_response) private (covar) num_threads(threads_)
00311 #endif
00312   for (int index = 0; index < output_size; ++index)
00313   {
00314     PointOutT& out_point = output.points [index];
00315     const PointInT &in_point = (*input_).points [index];
00316     out_point.intensity = 0;
00317     out_point.x = in_point.x;
00318     out_point.y = in_point.y;
00319     out_point.z = in_point.z;
00320     if (isFinite (in_point))
00321     {
00322       computeSecondMomentMatrix (index, covar);
00323       float trace = covar [0] + covar [2];
00324       if (trace != 0.f)
00325       {
00326         float det = covar[0] * covar[2] - covar[1] * covar[1];
00327         out_point.intensity = 0.04f + det - 0.04f * trace * trace;
00328 
00329 #ifdef _OPENMP
00330 #pragma omp critical
00331 #endif
00332         highest_response =  (out_point.intensity > highest_response) ? out_point.intensity : highest_response;
00333       }
00334     }
00335   }
00336 
00337   output.height = input_->height;
00338   output.width = input_->width;
00339 }
00340 
00342 template <typename PointInT, typename PointOutT, typename IntensityT> void
00343 pcl::HarrisKeypoint2D<PointInT, PointOutT, IntensityT>::responseNoble (PointCloudOut &output, float& highest_response) const
00344 {
00345   PCL_ALIGN (16) float covar [3];
00346   output.clear ();
00347   output.resize (input_->size ());
00348   highest_response = - std::numeric_limits<float>::max ();
00349   const int output_size (output.size ());
00350 
00351 #ifdef _OPENMP
00352 #pragma omp parallel for shared (output, highest_response) private (covar) num_threads(threads_)
00353 #endif
00354   for (size_t index = 0; index < output_size; ++index)
00355   {
00356     PointOutT &out_point = output.points [index];
00357     const PointInT &in_point = input_->points [index];
00358     out_point.x = in_point.x;
00359     out_point.y = in_point.y;
00360     out_point.z = in_point.z;
00361     out_point.intensity = 0;
00362     if (isFinite (in_point))
00363     {    
00364       computeSecondMomentMatrix (index, covar);
00365       float trace = covar [0] + covar [2];
00366       if (trace != 0)
00367       {
00368         float det = covar[0] * covar[2] - covar[1] * covar[1];
00369         out_point.intensity = det / trace;
00370 
00371 #ifdef _OPENMP
00372 #pragma omp critical
00373 #endif
00374         highest_response =  (out_point.intensity > highest_response) ? out_point.intensity : highest_response;
00375       }
00376     }    
00377   }
00378   
00379   output.height = input_->height;
00380   output.width = input_->width;
00381 }
00382 
00384 template <typename PointInT, typename PointOutT, typename IntensityT> void
00385 pcl::HarrisKeypoint2D<PointInT, PointOutT, IntensityT>::responseLowe (PointCloudOut &output, float& highest_response) const
00386 {
00387   PCL_ALIGN (16) float covar [3];
00388   output.clear ();
00389   output.resize (input_->size ());
00390   highest_response = -std::numeric_limits<float>::max ();
00391   const int output_size (output.size ());
00392 
00393 #ifdef _OPENMP
00394 #pragma omp parallel for shared (output, highest_response) private (covar) num_threads(threads_)
00395 #endif
00396   for (size_t index = 0; index < output_size; ++index)      
00397   {
00398     PointOutT &out_point = output.points [index];
00399     const PointInT &in_point = input_->points [index];
00400     out_point.x = in_point.x;
00401     out_point.y = in_point.y;
00402     out_point.z = in_point.z;
00403     out_point.intensity = 0;
00404     if (isFinite (in_point))
00405     {    
00406       computeSecondMomentMatrix (index, covar);
00407       float trace = covar [0] + covar [2];
00408       if (trace != 0)
00409       {
00410         float det = covar[0] * covar[2] - covar[1] * covar[1];
00411         out_point.intensity = det / (trace * trace);
00412 
00413 #ifdef _OPENMP
00414 #pragma omp critical
00415 #endif
00416         highest_response =  (out_point.intensity > highest_response) ? out_point.intensity : highest_response;
00417       }
00418     }
00419   }
00420 
00421   output.height = input_->height;
00422   output.width = input_->width;
00423 }
00424 
00426 template <typename PointInT, typename PointOutT, typename IntensityT> void
00427 pcl::HarrisKeypoint2D<PointInT, PointOutT, IntensityT>::responseTomasi (PointCloudOut &output, float& highest_response) const
00428 {
00429   PCL_ALIGN (16) float covar [3];
00430   output.clear ();
00431   output.resize (input_->size ());
00432   highest_response = -std::numeric_limits<float>::max ();
00433   const int output_size (output.size ());
00434 
00435 #ifdef _OPENMP
00436 #pragma omp parallel for shared (output, highest_response) private (covar) num_threads(threads_)
00437 #endif
00438   for (size_t index = 0; index < output_size; ++index)
00439   {
00440     PointOutT &out_point = output.points [index];
00441     const PointInT &in_point = input_->points [index];
00442     out_point.x = in_point.x;
00443     out_point.y = in_point.y;
00444     out_point.z = in_point.z;
00445     out_point.intensity = 0;
00446     if (isFinite (in_point))
00447     {      
00448       computeSecondMomentMatrix (index, covar);
00449       
00450       out_point.intensity = ((covar[0] + covar[2] - sqrt((covar[0] - covar[2])*(covar[0] - covar[2]) + 4 * covar[1] * covar[1])) /2.0f);
00451 
00452 #ifdef _OPENMP
00453 #pragma omp critical
00454 #endif
00455       highest_response =  (out_point.intensity > highest_response) ? out_point.intensity : highest_response;
00456     }    
00457   }
00458   
00459   output.height = input_->height;
00460   output.width = input_->width;
00461 }
00462 
00463 
00464 
00465 
00466 
00467 
00468 
00469 
00470 
00471 
00472 
00473 
00474 
00475 
00476 
00477 
00478 
00479 
00480 
00481 
00482 
00483 
00484 
00485 
00486 
00487 
00488 
00489 
00490 
00491 
00492 
00493 
00494 
00495 
00496 
00497 
00498 
00499 
00500 
00501 
00502 
00503 
00504 
00505 
00506 
00507 #define PCL_INSTANTIATE_HarrisKeypoint2D(T,U,I) template class PCL_EXPORTS pcl::HarrisKeypoint2D<T,U,I>;
00508 #endif // #ifndef PCL_HARRIS_KEYPOINT_2D_IMPL_H_