Go to the documentation of this file.00001
00059
00060
00061
00062
00063
00064
00065
00066 #ifndef FEATURE_CONTAINER_H_
00067 #define FEATURE_CONTAINER_H_
00068
00069
00070 #include <pcl/kdtree/kdtree_flann.h>
00071 #include <pcl/range_image/range_image.h>
00072 #include <pcl/features/fpfh.h>
00073 #include <pcl/features/narf.h>
00074 #include <pcl/features/narf_descriptor.h>
00075 #include "pcl/keypoints/narf_keypoint.h"
00076 #include <pcl/features/range_image_border_extractor.h>
00077
00078
00079 class FeatureContainerInterface
00080 {
00081 public:
00082 virtual bool isValid () = 0;
00083 virtual void findFeatureCorrespondences (int index, std::vector<int> &correspondence_indices,
00084 std::vector<float> &distances) = 0;
00085 };
00086
00087 template <typename FeatureType>
00088 class FeatureContainer : public FeatureContainerInterface
00089 {
00090 public:
00091 typedef typename pcl::PointCloud<FeatureType>::ConstPtr FeatureCloudConstPtr;
00092
00093 #ifdef PCL_VERSION_COMPARE
00094 typedef typename pcl::search::KdTree<FeatureType> KdTree;
00095 typedef typename pcl::search::KdTree<FeatureType>::Ptr KdTreePtr;
00096 #else
00097 typedef typename pcl::KdTree<FeatureType> KdTree;
00098 typedef typename pcl::KdTree<FeatureType>::Ptr KdTreePtr;
00099 #endif
00100 typedef boost::function<int (const pcl::PointCloud<FeatureType> &, int, std::vector<int> &,
00101 std::vector<float> &)> SearchMethod;
00102
00103 FeatureContainer () : k_(0), radius_(0) {}
00104
00105 void setSourceFeature (const FeatureCloudConstPtr &source_features)
00106 {
00107 source_features_ = source_features;
00108 }
00109
00110 FeatureCloudConstPtr getSourceFeature ()
00111 {
00112 return (source_features_);
00113 }
00114
00115 void setTargetFeature (const FeatureCloudConstPtr &target_features)
00116 {
00117 target_features_ = target_features;
00118 if (tree_)
00119 {
00120 tree_->setInputCloud (target_features_);
00121 }
00122 }
00123
00124 FeatureCloudConstPtr getTargetFeature ()
00125 {
00126 return (target_features_);
00127 }
00128
00129 void setRadiusSearch (KdTreePtr tree, float r)
00130 {
00131 tree_ = tree;
00132 radius_ = r;
00133 k_ = 0;
00134 if (target_features_)
00135 {
00136 tree_->setInputCloud (target_features_);
00137 }
00138 }
00139
00140 void setKSearch (KdTreePtr tree, int k)
00141 {
00142 tree_ = tree;
00143 k_ = k;
00144 radius_ = 0.0;
00145 if (target_features_)
00146 {
00147 tree_->setInputCloud (target_features_);
00148 }
00149 }
00150
00151 virtual bool isValid ()
00152 {
00153 if (!source_features_ || !target_features_ || !tree_)
00154 {
00155 return (false);
00156 }
00157 else
00158 {
00159 return (source_features_->points.size () > 0 &&
00160 target_features_->points.size () > 0 &&
00161 (k_ > 0 || radius_ > 0.0));
00162 }
00163 }
00164
00165 virtual void findFeatureCorrespondences (int index, std::vector<int> &correspondence_indices,
00166 std::vector<float> &distances)
00167 {
00168 if (k_ > 0)
00169 {
00170 correspondence_indices.resize (k_);
00171 distances.resize (k_);
00172 tree_->nearestKSearch (*source_features_, index, k_, correspondence_indices, distances);
00173 }
00174 else
00175 {
00176 tree_->radiusSearch (*source_features_, index, radius_, correspondence_indices, distances);
00177 }
00178 }
00179
00180 private:
00181 FeatureCloudConstPtr source_features_, target_features_;
00182 KdTreePtr tree_;
00183 SearchMethod search_method_;
00184 int k_;
00185 double radius_;
00186 };
00187
00188 template <typename Point>
00189 class FeatureContainerInterface_Euclidean : public FeatureContainerInterface
00190 {
00191 protected:
00192 bool build_;
00193 float radius2_;
00194 pcl::PointCloud<Point> org_in_, org_out_;
00195 #ifdef PCL_VERSION_COMPARE
00196 boost::shared_ptr<pcl::search::KdTree<Point> > tree_;
00197 #else
00198 boost::shared_ptr<pcl::KdTree<Point> > tree_;
00199 #endif
00200 public:
00201
00202 FeatureContainerInterface_Euclidean():
00203 build_(false), radius2_(0.05)
00204 {
00205 }
00206
00207 void setSearchRadius(float v) {radius2_ = v;}
00208
00209 virtual void build(const pcl::PointCloud<Point> &src, const pcl::PointCloud<Point> &tgt) {
00210 org_in_=src;
00211 org_out_=tgt;
00212
00213 #ifdef PCL_VERSION_COMPARE
00214 tree_.reset (new pcl::search::KdTree<Point>);
00215 #else
00216 tree_.reset (new pcl::KdTreeFLANN<Point>);
00217 #endif
00218 if(org_in_.size()>0) tree_->setInputCloud(org_in_.makeShared());
00219
00220 build_ = hidden_build();
00221 }
00222
00223 virtual bool isValid () {return build_;}
00224 virtual void findFeatureCorrespondences (int index, std::vector<int> &correspondence_indices,
00225 std::vector<float> &distances) {
00226 correspondence_indices.clear();
00227 distances.clear();
00228
00229 int num_k2_=2;
00230 float border_=111;
00231
00232 std::vector<int> inds;
00233 std::vector<float> dis;
00234 tree_->radiusSearch(org_out_.points[index], radius2_, inds, dis);
00235 if(inds.size()<1)
00236 tree_->nearestKSearch(org_out_.points[index], num_k2_, inds, dis);
00237
00238 if(inds.size()<1)
00239 return;
00240 float min_dis=border_*border_;
00241 Eigen::VectorXf b = getFeatureOut(index);
00242 int mi=inds[0];
00243 for(int i=0; i<(int)inds.size(); i++) {
00244 Eigen::VectorXf a = getFeatureIn(inds[i]);
00245 if( (a-b).squaredNorm()*(a-b).squaredNorm()*(org_in_.points[inds[i]].getVector3fMap()-org_out_.points[index].getVector3fMap()).squaredNorm()<min_dis ) {
00246 min_dis = (a-b).squaredNorm()*(a-b).squaredNorm()*(org_in_.points[inds[i]].getVector3fMap()-org_out_.points[index].getVector3fMap()).squaredNorm();
00247 mi = inds[i];
00248 }
00249 }
00250 if(mi!=-1)
00251 correspondence_indices.push_back(mi);
00252
00253 for(int i=0; i<(int)correspondence_indices.size(); i++) {
00254 distances.push_back( (org_in_.points[correspondence_indices[i]].getVector3fMap()-org_out_.points[index].getVector3fMap()).squaredNorm() );
00255 }
00256 }
00257
00258 virtual Eigen::VectorXf getFeatureOut(const int)=0;
00259 virtual Eigen::VectorXf getFeatureIn(const int)=0;
00260 virtual bool hidden_build()=0;
00261 };
00262
00263 #endif