finddd_alg.cpp
Go to the documentation of this file.
00001 #include "finddd_alg.h"
00002 
00003 #define PI 3.1415926535
00004 
00005 //helper fun
00006 inline 
00007 std::vector<float> get_bin_float_empty(std::vector<float> &bin_centers_phi, std::vector<float> &bin_centers_theta)
00008 {
00009   int nb_phi=bin_centers_phi.size();
00010   std::vector<float> val_bins;
00011   val_bins.resize(nb_phi,0);
00012   return val_bins;
00013 }
00014 
00015 inline 
00016 std::vector<float> get_bin_float_interp_xyz(float x, float y, float z, std::vector<float> &bin_centers_x, std::vector<float> &bin_centers_y, std::vector<float> &bin_centers_z, float radius_inf)
00017 {
00018   int nb_bins=bin_centers_x.size();
00019   std::vector<float> val_bins;
00020   val_bins.resize(nb_bins,0);
00021 
00022   //radius_inf now determined from loaded centroids
00023   //float radius_inf = 0.4; //0.39 is dist among bins in 54 bin case.
00024 
00025   for(int ith=0; ith<nb_bins; ith++)
00026   {
00027     float dx=(x-bin_centers_x[ith]);
00028     float dy=(y-bin_centers_y[ith]);
00029     float dz=(z-bin_centers_z[ith]);
00030     float dist = sqrt(dx*dx+dy*dy+dz*dz);
00031     float vote = std::max(1-dist/radius_inf, (float)0.0);
00032     //From D Lowe, IJCV 04: Therefore, trilinear interpolation is used to
00033     //distribute the value of each gradient sample into adjacent histogram
00034     //bins. In other words, each entry into a bin is multiplied by a weight
00035     //of 1 − d for each dimension, where d is the distance of the sample
00036     //from the central value of the bin as measured in units of the
00037     //histogram bin spacing.
00038     
00039     val_bins[ith] = vote;
00040   }
00041   return val_bins;
00042 }
00043 
00044 inline 
00045 std::vector<float> get_bin_float_xyz(float x, float y, float z, std::vector<float> &bin_centers_x, std::vector<float> &bin_centers_y, std::vector<float> &bin_centers_z)
00046 {
00047   int nb_bins=bin_centers_x.size();
00048   std::vector<float> val_bins;
00049   val_bins.resize(nb_bins,0);
00050 
00051   int best_match=0;
00052   float dist_best_match=999999999999;
00053 
00054   for(int ith=0; ith<nb_bins; ith++)
00055   {
00056     float dx=(x-bin_centers_x[ith]);
00057     float dy=(y-bin_centers_y[ith]);
00058     float dz=(z-bin_centers_z[ith]);
00059     float dist = sqrt(dx*dx+dy*dy+dz*dz);
00060     if(dist < dist_best_match)
00061     {
00062       best_match = ith;
00063       dist_best_match = dist;
00064     }
00065   }
00066   val_bins[best_match] = 1;
00067 
00068   return val_bins;
00069 }
00070 
00071 void compute_normals_integral(pcl::PointCloud<pcl::Normal> &pcl_normals, pcl::PointCloud<pcl::PointXYZ>& cloud)
00072 {
00073   //#include <pcl/features/integral_image_normal.h>
00074   //compute normal
00075   pcl::IntegralImageNormalEstimation<pcl::PointXYZ, pcl::Normal> normal_estimator;
00076   normal_estimator.setNormalEstimationMethod (normal_estimator.AVERAGE_3D_GRADIENT);
00077   normal_estimator.setMaxDepthChangeFactor(0.02f);
00078   normal_estimator.setNormalSmoothingSize(10.0f);
00079   normal_estimator.setInputCloud(boost::make_shared<pcl::PointCloud<pcl::PointXYZ> > (cloud));
00080   normal_estimator.compute (pcl_normals);
00081   //pcl::io::savePCDFileASCII("/tmp/cloud_pointnormals.pcd", pcl_normals);
00082 }
00083 
00084 void compute_normals(pcl::PointCloud<pcl::Normal> &pcl_normals, pcl::PointCloud<pcl::PointXYZ>& cloud)
00085 {
00086   //compute normal
00087   pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normal_estimator;
00088   normal_estimator.setInputCloud(boost::make_shared<pcl::PointCloud<pcl::PointXYZ> > (cloud));
00089   normal_estimator.setKSearch (400);
00090   pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ> ());
00091   //pcl::KdTreeFLANN<pcl::PointXYZ>::Ptr tree = boost::make_shared<pcl::KdTreeFLANN<pcl::PointXYZ> > ();
00092   normal_estimator.setSearchMethod (tree);
00093   normal_estimator.compute (pcl_normals);
00094 }
00095 
00096 class IIf
00097 {
00098 public:
00099   std::vector<float*> ii_;
00100   unsigned int bins_;
00101   unsigned int width_;
00102   unsigned int height_;
00103 
00104   IIf(unsigned int bins, unsigned int width, unsigned int height):bins_(bins),width_(width),height_(height){
00105     ii_.resize(bins);
00106     for(unsigned int i=0;i<bins;i++)
00107       ii_[i]=new float[width*height];
00108   }
00109   ~IIf(){
00110     for(unsigned int i=0;i<this->bins_;i++)
00111       delete [] ii_[i];
00112   }
00113   void construct(std::vector<std::vector<float> > &im){
00114     //0,0
00115     unsigned int u=0;
00116     unsigned int v=0;
00117     for(unsigned int b=0;b<this->bins_;b++)
00118     {
00119       //printf("%d %d %d\n",u,v,b);fflush(0);
00120       ii_[b][this->width_*v+u] = im[this->width_*v+u][b];
00121     }
00122 
00123     //n,0
00124     v=0;
00125     for(u=1;u<this->width_;u++)
00126     {
00127       for(unsigned int b=0;b<this->bins_;b++)
00128       {
00129         //printf("%d %d %d\n",u,v,b);fflush(0);
00130         ii_[b][this->width_*v+u] =                   \
00131           ii_[b][this->width_*v+(u-1)] +             \
00132           im[this->width_*v+u][b];
00133         //printf("%d ",im[this->width_*v+u]);
00134       }
00135     }
00136     //printf("0,n\n");fflush(0);
00137     //0,n
00138     u=0;
00139     for(v=1;v<this->height_;v++)
00140     {
00141       for(unsigned int b=0;b<this->bins_;b++)
00142       {
00143         //printf("%d %d %d\n",u,v,b);fflush(0);
00144         ii_[b][this->width_*v+u] =                   \
00145           ii_[b][this->width_*(v-1)+u] +             \
00146           im[this->width_*v+u][b];
00147         //printf("%d ",im[this->width_*v+u]);
00148       }
00149     }
00150     //n,n
00151     for(v=1;v<this->height_;v++)
00152     {
00153       for(u=1;u<this->width_;u++)
00154       {
00155         for(unsigned int b=0;b<this->bins_;b++)
00156         {
00157           //printf("%d %d %d\n",u,v,b);fflush(0);
00158           ii_[b][this->width_*v+u] =                 \
00159             ii_[b][this->width_*(v-1)+u] +           \
00160             ii_[b][this->width_*v+(u-1)] -           \
00161             ii_[b][this->width_*(v-1)+(u-1)] +       \
00162             im[this->width_*v+u][b];
00163       
00164           //printf("%d ",im[this->width_*v+u]);
00165         }
00166       }
00167     }
00168     // FILE *pf=fopen("/tmp/aaaa.txt","w");
00169     // for(unsigned int b=0;b<this->bins_;b++)
00170     // {
00171     //   for(v=0;v<this->height_;v++)
00172     //   {
00173     //  for(u=0;u<this->width_;u++)
00174     //  {
00175     //    fprintf(pf,"%f ",ii_[b][this->width_*v+u]);
00176     //  }
00177     //  fprintf(pf,"\n");
00178     //   }
00179     // }
00180     // fclose(pf);
00181   }
00182   std::vector<float> get_sub_rect(unsigned int tu, unsigned int tv, unsigned int bu, unsigned int bv)
00183   {
00184     std::vector<float> ret(this->bins_);
00185     for(unsigned int b=0;b<this->bins_;b++)
00186     {
00187       ret[b] = ii_[b][this->width_*tv+tu] + ii_[b][this->width_*bv+bu] - ii_[b][this->width_*tv+bu] - ii_[b][this->width_*bv+tu];
00188       //ROS_INFO("(%i) %f + %f - %f - %f = %f", b, ii_[b][this->width_*tv+tu], ii_[b][this->width_*bv+bu], ii_[b][this->width_*tv+bu], ii_[b][this->width_*bv+tu], ret[b]);
00189       if(ret[b]<0){
00190         //ROS_ERROR("wtfwtf %f\n", ret[b]);
00191         ret[b]=0;
00192       }
00193     }
00194 
00195     return ret;
00196   }
00197 };
00198 
00200 
00201 
00202 FindddAlgorithm::FindddAlgorithm(void)
00203 {
00204   //TODO check for new parameters!!!
00205   //TODO add the list of bin centers
00206   //TODO remove useless parameters
00207 
00208   //default values
00209   this->desc_num_side_spatial_bins_ = 1;
00210   this->desc_patch_radius_=15;  
00211   
00212   //patch radius
00213   this->set_desc_patch_radius(15);
00214 
00215   //Spatial bins (side)
00216   this->set_num_side_spatial_bins(1);
00217 
00218   //Sample each (num) pixels
00219   this->sample_each_ = 1;
00220   this->desc_compute_positionsX_.clear();
00221   this->desc_compute_positionsY_.clear();
00222   //this->centroids_file_ = "conf/xyz_centers13.txt";
00223   //this->update_centroids();
00224   this->set_positions_file("");
00225 }
00226 
00227 FindddAlgorithm::~FindddAlgorithm(void)
00228 {
00229 }
00230 
00231 void FindddAlgorithm::config_update(Config& new_cfg, uint32_t level)
00232 {
00233   this->lock();
00234 
00235   //TODO check what parameters need to be here
00236   if(this->config_.num_spatial_bins != new_cfg.num_spatial_bins)
00237   {
00238     this->set_num_side_spatial_bins(new_cfg.num_spatial_bins);
00239   }
00240   if(this->config_.desc_patch_radius != new_cfg.desc_patch_radius)
00241   {
00242     this->set_desc_patch_radius(new_cfg.desc_patch_radius);
00243   }
00244   if(this->config_.sample_each != new_cfg.sample_each)
00245   {
00246     this->set_sample_each(new_cfg.sample_each);
00247   }
00248   if(this->config_.centroids_file.compare(new_cfg.centroids_file)!=0)
00249   {
00250     this->set_centroids_file(new_cfg.centroids_file);
00251     this->update_centroids();
00252   }
00253   if(this->config_.positions_file.compare(new_cfg.positions_file)!=0)
00254   {
00255     this->set_positions_file(new_cfg.positions_file);
00256   }
00257   if(this->config_.normalize_desc != new_cfg.normalize_desc) // * 0 - No normalization
00258   {                                                           // * 1 - L1
00259     this->normalize_desc_ = new_cfg.normalize_desc;           // * 2 - L2
00260   }                                                           // * 3 - sqrt + L2
00261   if(this->config_.use_soft_voting != new_cfg.use_soft_voting)
00262   {
00263     this->use_soft_voting_ = new_cfg.use_soft_voting;
00264   }
00265 
00266   // save the current configuration
00267   this->config_=new_cfg;
00268   
00269   this->unlock();
00270 }
00271 
00272 // FindddAlgorithm Public API
00273 
00274 void FindddAlgorithm::compute_ndescs_integral_spatial_interpolation(pcl::PointCloud<pcl::PointXYZ>& cloud, iri_perception_msgs::DescriptorSet &descriptor_set)
00275 {
00276 
00277   clock_t start=clock();
00278   ROS_INFO("II with interpolation method.\n");
00279 
00280   ROS_INFO("PointCloud received");
00281 
00282   //compute normal
00283   pcl::PointCloud<pcl::Normal> pcl_normals; 
00284   compute_normals_integral(pcl_normals, cloud);
00285   //save normals file
00286   //pcl::PointCloud<pcl::PointNormal> pcl_pointnormals;
00287   //pcl::concatenateFields(cloud, pcl_normals, pcl_pointnormals); 
00288   //pcl::io::savePCDFileASCII("/tmp/cloud_pointnormals.pcd", pcl_pointnormals);
00289   
00290   //get spherical coordinates
00291   //pcl::PointCloud<pcl::PointXY> pcl_spherical; //(ab)using PointXY for holding spherical angles
00292   //compute_spherical_coords(pcl_normals, pcl_spherical);
00293 
00294   //compute descriptors
00295   descriptor_set.descriptors.clear();
00296   descriptor_set.len    = this->desc_num_total_bins_;
00297   descriptor_set.width  = pcl_normals.width;
00298   descriptor_set.height = pcl_normals.height;
00299   descriptor_set.num_orient_bins = this->orient_bin_centers_x_.size();
00300   descriptor_set.num_spa_bins = this->desc_num_side_spatial_bins_;
00301 
00302 
00303   //Compile all normal orientations and add them to the II
00304   std::vector<std::vector<float> > binned(cloud.width*cloud.height);
00305 
00306   // TODO this would be more compact with function pointers!!
00307   if(this->use_soft_voting_)
00308   {
00309     for(uint v=0;v<cloud.height;v++)
00310     {
00311       for(uint u=0;u<cloud.width;u++)
00312       {
00313         if(isnan(pcl_normals(u,v).normal_x) || isnan(pcl_normals(u,v).normal_y) || isnan(pcl_normals(u,v).normal_z))
00314           binned[u+cloud.width*v]=get_bin_float_empty(this->orient_bin_centers_x_, this->orient_bin_centers_y_); // empty vector
00315         else
00316         {
00317           binned[u+cloud.width*v] = 
00318             get_bin_float_interp_xyz(
00319               pcl_normals(u,v).normal_x, pcl_normals(u,v).normal_y, pcl_normals(u,v).normal_z, 
00320               this->orient_bin_centers_x_, this->orient_bin_centers_y_, this->orient_bin_centers_z_,
00321               this->radius_inf_);
00322         }
00323       }
00324     }
00325   }
00326   else
00327   {
00328     for(uint v=0;v<cloud.height;v++)
00329     {
00330       for(uint u=0;u<cloud.width;u++)
00331       {
00332         if(isnan(pcl_normals(u,v).normal_x) || isnan(pcl_normals(u,v).normal_y) || isnan(pcl_normals(u,v).normal_z))
00333           binned[u+cloud.width*v]=get_bin_float_empty(this->orient_bin_centers_x_, this->orient_bin_centers_y_); // empty vector
00334         else
00335         {
00336           binned[u+cloud.width*v] = 
00337             get_bin_float_xyz(
00338               pcl_normals(u,v).normal_x, pcl_normals(u,v).normal_y, pcl_normals(u,v).normal_z, 
00339               this->orient_bin_centers_x_, this->orient_bin_centers_y_, this->orient_bin_centers_z_);
00340         }
00341       }
00342     }
00343   }
00344 
00345   //Build II
00346   IIf intim(this->desc_num_orient_bins_, cloud.width, cloud.height);
00347   intim.construct(binned);
00348   ROS_INFO("built II\n");
00349 
00350   unsigned int spatial_bin_size    = (2*this->desc_patch_radius_+1)/this->desc_num_side_spatial_bins_;
00351   unsigned int spatial_bin_orients = this->desc_num_orient_bins_;
00352 
00353   //If no positions given, generate standard positions
00354   if(this->desc_compute_positionsX_.size()==0)
00355   {
00356     ROS_INFO("Generating default positions");
00357     for(unsigned int v=this->desc_patch_radius_;v<cloud.height-this->desc_patch_radius_-1;v+=this->sample_each_)
00358     {
00359       for(unsigned int u=this->desc_patch_radius_;u<cloud.width-this->desc_patch_radius_-1;u+=this->sample_each_)
00360       {      
00361         this->desc_compute_positionsX_.push_back(u);
00362         this->desc_compute_positionsY_.push_back(v);
00363       }
00364     }
00365   }
00366   
00367   //ROS_INFO("p;oasdpoasdifaposdf");
00368 
00369   //Compute descriptors
00370   for(unsigned int i_pos=0; i_pos<this->desc_compute_positionsX_.size();i_pos++)
00371   {
00372     unsigned int u=this->desc_compute_positionsX_[i_pos];
00373     unsigned int v=this->desc_compute_positionsY_[i_pos];
00374     //ROS_INFO("i_pos %d",i_pos);
00375 
00376     if( v<this->desc_patch_radius_ || 
00377         u<this->desc_patch_radius_ || 
00378         u>=cloud.width-this->desc_patch_radius_-1 || 
00379         v>=cloud.height-this->desc_patch_radius_-1)
00380     {
00381       //ROS_INFO("skipping %d %d",u,v);
00382       continue;
00383     }
00384     //ROS_INFO("computing %d %d",u,v);
00385     //ROS_INFO("Computing base descriptor");
00386     iri_perception_msgs::Descriptor desc;
00387     //insert point3D
00388     desc.point3d.x=cloud(u,v).x;
00389     desc.point3d.y=cloud(u,v).y;
00390     desc.point3d.z=cloud(u,v).z;
00391     
00392     //insert point2D
00393     desc.u=u;
00394     desc.v=v;
00395     
00396     desc.descriptor.resize(this->desc_num_total_bins_,0);
00397     float total_votes=0; // for normalization
00398     
00399     unsigned int absolute_top  = v-this->desc_patch_radius_;
00400     //int absolute_bottom = v+this->desc_patch_radius_;
00401     unsigned int absolute_left = u-this->desc_patch_radius_;
00402     //int absolute_right = u+this->desc_patch_radius_;
00403     //ROS_INFO("atop aleft %d %d",absolute_top,absolute_left);
00404     
00405     for(unsigned int k=0;k<this->desc_num_side_spatial_bins_; k++)
00406     {
00407       unsigned int bound_left  = absolute_left + k*spatial_bin_size;
00408       unsigned int bound_right = absolute_left + (k+1)*spatial_bin_size;
00409       for(unsigned int l=0; l<this->desc_num_side_spatial_bins_; l++)
00410       {
00411         unsigned int bound_top    = absolute_top + l*spatial_bin_size;
00412         unsigned int bound_bottom = absolute_top + (l+1)*spatial_bin_size;
00413 
00414         //ROS_INFO("(l,t,r,b)(%d,%d,%d,%d)",bound_left, bound_top, bound_right, bound_bottom);
00415         std::vector<float> tmp = intim.get_sub_rect(bound_left, bound_top, bound_right, bound_bottom);
00416         for(unsigned int i=0;i<spatial_bin_orients;i++)
00417         {
00418           unsigned int offset_full_rows = l*this->desc_num_side_spatial_bins_*spatial_bin_orients;
00419           unsigned int offset_this_row  = k*spatial_bin_orients;//swaped k and l, Arnau 4/4/12
00420           desc.descriptor[offset_full_rows + offset_this_row + i]=tmp[i];
00421           total_votes+=tmp[i];
00422         }
00423       }
00424     }
00425  
00426     if(this->normalize_desc_ != 0)
00427     {
00428       float sum=0;
00429       for(int iii=0; iii<desc.descriptor.size(); iii++)
00430       {
00431         //printf("%f ",desc.descriptor[iii]);
00432         if((this->normalize_desc_==1) || (this->normalize_desc_==3)) sum+=desc.descriptor[iii];
00433         else if(this->normalize_desc_==2) sum+=desc.descriptor[iii]*desc.descriptor[iii];
00434       }
00435       if(this->normalize_desc_==2) sum=sqrt(sum);
00436       for(int iii=0; iii<desc.descriptor.size(); iii++)
00437       {
00438         if((this->normalize_desc_==1) || (this->normalize_desc_==2)) desc.descriptor[iii] /= sum;
00439         else if(this->normalize_desc_==3) desc.descriptor[iii] = sqrt(desc.descriptor[iii])/sqrt(sum);
00440       }
00441       //printf("\n");
00442     }
00443     descriptor_set.descriptors.push_back(desc);
00444     descriptor_set.num++;
00445   }
00446 
00447   ROS_INFO("Computed %d descriptors, in %f s", descriptor_set.num, (clock()-start)/(float)CLOCKS_PER_SEC);
00448 }
00449 
00450 
00451 
00452 


iri_finddd
Author(s): Arnau Ramisa
autogenerated on Fri Dec 6 2013 21:09:52