00001 #include "finddd_alg.h"
00002
00003 #define PI 3.1415926535
00004
00005
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
00023
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
00033
00034
00035
00036
00037
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
00074
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
00082 }
00083
00084 void compute_normals(pcl::PointCloud<pcl::Normal> &pcl_normals, pcl::PointCloud<pcl::PointXYZ>& cloud)
00085 {
00086
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
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
00115 unsigned int u=0;
00116 unsigned int v=0;
00117 for(unsigned int b=0;b<this->bins_;b++)
00118 {
00119
00120 ii_[b][this->width_*v+u] = im[this->width_*v+u][b];
00121 }
00122
00123
00124 v=0;
00125 for(u=1;u<this->width_;u++)
00126 {
00127 for(unsigned int b=0;b<this->bins_;b++)
00128 {
00129
00130 ii_[b][this->width_*v+u] = \
00131 ii_[b][this->width_*v+(u-1)] + \
00132 im[this->width_*v+u][b];
00133
00134 }
00135 }
00136
00137
00138 u=0;
00139 for(v=1;v<this->height_;v++)
00140 {
00141 for(unsigned int b=0;b<this->bins_;b++)
00142 {
00143
00144 ii_[b][this->width_*v+u] = \
00145 ii_[b][this->width_*(v-1)+u] + \
00146 im[this->width_*v+u][b];
00147
00148 }
00149 }
00150
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
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
00165 }
00166 }
00167 }
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
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
00189 if(ret[b]<0){
00190
00191 ret[b]=0;
00192 }
00193 }
00194
00195 return ret;
00196 }
00197 };
00198
00200
00201
00202 FindddAlgorithm::FindddAlgorithm(void)
00203 {
00204
00205
00206
00207
00208
00209 this->desc_num_side_spatial_bins_ = 1;
00210 this->desc_patch_radius_=15;
00211
00212
00213 this->set_desc_patch_radius(15);
00214
00215
00216 this->set_num_side_spatial_bins(1);
00217
00218
00219 this->sample_each_ = 1;
00220 this->desc_compute_positionsX_.clear();
00221 this->desc_compute_positionsY_.clear();
00222
00223
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
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)
00258 {
00259 this->normalize_desc_ = new_cfg.normalize_desc;
00260 }
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
00267 this->config_=new_cfg;
00268
00269 this->unlock();
00270 }
00271
00272
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
00283 pcl::PointCloud<pcl::Normal> pcl_normals;
00284 compute_normals_integral(pcl_normals, cloud);
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
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
00304 std::vector<std::vector<float> > binned(cloud.width*cloud.height);
00305
00306
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_);
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_);
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
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
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
00368
00369
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
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
00382 continue;
00383 }
00384
00385
00386 iri_perception_msgs::Descriptor desc;
00387
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
00393 desc.u=u;
00394 desc.v=v;
00395
00396 desc.descriptor.resize(this->desc_num_total_bins_,0);
00397 float total_votes=0;
00398
00399 unsigned int absolute_top = v-this->desc_patch_radius_;
00400
00401 unsigned int absolute_left = u-this->desc_patch_radius_;
00402
00403
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
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;
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
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
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