Go to the documentation of this file.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 #ifndef _SPIN_IMAGE_ESTIMATION_H_
00035 #define _SPIN_IMAGE_ESTIMATION_H_
00036 
00037 #include <iostream>
00038 #include <pcl/features/feature.h>
00039 
00040 namespace pcl
00041 {
00042   template <typename PointInT, typename PointNT, typename PointOutT>
00043   class SpinImageEstimation: public FeatureFromNormals<PointInT, PointNT, PointOutT>
00044   {
00045     public:
00046       typedef typename Feature<PointInT, PointOutT>::PointCloudOut PointCloudOut;
00047       typedef typename Feature<PointInT, PointOutT>::PointCloudIn  PointCloudIn;
00048 
00049     public:
00050       
00051       SpinImageEstimation() {};
00052 
00053       
00054       virtual ~SpinImageEstimation(){};
00055 
00056       inline bool
00057         computeAlphaBeta (const pcl::PointCloud<PointInT> &cloud, const pcl::PointCloud<PointNT> &normals,
00058                              int p_idx, int q_idx, float &alpha, float &beta)
00059       {
00060         if( p_idx == q_idx)
00061           return(false);
00062         Eigen::Vector3f delta_vector, u;
00063 
00064         
00065         delta_vector[0] = cloud.points[p_idx].x - cloud.points[q_idx].x;
00066         delta_vector[1] = cloud.points[p_idx].y - cloud.points[q_idx].y;
00067         delta_vector[2] = cloud.points[p_idx].z - cloud.points[q_idx].z;
00068 
00069         if (delta_vector.squaredNorm() == 0.0 )
00070         {
00071           ROS_ERROR ("Euclidean distance between points %d and %d is 0!", p_idx, q_idx);
00072           return (false);
00073         }
00074 
00075         
00076         u[0] = normals.points[q_idx].normal[0];
00077         u[1] = normals.points[q_idx].normal[1];
00078         u[2] = normals.points[q_idx].normal[2];
00079 
00080         
00081         beta = fabs(delta_vector.dot(u));
00082 
00083         
00084         alpha = ( ( -delta_vector ).cross( -u ) ).norm();
00085 
00086         return (true);
00087       }
00088 
00090 
00093       inline void
00094         setNrSubdivisions (int nr_subdiv)
00095       {
00096         nr_subdiv_ = nr_subdiv;
00097       }
00098 
00100 
00103       inline void
00104         getNrSubdivisions (int &nr_subdiv)
00105       {
00106         nr_subdiv = nr_subdiv_;
00107       }
00108 
00110 
00113       inline void
00114         setRadius (double radius)
00115       {
00116         radius_ = radius;
00117       }
00118 
00120 
00123       inline void
00124         getRadius (double &radius)
00125       {
00126         radius = radius_;
00127       }
00128 
00129     private:
00130 
00131       inline void
00132         computeFeature (PointCloudOut &output)
00133       {
00134         
00135         if (!this->normals_)
00136         {
00137           ROS_ERROR ("[pcl::%s::computeFeature] No input dataset containing normals was given!", getName ().c_str ());
00138           return;
00139         }
00140         if (this->normals_->points.size () != this->surface_->points.size ())
00141         {
00142           ROS_ERROR ("[pcl::%s::computeFeature] The number of points in the input dataset differs from the number of points in the dataset containing the normals!", getName ().c_str ());
00143           return;
00144         }
00145 
00146         spin_image_histogram_.setZero (nr_subdiv_ * nr_subdiv_);
00147 
00148         
00149         
00150         std::vector<int> nn_indices (this->k_);
00151         std::vector<float> nn_dists (this->k_);
00152 
00153         double step_size = radius_ / nr_subdiv_;
00154 
00155         
00156         for (size_t idx = 0; idx < this->indices_->size (); ++idx)
00157         {
00158           searchForNeighbors ((*this->indices_)[idx], this->search_parameter_, nn_indices, nn_dists);
00159 
00160           
00161           for(size_t i = 0 ; i < nn_indices.size(); i++)
00162           {
00163             if(sqrt(nn_dists[i]) > radius_)
00164               continue;
00165             else
00166             {
00167               float alpha, beta;
00168               if( computeAlphaBeta(*this->surface_, *this->normals_, (*this->indices_)[idx], nn_indices[i], alpha, beta) )
00169               {
00170                 int alpha_idx = (int) floor( alpha / step_size);
00171                 int beta_idx = (int)  floor( beta / step_size);
00172                 spin_image_histogram_[ alpha_idx + beta_idx * nr_subdiv_] ++ ;
00173               }
00174             }
00175           }
00176 
00177           
00178           for (int d = 0; d < spin_image_histogram_.size (); ++d)
00179             output.points[idx].histogram[d] = spin_image_histogram_[d];
00180 
00181           
00182           spin_image_histogram_.setZero();
00183         }
00184 
00185       }
00186 
00187     private:
00189       double radius_;
00190 
00192       int nr_subdiv_;
00193 
00195       Eigen::VectorXf spin_image_histogram_;
00196 
00198 
00199       std::string getName () const { return ("SpinImageEstimation"); }
00200 
00201   }; 
00202 } 
00203 
00204 #endif