00001
00002
00003 template <typename T>
00004 bool readPoints( const char *name, pcl::PointCloud<T>& cloud ){
00005 if (pcl::io::loadPCDFile (name, cloud) == -1){
00006 ROS_ERROR ("Couldn't read file %s",name);
00007 return (-1);
00008 }
00009 #ifndef QUIET
00010 ROS_INFO ("Loaded %d data points from %s with the following fields: %s", (int)(cloud.width * cloud.height), name, pcl::getFieldsList (cloud).c_str ());
00011 #endif
00012 return(1);
00013 }
00014
00015
00016
00017 template <typename T1, typename T2>
00018 void computeNormal( pcl::PointCloud<T1> input_cloud, pcl::PointCloud<T2>& output_cloud ){
00019
00020
00021
00022
00023
00024
00025
00026 pcl::NormalEstimation<T1, T2> n3d_;
00027
00028 n3d_.setRadiusSearch (normals_radius_search);
00029 n3d_.setSearchMethod ( boost::make_shared<pcl::KdTreeFLANN<T1> > () );
00030 n3d_.setInputCloud ( input_cloud.makeShared() );
00031 n3d_.compute (output_cloud);
00032
00033
00034 for ( int i=0; i< (int)input_cloud.points.size (); i++ ){
00035 output_cloud.points[ i ].x = input_cloud.points[ i ].x;
00036 output_cloud.points[ i ].y = input_cloud.points[ i ].y;
00037 output_cloud.points[ i ].z = input_cloud.points[ i ].z;
00038 output_cloud.points[ i ].rgb = input_cloud.points[ i ].rgb;
00039 }
00040 }
00041
00042
00043
00044 int getType (float min_radius, float max_radius)
00045 {
00046 if (min_radius > 0.100)
00047 return PLANE;
00048 else if (max_radius > 0.175)
00049 return CYLINDER;
00050 else if (min_radius < 0.015)
00051 return NOISE;
00052 else if (max_radius - min_radius < 0.050)
00053 return SPHERE;
00054 else
00055 return EDGE;
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 }
00067
00068
00069
00070 template <typename T>
00071 Eigen::Vector3i extractGRSDSignature21(pcl::VoxelGrid<T> grid, pcl::PointCloud<T> cloud, pcl::PointCloud<T> cloud_downsampled, std::vector< std::vector<float> > &feature, const float voxel_size, const int subdivision_size = 0, const int offset_x = 0, const int offset_y = 0, const int offset_z = 0, const bool is_normalize ){
00072 #ifndef QUIET
00073 ROS_INFO("rsd %f, normals %f, leaf %f", rsd_radius_search, normals_radius_search, voxel_size);
00074 #endif
00075 feature.resize( 0 );
00076 boost::shared_ptr< const pcl::PointCloud<T> > cloud_downsampled_ptr;
00077 cloud_downsampled_ptr.reset (new pcl::PointCloud<T> (cloud_downsampled));
00078
00079
00080 int hist_num = 1;
00081 float inverse_subdivision_size = 0;
00082 Eigen::Vector3i div_b_= Eigen::Vector3i::Zero();
00083 Eigen::Vector3i min_b_= Eigen::Vector3i::Zero();
00084 Eigen::Vector3i subdiv_b_ = Eigen::Vector3i::Zero();
00085 Eigen::Vector3i subdivb_mul_= Eigen::Vector3i::Zero();
00086 if( subdivision_size > 0 ){
00087 inverse_subdivision_size = 1.0 / subdivision_size;
00088 div_b_ = grid.getNrDivisions();
00089 min_b_ = grid.getMinBoxCoordinates();
00090 if( ( div_b_[0] <= offset_x ) || ( div_b_[1] <= offset_y ) || ( div_b_[2] <= offset_z ) ){
00091 std::cerr << "(In extractGRSDSignature21) offset values (" << offset_x << "," << offset_y << "," << offset_z << ") exceed voxel grid size (" << div_b_[0] << "," << div_b_[1] << "," << div_b_[2] << ")."<< std::endl;
00092 return Eigen::Vector3i::Zero();
00093 }
00094 subdiv_b_ = Eigen::Vector3i ( ceil( ( div_b_[0] - offset_x )*inverse_subdivision_size ), ceil( ( div_b_[1] - offset_y )*inverse_subdivision_size ), ceil( ( div_b_[2] - offset_z )*inverse_subdivision_size ) );
00095 subdivb_mul_ = Eigen::Vector3i ( 1, subdiv_b_[0], subdiv_b_[0] * subdiv_b_[1] );
00096 hist_num = subdiv_b_[0] * subdiv_b_[1] * subdiv_b_[2];
00097 }
00098 else if( subdivision_size < 0 ){
00099 std::cerr << "(In extractGRSDSignature21) Invalid subdivision size: " << subdivision_size << std::endl;
00100 return Eigen::Vector3i::Zero();
00101 }
00102
00103
00104 pcl::RSDEstimation <T, T, pcl::PrincipalRadiiRSD> rsd;
00105 rsd.setInputCloud( cloud_downsampled_ptr );
00106 boost::shared_ptr< const pcl::PointCloud<T> > cloud_ptr = cloud.makeShared();
00107 rsd.setSearchSurface( cloud_ptr );
00108 rsd.setInputNormals( cloud_ptr );
00109 #ifndef QUIET
00110 ROS_INFO("radius search: %f", std::max(rsd_radius_search, voxel_size/2 * sqrt(3)));
00111 #endif
00112 rsd.setRadiusSearch(std::max(rsd_radius_search, voxel_size/2 * sqrt(3)));
00113 boost::shared_ptr< pcl::KdTree<T> > tree2 = boost::make_shared<pcl::KdTreeFLANN<T> > ();
00114 tree2->setInputCloud (cloud.makeShared());
00115 rsd.setSearchMethod(tree2);
00116 pcl::PointCloud<pcl::PrincipalRadiiRSD> radii;
00117 t1 = my_clock();
00118 rsd.compute(radii);
00119 #ifndef QUIET
00120 ROS_INFO("RSD compute done in %f seconds.", my_clock()-t1);
00121 #endif
00122
00123
00124 t1 = my_clock();
00125 Eigen::MatrixXi relative_coordinates (3, 13);
00126
00127
00128 std::vector< Eigen::MatrixXi > transition_matrix( hist_num );
00129 for( int i=0; i<hist_num; i++ )
00130 transition_matrix[ i ] = Eigen::MatrixXi::Zero(6, 6);
00131
00132 int idx = 0;
00133
00134
00135 for( int i=-1; i<2; i++ )
00136 {
00137 for( int j=-1; j<2; j++ )
00138 {
00139 relative_coordinates( 0, idx ) = i;
00140 relative_coordinates( 1, idx ) = j;
00141 relative_coordinates( 2, idx ) = -1;
00142 idx++;
00143 }
00144 }
00145
00146 for( int i=-1; i<2; i++ )
00147 {
00148 relative_coordinates( 0, idx ) = i;
00149 relative_coordinates( 1, idx ) = -1;
00150 relative_coordinates( 2, idx ) = 0;
00151 idx++;
00152 }
00153
00154 relative_coordinates( 0, idx ) = -1;
00155 relative_coordinates( 1, idx ) = 0;
00156 relative_coordinates( 2, idx ) = 0;
00157
00158 Eigen::MatrixXi relative_coordinates_all (3, 26);
00159 relative_coordinates_all.block<3, 13>(0, 0) = relative_coordinates;
00160 relative_coordinates_all.block<3, 13>(0, 13) = -relative_coordinates;
00161
00162
00163 std::vector<int> types (radii.points.size());
00164
00165 for (size_t idx = 0; idx < radii.points.size (); ++idx)
00166 types[idx] = getType(radii.points[idx].r_min, radii.points[idx].r_max);
00167
00168 for (size_t idx = 0; idx < cloud_downsampled_ptr->points.size (); ++idx)
00169 {
00170
00171 int hist_idx;
00172 if( hist_num == 1 ) hist_idx = 0;
00173 else{
00174 const int tmp_x = floor( cloud_downsampled_ptr->points[ idx ].x/voxel_size ) - min_b_[ 0 ] - offset_x;
00175 const int tmp_y = floor( cloud_downsampled_ptr->points[ idx ].y/voxel_size ) - min_b_[ 1 ] - offset_y;
00176 const int tmp_z = floor( cloud_downsampled_ptr->points[ idx ].z/voxel_size ) - min_b_[ 2 ] - offset_z;
00177
00178
00179
00180
00181 if( ( tmp_x < 0 ) || ( tmp_y < 0 ) || ( tmp_z < 0 ) ) continue;
00182 Eigen::Vector3i ijk = Eigen::Vector3i ( floor ( tmp_x * inverse_subdivision_size), floor ( tmp_y * inverse_subdivision_size), floor ( tmp_z * inverse_subdivision_size) );
00183 hist_idx = ijk.dot (subdivb_mul_);
00184 }
00185
00186 int source_type = types[idx];
00187 std::vector<int> neighbors = grid.getNeighborCentroidIndices ( cloud_downsampled_ptr->points[idx], relative_coordinates_all);
00188 for (unsigned id_n = 0; id_n < neighbors.size(); id_n++)
00189 {
00190 int neighbor_type;
00191 if (neighbors[id_n] == -1)
00192 neighbor_type = EMPTY;
00193 else
00194 neighbor_type = types[neighbors[id_n]];
00195
00196 transition_matrix[ hist_idx ](source_type, neighbor_type)++;
00197 }
00198 }
00199 #ifndef QUIET
00200 std::cerr << "transition matrix" << std::endl << transition_matrix[0] << std::endl;
00201 ROS_INFO("GRSD compute done in %f seconds.", my_clock()-t1);
00202 #endif
00203
00204 pcl::PointCloud<pcl::GRSDSignature21> cloud_grsd;
00205 cloud_grsd.points.resize(hist_num);
00206
00207 for( int h=0; h<hist_num; h++ ){
00208 int nrf = 0;
00209 for (int i=0; i<NR_CLASS+1; i++)
00210 for (int j=i; j<NR_CLASS+1; j++)
00211
00212
00213 cloud_grsd.points[ h ].histogram[nrf++] = transition_matrix[ h ](i, j) + transition_matrix[ h ](j, i);
00214 }
00215
00216 feature.resize( hist_num );
00217 if( is_normalize ){
00218 for( int h=0; h<hist_num; h++ ){
00219 feature[ h ].resize( 20 );
00220 for( int i=0; i<20; i++)
00221 feature[ h ][ i ] = cloud_grsd.points[ h ].histogram[ i ] * NORMALIZE_GRSD;
00222 }
00223 }
00224 else{
00225 for( int h=0; h<hist_num; h++ ){
00226 feature[ h ].resize( 20 );
00227 for( int i=0; i<20; i++)
00228 feature[ h ][ i ] = cloud_grsd.points[ h ].histogram[ i ];
00229 }
00230 }
00231 return subdiv_b_;
00232 }
00233
00234 template <typename T>
00235 void extractGRSDSignature21(pcl::VoxelGrid<T> grid, pcl::PointCloud<T> cloud, pcl::PointCloud<T> cloud_downsampled, std::vector<float> &feature, const float voxel_size, const bool is_normalize ){
00236 std::vector< std::vector<float> > tmp( 1 );
00237 extractGRSDSignature21( grid, cloud, cloud_downsampled, tmp, voxel_size, 0, 0, 0, 0, is_normalize );
00238 feature = tmp[ 0 ];
00239 }
00240
00241
00242
00243 template <typename T>
00244 Eigen::Vector3i extractGRSDSignature325(pcl::VoxelGrid<T> grid, pcl::PointCloud<T> cloud, pcl::PointCloud<T> cloud_downsampled, std::vector< std::vector<float> > &feature, const float voxel_size, const int subdivision_size = 0, const int offset_x = 0, const int offset_y = 0, const int offset_z = 0, const bool is_normalize ){
00245 #ifndef QUIET
00246 ROS_INFO("rsd %f, normals %f, leaf %f", rsd_radius_search, normals_radius_search, voxel_size);
00247 #endif
00248 feature.resize( 0 );
00249 boost::shared_ptr< const pcl::PointCloud<T> > cloud_downsampled_ptr;
00250 cloud_downsampled_ptr.reset (new pcl::PointCloud<T> (cloud_downsampled));
00251 pcl::PointCloud<pcl::GRSDSignature325> cloud_grsd;
00252
00253
00254 int hist_num = 1;
00255 float inverse_subdivision_size = 0;
00256 Eigen::Vector3i div_b_= Eigen::Vector3i::Zero();
00257 Eigen::Vector3i min_b_= Eigen::Vector3i::Zero();
00258 Eigen::Vector3i subdiv_b_= Eigen::Vector3i::Zero();
00259 Eigen::Vector3i subdivb_mul_= Eigen::Vector3i::Zero();
00260 if( subdivision_size > 0 ){
00261 inverse_subdivision_size = 1.0 / subdivision_size;
00262 div_b_ = grid.getNrDivisions();
00263 min_b_ = grid.getMinBoxCoordinates();
00264 if( ( div_b_[0] <= offset_x ) || ( div_b_[1] <= offset_y ) || ( div_b_[2] <= offset_z ) ){
00265 std::cerr << "(In extractGRSDSignature325) offset values (" << offset_x << "," << offset_y << "," << offset_z << ") exceed voxel grid size (" << div_b_[0] << "," << div_b_[1] << "," << div_b_[2] << ")."<< std::endl;
00266 return Eigen::Vector3i::Zero();
00267 }
00268 subdiv_b_ = Eigen::Vector3i ( ceil( ( div_b_[0] - offset_x )*inverse_subdivision_size ), ceil( ( div_b_[1] - offset_y )*inverse_subdivision_size ), ceil( ( div_b_[2] - offset_z )*inverse_subdivision_size ) );
00269 subdivb_mul_ = Eigen::Vector3i ( 1, subdiv_b_[0], subdiv_b_[0] * subdiv_b_[1] );
00270 hist_num = subdiv_b_[0] * subdiv_b_[1] * subdiv_b_[2];
00271 }
00272 else if( subdivision_size < 0 ){
00273 std::cerr << "(In extractGRSDSignature325) Invalid subdivision size: " << subdivision_size << std::endl;
00274 return Eigen::Vector3i::Zero();
00275 }
00276 cloud_grsd.points.resize(hist_num);
00277
00278
00279 pcl::RSDEstimation <T, T, pcl::PrincipalRadiiRSD> rsd;
00280 rsd.setInputCloud( cloud_downsampled_ptr );
00281 boost::shared_ptr< const pcl::PointCloud<T> > cloud_ptr = cloud.makeShared();
00282 rsd.setSearchSurface( cloud_ptr );
00283 rsd.setInputNormals( cloud_ptr );
00284 #ifndef QUIET
00285 ROS_INFO("radius search: %f", std::max(rsd_radius_search, voxel_size/2 * sqrt(3)));
00286 #endif
00287 rsd.setRadiusSearch(std::max(rsd_radius_search, voxel_size/2 * sqrt(3)));
00288 boost::shared_ptr< pcl::KdTree<T> > tree2 = boost::make_shared<pcl::KdTreeFLANN<T> > ();
00289 tree2->setInputCloud (cloud.makeShared());
00290 rsd.setSearchMethod(tree2);
00291 pcl::PointCloud<pcl::PrincipalRadiiRSD> radii;
00292 t1 = my_clock();
00293 rsd.compute(radii);
00294 #ifndef QUIET
00295 ROS_INFO("RSD compute done in %f seconds.", my_clock()-t1);
00296 #endif
00297
00298
00299 t1 = my_clock();
00300 Eigen::MatrixXi relative_coordinates (3, 13);
00301
00302 int idx = 0;
00303
00304
00305 for( int i=-1; i<2; i++ )
00306 {
00307 for( int j=-1; j<2; j++ )
00308 {
00309 relative_coordinates( 0, idx ) = i;
00310 relative_coordinates( 1, idx ) = j;
00311 relative_coordinates( 2, idx ) = -1;
00312 idx++;
00313 }
00314 }
00315
00316 for( int i=-1; i<2; i++ )
00317 {
00318 relative_coordinates( 0, idx ) = i;
00319 relative_coordinates( 1, idx ) = -1;
00320 relative_coordinates( 2, idx ) = 0;
00321 idx++;
00322 }
00323
00324 relative_coordinates( 0, idx ) = -1;
00325 relative_coordinates( 1, idx ) = 0;
00326 relative_coordinates( 2, idx ) = 0;
00327
00328
00329 std::vector<int> types (radii.points.size());
00330
00331 for (size_t idx = 0; idx < radii.points.size (); ++idx)
00332 types[idx] = getType(radii.points[idx].r_min, radii.points[idx].r_max);
00333
00334 for (size_t idx = 0; idx < cloud_downsampled_ptr->points.size (); ++idx)
00335 {
00336
00337 int hist_idx;
00338 if( hist_num == 1 ) hist_idx = 0;
00339 else{
00340 const int tmp_x = floor( cloud_downsampled_ptr->points[ idx ].x/voxel_size ) - min_b_[ 0 ] - offset_x;
00341 const int tmp_y = floor( cloud_downsampled_ptr->points[ idx ].y/voxel_size ) - min_b_[ 1 ] - offset_y;
00342 const int tmp_z = floor( cloud_downsampled_ptr->points[ idx ].z/voxel_size ) - min_b_[ 2 ] - offset_z;
00343
00344
00345
00346
00347 if( ( tmp_x < 0 ) || ( tmp_y < 0 ) || ( tmp_z < 0 ) ) continue;
00348 Eigen::Vector3i ijk = Eigen::Vector3i ( floor ( tmp_x * inverse_subdivision_size), floor ( tmp_y * inverse_subdivision_size), floor ( tmp_z * inverse_subdivision_size) );
00349 hist_idx = ijk.dot (subdivb_mul_);
00350 }
00351
00352 int source_type = types[idx];
00353 std::vector<int> neighbors = grid.getNeighborCentroidIndices ( cloud_downsampled_ptr->points[idx], relative_coordinates);
00354 for (unsigned id_n = 0; id_n < neighbors.size(); id_n++)
00355 {
00356 int neighbor_type;
00357 if (neighbors[id_n] == -1)
00358 neighbor_type = EMPTY;
00359 else
00360 neighbor_type = types[neighbors[id_n]];
00361
00362
00363 if( neighbor_type != EMPTY )
00364 cloud_grsd.points[ hist_idx ].histogram[ source_type + neighbor_type * 5 + id_n * 25 ]++;
00365 }
00366 }
00367 #ifndef QUIET
00368 ROS_INFO("GRSD compute done in %f seconds.", my_clock()-t1);
00369 #endif
00370
00371 feature.resize( hist_num );
00372 if( is_normalize ){
00373 for( int h=0; h<hist_num; h++ ){
00374 feature[ h ].resize( GRSD_LARGE_DIM );
00375 for( int i=0; i<GRSD_LARGE_DIM; i++)
00376 feature[ h ][ i ] = cloud_grsd.points[ h ].histogram[ i ] * NORMALIZE_GRSD;
00377 }
00378 }
00379 else{
00380 for( int h=0; h<hist_num; h++ ){
00381 feature[ h ].resize( GRSD_LARGE_DIM );
00382 for( int i=0; i<GRSD_LARGE_DIM; i++)
00383 feature[ h ][ i ] = cloud_grsd.points[ h ].histogram[ i ];
00384 }
00385 }
00386 return subdiv_b_;
00387 }
00388
00389 template <typename T>
00390 void extractGRSDSignature325(pcl::VoxelGrid<T> grid, pcl::PointCloud<T> cloud, pcl::PointCloud<T> cloud_downsampled, std::vector<float> &feature, const float voxel_size, const bool is_normalize ){
00391 std::vector< std::vector<float> > tmp( 1 );
00392 extractGRSDSignature325( grid, cloud, cloud_downsampled, tmp, voxel_size, 0, 0, 0, 0, is_normalize );
00393 feature = tmp[ 0 ];
00394 }
00395
00396
00397
00398 template <typename T>
00399 Eigen::Vector3i extractPlusGRSDSignature110(pcl::VoxelGrid<T> grid, pcl::PointCloud<T> cloud, pcl::PointCloud<T> cloud_downsampled, std::vector< std::vector<float> > &feature, const float voxel_size, const int subdivision_size = 0, const int offset_x = 0, const int offset_y = 0, const int offset_z = 0, const bool is_normalize ){
00400 #ifndef QUIET
00401 ROS_INFO("rsd %f, normals %f, leaf %f", rsd_radius_search, normals_radius_search, voxel_size);
00402 #endif
00403 feature.resize( 0 );
00404 boost::shared_ptr< const pcl::PointCloud<T> > cloud_downsampled_ptr;
00405 cloud_downsampled_ptr.reset (new pcl::PointCloud<T> (cloud_downsampled));
00406
00407
00408 int hist_num = 1;
00409 float inverse_subdivision_size = 0;
00410 Eigen::Vector3i div_b_= Eigen::Vector3i::Zero();
00411 Eigen::Vector3i min_b_= Eigen::Vector3i::Zero();
00412 Eigen::Vector3i subdiv_b_= Eigen::Vector3i::Zero();
00413 Eigen::Vector3i subdivb_mul_= Eigen::Vector3i::Zero();
00414 if( subdivision_size > 0 ){
00415 inverse_subdivision_size = 1.0 / subdivision_size;
00416 div_b_ = grid.getNrDivisions();
00417 min_b_ = grid.getMinBoxCoordinates();
00418 if( ( div_b_[0] <= offset_x ) || ( div_b_[1] <= offset_y ) || ( div_b_[2] <= offset_z ) ){
00419 std::cerr << "(In extractPlusGRSDSignature110) offset values (" << offset_x << "," << offset_y << "," << offset_z << ") exceed voxel grid size (" << div_b_[0] << "," << div_b_[1] << "," << div_b_[2] << ")."<< std::endl;
00420 return Eigen::Vector3i::Zero();
00421 }
00422 subdiv_b_ = Eigen::Vector3i ( ceil( ( div_b_[0] - offset_x )*inverse_subdivision_size ), ceil( ( div_b_[1] - offset_y )*inverse_subdivision_size ), ceil( ( div_b_[2] - offset_z )*inverse_subdivision_size ) );
00423 subdivb_mul_ = Eigen::Vector3i ( 1, subdiv_b_[0], subdiv_b_[0] * subdiv_b_[1] );
00424 hist_num = subdiv_b_[0] * subdiv_b_[1] * subdiv_b_[2];
00425 }
00426 else if( subdivision_size < 0 ){
00427 std::cerr << "(In extractPlusGRSDSignature110) Invalid subdivision size: " << subdivision_size << std::endl;
00428 return Eigen::Vector3i::Zero();
00429 }
00430
00431
00432 pcl::RSDEstimation <T, T, pcl::PrincipalRadiiRSD> rsd;
00433 rsd.setInputCloud( cloud_downsampled_ptr );
00434 boost::shared_ptr< const pcl::PointCloud<T> > cloud_ptr = cloud.makeShared();
00435 rsd.setSearchSurface( cloud_ptr );
00436 rsd.setInputNormals( cloud_ptr );
00437 #ifndef QUIET
00438 ROS_INFO("radius search: %f", std::max(rsd_radius_search, voxel_size/2 * sqrt(3)));
00439 #endif
00440 rsd.setRadiusSearch(std::max(rsd_radius_search, voxel_size/2 * sqrt(3)));
00441 boost::shared_ptr< pcl::KdTree<T> > tree2 = boost::make_shared<pcl::KdTreeFLANN<T> > ();
00442 tree2->setInputCloud (cloud.makeShared());
00443 rsd.setSearchMethod(tree2);
00444 pcl::PointCloud<pcl::PrincipalRadiiRSD> radii;
00445 t1 = my_clock();
00446 rsd.compute(radii);
00447 #ifndef QUIET
00448 ROS_INFO("RSD compute done in %f seconds.", my_clock()-t1);
00449 pcl::io::savePCDFile ("hoge.pcd", cloud_downsampled, false);
00450 #endif
00451
00452
00453 t1 = my_clock();
00454 Eigen::MatrixXi relative_coordinates (3, 13);
00455
00456 int idx = 0;
00457
00458
00459 for( int i=-1; i<2; i++ )
00460 {
00461 for( int j=-1; j<2; j++ )
00462 {
00463 relative_coordinates( 0, idx ) = i;
00464 relative_coordinates( 1, idx ) = j;
00465 relative_coordinates( 2, idx ) = -1;
00466 idx++;
00467 }
00468 }
00469
00470 for( int i=-1; i<2; i++ )
00471 {
00472 relative_coordinates( 0, idx ) = i;
00473 relative_coordinates( 1, idx ) = -1;
00474 relative_coordinates( 2, idx ) = 0;
00475 idx++;
00476 }
00477
00478 relative_coordinates( 0, idx ) = -1;
00479 relative_coordinates( 1, idx ) = 0;
00480 relative_coordinates( 2, idx ) = 0;
00481
00482 Eigen::MatrixXi relative_coordinates_all (3, 26);
00483 relative_coordinates_all.block<3, 13>(0, 0) = relative_coordinates;
00484 relative_coordinates_all.block<3, 13>(0, 13) = -relative_coordinates;
00485
00486
00487 std::vector<int> types (radii.points.size());
00488
00489 for (size_t idx = 0; idx < radii.points.size (); ++idx)
00490 types[idx] = getType(radii.points[idx].r_min, radii.points[idx].r_max);
00491
00492
00493 for (size_t idx = 0; idx < cloud_downsampled_ptr->points.size (); ++idx)
00494 cloud_downsampled.points[idx].getNormalVector3fMap ().normalize ();
00495
00496
00497 std::vector<Eigen::MatrixXi> transition_matrix_list (hist_num * NR_DIV, Eigen::MatrixXi::Zero (NR_CLASS, NR_CLASS));
00498 std::vector<Eigen::VectorXi> transitions_to_empty( hist_num, Eigen::VectorXi::Zero (NR_CLASS));
00499
00500 for (size_t idx = 0; idx < cloud_downsampled_ptr->points.size (); ++idx)
00501 {
00502
00503 int hist_idx;
00504 if( hist_num == 1 ) hist_idx = 0;
00505 else{
00506 const int tmp_x = floor( cloud_downsampled_ptr->points[ idx ].x/voxel_size ) - min_b_[ 0 ] - offset_x;
00507 const int tmp_y = floor( cloud_downsampled_ptr->points[ idx ].y/voxel_size ) - min_b_[ 1 ] - offset_y;
00508 const int tmp_z = floor( cloud_downsampled_ptr->points[ idx ].z/voxel_size ) - min_b_[ 2 ] - offset_z;
00509
00510
00511
00512
00513 if( ( tmp_x < 0 ) || ( tmp_y < 0 ) || ( tmp_z < 0 ) ) continue;
00514 Eigen::Vector3i ijk = Eigen::Vector3i ( floor ( tmp_x * inverse_subdivision_size), floor ( tmp_y * inverse_subdivision_size), floor ( tmp_z * inverse_subdivision_size) );
00515 hist_idx = ijk.dot (subdivb_mul_);
00516 }
00517
00518 int source_type = types[idx];
00519 std::vector<int> neighbors = grid.getNeighborCentroidIndices ( cloud_downsampled_ptr->points[idx], relative_coordinates_all);
00520 Eigen::Vector3f source_normal = cloud_downsampled.points[idx].getNormalVector3fMap ();
00521 if( std::isfinite( cloud_downsampled.points[idx].normal_x ) && std::isfinite( cloud_downsampled.points[idx].normal_y ) && std::isfinite( cloud_downsampled.points[idx].normal_z ) ){
00522 for (unsigned id_n = 0; id_n < neighbors.size(); id_n++)
00523 {
00524 int neighbor_type;
00525 if (neighbors[id_n] == -1)
00526 neighbor_type = EMPTY;
00527 else
00528 neighbor_type = types[neighbors[id_n]];
00529
00530
00531 if (neighbors[id_n] == -1)
00532 transitions_to_empty[ hist_idx ](source_type)++;
00533 else{
00534
00535 assert (source_type != EMPTY);
00536
00537
00538
00539
00540
00541 if( std::isfinite( cloud_downsampled.points[neighbors[id_n]].normal_x ) && std::isfinite( cloud_downsampled.points[neighbors[id_n]].normal_y ) && std::isfinite( cloud_downsampled.points[neighbors[id_n]].normal_z ) )
00542 transition_matrix_list[ (std::min (NR_DIV-1, (int) floor (sqrt (source_normal.cross (cloud_downsampled.points[neighbors[id_n]].getNormalVector3fMap ()).norm ()) * NR_DIV)) )*hist_num + hist_idx ](source_type, neighbor_type)++;
00543 else
00544 transitions_to_empty[ hist_idx ](source_type)++;
00545
00546
00547
00548
00549 }
00550 }
00551 }
00552 }
00553
00554 #ifndef QUIET
00555 std::cerr << "List of transition matrices by normal angle:" << std::endl;
00556 std::copy (transition_matrix_list.begin (), transition_matrix_list.end (), std::ostream_iterator<Eigen::MatrixXi> (std::cerr, "\n---\n"));
00557 for( int h=0; h<hist_num; h++ )
00558 std::cerr << "Transitions to empty: " << transitions_to_empty[h].transpose () << std::endl;
00559 #endif
00560
00561 pcl::PointCloud<pcl::PlusGRSDSignature110> cloud_grsd;
00562 cloud_grsd.points.resize(hist_num);
00563
00564 for( int h=0; h<hist_num; h++ ){
00565 int nrf = 0;
00566
00567 for ( int d=0; d<NR_DIV; d++ )
00568 {
00569 for (int i=0; i<NR_CLASS; i++)
00570 for (int j=i; j<NR_CLASS; j++)
00571 cloud_grsd.points[h].histogram[nrf++] = transition_matrix_list[ d * hist_num + h ](i, j);
00572 }
00573 for (int it = 0; it < NR_CLASS; ++it)
00574 cloud_grsd.points[h].histogram[nrf++] = transitions_to_empty[ h ][it];
00575
00576
00577 #ifndef QUIET
00578 std::cerr << "PlusGRSDS: " << cloud_grsd.points[0] << std::endl;
00579 #endif
00580 }
00581
00582 #ifndef QUIET
00583 ROS_INFO("GRSD compute done in %f seconds.", my_clock()-t1);
00584 #endif
00585
00586 feature.resize( hist_num );
00587 if( is_normalize ){
00588 for( int h=0; h<hist_num; h++ ){
00589 feature[ h ].resize( 110 );
00590 for( int i=0; i<110; i++)
00591 feature[ h ][ i ] = cloud_grsd.points[ h ].histogram[ i ] * NORMALIZE_GRSD;
00592 }
00593 }
00594 else{
00595 for( int h=0; h<hist_num; h++ ){
00596 feature[ h ].resize( 110 );
00597 for( int i=0; i<110; i++)
00598 feature[ h ][ i ] = cloud_grsd.points[ h ].histogram[ i ];
00599 }
00600 }
00601 return subdiv_b_;
00602 }
00603
00604 template <typename T>
00605 void extractPlusGRSDSignature110(pcl::VoxelGrid<T> grid, pcl::PointCloud<T> cloud, pcl::PointCloud<T> cloud_downsampled, std::vector<float> &feature, const float voxel_size, const bool is_normalize ){
00606 std::vector< std::vector<float> > tmp( 1 );
00607 extractPlusGRSDSignature110( grid, cloud, cloud_downsampled, tmp, voxel_size, 0, 0, 0, 0, is_normalize );
00608 feature = tmp[ 0 ];
00609 }
00610
00611
00612
00613 const std::vector<float> concVector( const std::vector<float> v1, const std::vector<float> v2 ){
00614 std::vector<float> vec = v1;
00615 vec.insert(vec.end(), v2.begin(), v2.end());
00616 return vec;
00617 }
00618
00619
00620
00621 template <typename PointT>
00622 Eigen::Vector3i extractVOSCH(pcl::VoxelGrid<PointT> grid, pcl::PointCloud<PointT> cloud, pcl::PointCloud<PointT> cloud_downsampled, std::vector< std::vector<float> > &feature, int color_threshold_r, int color_threshold_g, int color_threshold_b, const float voxel_size, const int subdivision_size = 0, const int offset_x = 0, const int offset_y = 0, const int offset_z = 0, const bool is_normalize ){
00623 std::vector< std::vector<float> > grsd;
00624 Eigen::Vector3i subdiv_b_ = extractGRSDSignature21( grid, cloud, cloud_downsampled, grsd, voxel_size, subdivision_size, offset_x, offset_y, offset_z, is_normalize );
00625 std::vector< std::vector<float> > c3_hlac;
00626 extractC3HLACSignature117( grid, cloud_downsampled, c3_hlac, color_threshold_r, color_threshold_g, color_threshold_b, voxel_size, subdivision_size, offset_x, offset_y, offset_z );
00627
00628 const int hist_num = grsd.size();
00629 for( int h=0; h<hist_num; h++ )
00630 feature.push_back ( concVector( grsd[ h ], c3_hlac[ h ] ) );
00631 return subdiv_b_;
00632 }
00633
00634 template <typename PointT>
00635 void extractVOSCH(pcl::VoxelGrid<PointT> grid, pcl::PointCloud<PointT> cloud, pcl::PointCloud<PointT> cloud_downsampled, std::vector<float> &feature, int color_threshold_r, int color_threshold_g, int color_threshold_b, const float voxel_size, const int subdivision_size = 0, const int offset_x = 0, const int offset_y = 0, const int offset_z = 0 ){
00636 std::vector< std::vector<float> > tmp;
00637 extractVOSCH( grid, cloud, cloud_downsampled, tmp, color_threshold_r, color_threshold_g, color_threshold_b, voxel_size );
00638 feature = tmp[ 0 ];
00639 }
00640
00641
00642
00643 template <typename PointT>
00644 Eigen::Vector3i extractConVOSCH(pcl::VoxelGrid<PointT> grid, pcl::PointCloud<PointT> cloud, pcl::PointCloud<PointT> cloud_downsampled, std::vector< std::vector<float> > &feature, int color_threshold_r, int color_threshold_g, int color_threshold_b, const float voxel_size, const int subdivision_size = 0, const int offset_x = 0, const int offset_y = 0, const int offset_z = 0, const bool is_normalize ){
00645 std::vector< std::vector<float> > grsd;
00646 Eigen::Vector3i subdiv_b_ = extractGRSDSignature21( grid, cloud, cloud_downsampled, grsd, voxel_size, subdivision_size, offset_x, offset_y, offset_z, is_normalize );
00647 std::vector< std::vector<float> > c3_hlac;
00648 extractC3HLACSignature981( grid, cloud_downsampled, c3_hlac, color_threshold_r, color_threshold_g, color_threshold_b, voxel_size, subdivision_size, offset_x, offset_y, offset_z );
00649
00650 const int hist_num = grsd.size();
00651 for( int h=0; h<hist_num; h++ )
00652 feature.push_back ( concVector( grsd[ h ], c3_hlac[ h ] ) );
00653 return subdiv_b_;
00654 }
00655
00656 template <typename PointT>
00657 void extractConVOSCH(pcl::VoxelGrid<PointT> grid, pcl::PointCloud<PointT> cloud, pcl::PointCloud<PointT> cloud_downsampled, std::vector<float> &feature, int color_threshold_r, int color_threshold_g, int color_threshold_b, const float voxel_size, const int subdivision_size = 0, const int offset_x = 0, const int offset_y = 0, const int offset_z = 0 ){
00658 std::vector< std::vector<float> > tmp;
00659 extractConVOSCH( grid, cloud, cloud_downsampled, tmp, color_threshold_r, color_threshold_g, color_threshold_b, voxel_size );
00660 feature = tmp[ 0 ];
00661 }