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
00035
00036
00037
00038
00039
00040 #include <gtest/gtest.h>
00041 #include <pcl/point_cloud.h>
00042 #include <pcl/features/normal_3d_omp.h>
00043 #include <pcl/io/pcd_io.h>
00044 #include <pcl/features/shot.h>
00045 #include <pcl/features/shot_omp.h>
00046 #include "pcl/features/shot_lrf.h"
00047 #include <pcl/features/3dsc.h>
00048 #include <pcl/features/usc.h>
00049
00050 using namespace pcl;
00051 using namespace pcl::io;
00052 using namespace std;
00053
00054 typedef search::KdTree<PointXYZ>::Ptr KdTreePtr;
00055
00056 PointCloud<PointXYZ> cloud;
00057 vector<int> indices;
00058 KdTreePtr tree;
00059
00061 template<typename PointT> void
00062 shotCopyPointCloud (const PointCloud<PointT> &cloud_in, const std::vector<int> &indices,
00063 PointCloud<PointT> &cloud_out)
00064 {
00065 pcl::copyPointCloud<PointT>(cloud_in, indices, cloud_out);
00066 }
00067
00069 template <typename PointT> void
00070 checkDesc(const pcl::PointCloud<PointT>& d0, const pcl::PointCloud<PointT>& d1)
00071 {
00072 ASSERT_EQ (d0.size (), d1.size ());
00073 for (size_t i = 0; i < d1.size (); ++i)
00074 for (size_t j = 0; j < d0.points[i].descriptor.size(); ++j)
00075 ASSERT_EQ (d0.points[i].descriptor[j], d1.points[i].descriptor[j]);
00076 }
00077
00079 template <> void
00080 checkDesc<SHOT352>(const pcl::PointCloud<SHOT352>& d0, const pcl::PointCloud<SHOT352>& d1)
00081 {
00082 ASSERT_EQ (d0.size (), d1.size ());
00083 for (size_t i = 0; i < d1.size (); ++i)
00084 for (size_t j = 0; j < 352; ++j)
00085 ASSERT_EQ (d0.points[i].descriptor[j], d1.points[i].descriptor[j]);
00086 }
00087
00089 template <> void
00090 checkDesc<SHOT1344>(const pcl::PointCloud<SHOT1344>& d0, const pcl::PointCloud<SHOT1344>& d1)
00091 {
00092 ASSERT_EQ (d0.size (), d1.size ());
00093 for (size_t i = 0; i < d1.size (); ++i)
00094 for (size_t j = 0; j < 1344; ++j)
00095 ASSERT_EQ (d0.points[i].descriptor[j], d1.points[i].descriptor[j]);
00096 }
00097
00099 template <> void
00100 checkDesc<ShapeContext1980>(const pcl::PointCloud<ShapeContext1980>& d0, const pcl::PointCloud<ShapeContext1980>& d1)
00101 {
00102 ASSERT_EQ (d0.size (), d1.size ());
00103 for (size_t i = 0; i < d1.size (); ++i)
00104 for (size_t j = 0; j < 1980; ++j)
00105 ASSERT_EQ (d0.points[i].descriptor[j], d1.points[i].descriptor[j]);
00106 }
00107
00109 template <typename FeatureEstimation, typename PointT, typename NormalT, typename OutputT>
00110 struct createSHOTDesc
00111 {
00112 FeatureEstimation operator ()(const typename PointCloud<NormalT>::Ptr & normals,
00113 const int nr_shape_bins_ = 10,
00114 const int = 30,
00115 const bool = true,
00116 const bool = false) const
00117 {
00118 FeatureEstimation f(nr_shape_bins_);
00119 f.setInputNormals (normals);
00120 return (f);
00121 }
00122 };
00123
00125 template <typename FeatureEstimation, typename PointT, typename NormalT>
00126 struct createSHOTDesc<FeatureEstimation, PointT, NormalT, SHOT352>
00127 {
00128 FeatureEstimation operator ()(const typename PointCloud<NormalT>::Ptr & normals,
00129 const int = 10,
00130 const int = 30,
00131 const bool = true,
00132 const bool = false) const
00133 {
00134 FeatureEstimation f;
00135 f.setInputNormals (normals);
00136 return (f);
00137 }
00138 };
00139
00141 template <typename FeatureEstimation, typename PointT, typename NormalT>
00142 struct createSHOTDesc<FeatureEstimation, PointT, NormalT, SHOT1344>
00143 {
00144 FeatureEstimation operator ()(const typename PointCloud<NormalT>::Ptr & normals,
00145 const int = 10,
00146 const int = 30,
00147 const bool describe_shape = true,
00148 const bool describe_color = false) const
00149 {
00150 FeatureEstimation f (describe_shape, describe_color);
00151 f.setInputNormals (normals);
00152 return (f);
00153 }
00154 };
00155
00157 template <typename PointT, typename NormalT, typename OutputT>
00158 struct createSHOTDesc<ShapeContext3DEstimation<PointT, NormalT, OutputT>, PointT, NormalT, OutputT>
00159 {
00160 ShapeContext3DEstimation<PointT, NormalT, OutputT>
00161 operator ()(const typename PointCloud<NormalT>::Ptr & normals,
00162 const int,
00163 const int,
00164 const bool,
00165 const bool) const
00166 {
00167 ShapeContext3DEstimation<PointT, NormalT, OutputT> sc3d;
00168
00169
00170
00171 sc3d.setMinimalRadius (0.004);
00172 sc3d.setPointDensityRadius (0.008);
00173 sc3d.setInputNormals (normals);
00174 return (sc3d);
00175 }
00176 };
00177
00179 template <typename PointT, typename NormalT, typename OutputT>
00180 struct createSHOTDesc<UniqueShapeContext<PointT, OutputT>, PointT, NormalT, OutputT>
00181 {
00182 UniqueShapeContext<PointT, OutputT>
00183 operator ()(const typename PointCloud<NormalT>::Ptr &,
00184 const int,
00185 const int,
00186 const bool,
00187 const bool) const
00188 {
00189 UniqueShapeContext<PointT, OutputT> usc;
00190
00191
00192
00193 usc.setMinimalRadius (0.004);
00194 usc.setPointDensityRadius (0.008);
00195 usc.setLocalRadius (0.04);
00196 return (usc);
00197 }
00198 };
00199
00201 template <typename FeatureEstimation, typename PointT, typename NormalT, typename OutputT> void
00202 testSHOTIndicesAndSearchSurface (const typename PointCloud<PointT>::Ptr & points,
00203 const typename PointCloud<NormalT>::Ptr & normals,
00204 const boost::shared_ptr<vector<int> > & indices,
00205 const int nr_shape_bins = 10,
00206 const int nr_color_bins = 30,
00207 const bool describe_shape = true,
00208 const bool describe_color = false)
00209 {
00210 double radius = 0.04;
00211
00212
00213
00214 PointCloud<OutputT> full_output, output0, output1, output2;
00215
00216
00217 FeatureEstimation est0 = createSHOTDesc<FeatureEstimation, PointT, NormalT, OutputT>()(normals, nr_shape_bins,nr_color_bins,describe_shape,describe_color);
00218 est0.setSearchMethod (typename search::KdTree<PointT>::Ptr (new search::KdTree<PointT>));
00219 est0.setRadiusSearch (radius);
00220 est0.setInputCloud (points);
00221 est0.compute (full_output);
00222
00223 shotCopyPointCloud<OutputT> (full_output, *indices, output0);
00224
00225
00226 typename PointCloud<PointT>::Ptr subpoints (new PointCloud<PointT>);
00227 copyPointCloud (*points, *indices, *subpoints);
00228 FeatureEstimation est1 = createSHOTDesc<FeatureEstimation, PointT, NormalT, OutputT>()(normals, nr_shape_bins,nr_color_bins,describe_shape,describe_color);
00229 est1.setSearchMethod (typename search::KdTree<PointT>::Ptr (new search::KdTree<PointT>));
00230 est1.setRadiusSearch (radius);
00231 est1.setInputCloud (subpoints);
00232 est1.setSearchSurface (points);
00233 est1.compute (output1);
00234
00236 FeatureEstimation est2 = createSHOTDesc<FeatureEstimation, PointT, NormalT, OutputT>()(normals, nr_shape_bins,nr_color_bins,describe_shape,describe_color);
00237 est2.setSearchMethod (typename search::KdTree<PointT>::Ptr (new search::KdTree<PointT>));
00238 est2.setRadiusSearch (radius);
00239 est2.setInputCloud (points);
00240 est2.setIndices (indices);
00241 est2.compute (output2);
00242
00243
00244 checkDesc<OutputT> (output0, output1);
00245 checkDesc<OutputT> (output1, output2);
00246
00247
00248
00249
00250 PointCloud<OutputT> output3, output4;
00251
00252 boost::shared_ptr<vector<int> > indices2 (new vector<int> (0));
00253 for (size_t i = 0; i < (indices->size ()/2); ++i)
00254 indices2->push_back (static_cast<int> (i));
00255
00256
00257 FeatureEstimation est3 = createSHOTDesc<FeatureEstimation, PointT, NormalT, OutputT>()(normals, nr_shape_bins,nr_color_bins,describe_shape,describe_color);
00258 est3.setSearchMethod (typename search::KdTree<PointT>::Ptr (new search::KdTree<PointT>));
00259 est3.setRadiusSearch (radius);
00260 est3.setSearchSurface (points);
00261 est3.setInputCloud (subpoints);
00262 est3.setIndices (indices2);
00263 est3.compute (output3);
00264
00265
00266 shotCopyPointCloud<OutputT> (output0, *indices2, output4);
00267
00268
00269 checkDesc<OutputT> (output3, output4);
00270 }
00271
00273 template <typename FeatureEstimation, typename PointT, typename NormalT, typename OutputT> void
00274 testSHOTLocalReferenceFrame (const typename PointCloud<PointT>::Ptr & points,
00275 const typename PointCloud<NormalT>::Ptr & normals,
00276 const boost::shared_ptr<vector<int> > & indices,
00277 const int nr_shape_bins = 10,
00278 const int nr_color_bins = 30,
00279 const bool describe_shape = true,
00280 const bool describe_color = false)
00281 {
00282 double radius = 0.04;
00283
00284 typename PointCloud<PointT>::Ptr subpoints (new PointCloud<PointT> ());
00285 copyPointCloud (*points, *indices, *subpoints);
00286
00287 boost::shared_ptr<vector<int> > indices2 (new vector<int> (0));
00288 for (size_t i = 0; i < (indices->size ()/2); ++i)
00289 indices2->push_back (static_cast<int> (i));
00290
00291
00292
00293 PointCloud<ReferenceFrame>::Ptr frames (new PointCloud<ReferenceFrame> ());
00294 SHOTLocalReferenceFrameEstimation<PointT, pcl::ReferenceFrame> lrf_estimator;
00295 lrf_estimator.setRadiusSearch (radius);
00296 lrf_estimator.setInputCloud (subpoints);
00297 lrf_estimator.setIndices (indices2);
00298 lrf_estimator.setSearchSurface(points);
00299 lrf_estimator.compute (*frames);
00300
00301 PointCloud<OutputT> output, output2;
00302
00303 FeatureEstimation est = createSHOTDesc<FeatureEstimation, PointT, NormalT, OutputT>()(normals, nr_shape_bins,nr_color_bins,describe_shape,describe_color);
00304 est.setSearchMethod (typename search::KdTree<PointT>::Ptr (new search::KdTree<PointT>));
00305 est.setRadiusSearch (radius);
00306 est.setSearchSurface (points);
00307 est.setInputCloud (subpoints);
00308 est.setIndices (indices2);
00309 est.compute (output);
00310
00311 FeatureEstimation est2 = createSHOTDesc<FeatureEstimation, PointT, NormalT, OutputT>()(normals, nr_shape_bins,nr_color_bins,describe_shape,describe_color);
00312 est2.setSearchMethod (typename search::KdTree<PointT>::Ptr (new search::KdTree<PointT>));
00313 est2.setRadiusSearch (radius);
00314 est2.setSearchSurface (points);
00315 est2.setInputCloud (subpoints);
00316 est2.setIndices (indices2);
00317 est2.setInputReferenceFrames (frames);
00318 est2.compute (output2);
00319
00320
00321 pcl::PointCloud<pcl::ReferenceFrame>::ConstPtr f = est.getInputReferenceFrames ();
00322 pcl::PointCloud<pcl::ReferenceFrame>::ConstPtr f2 = est2.getInputReferenceFrames ();
00323 ASSERT_EQ (frames->points.size (), f->points.size ());
00324 ASSERT_EQ (f2->points.size (), f->points.size ());
00325 for (int i = 0; i < static_cast<int> (frames->points.size ()); ++i)
00326 {
00327 for (unsigned j = 0; j < 9; ++j)
00328 ASSERT_EQ (frames->points[i].rf[j], f->points[i].rf[j]);
00329
00330 for (unsigned j = 0; j < 9; ++j)
00331 ASSERT_EQ (frames->points[i].rf[j], f2->points[i].rf[j]);
00332 }
00333
00334
00335 checkDesc<OutputT> (output, output2);
00336 }
00337
00339 TEST (PCL, SHOTShapeEstimation)
00340 {
00341
00342 double mr = 0.002;
00343 NormalEstimation<PointXYZ, Normal> n;
00344 PointCloud<Normal>::Ptr normals (new PointCloud<Normal> ());
00345
00346 n.setInputCloud (cloud.makeShared ());
00347 boost::shared_ptr<vector<int> > indicesptr (new vector<int> (indices));
00348 n.setIndices (indicesptr);
00349 n.setSearchMethod (tree);
00350 n.setRadiusSearch (20 * mr);
00351 n.compute (*normals);
00352
00353 EXPECT_NEAR (normals->points[103].normal_x, 0.36683175, 1e-4);
00354 EXPECT_NEAR (normals->points[103].normal_y, -0.44696972, 1e-4);
00355 EXPECT_NEAR (normals->points[103].normal_z, -0.81587529, 1e-4);
00356 EXPECT_NEAR (normals->points[200].normal_x, -0.71414840, 1e-4);
00357 EXPECT_NEAR (normals->points[200].normal_y, -0.06002361, 1e-4);
00358 EXPECT_NEAR (normals->points[200].normal_z, -0.69741613, 1e-4);
00359
00360 EXPECT_NEAR (normals->points[140].normal_x, -0.45109111, 1e-4);
00361 EXPECT_NEAR (normals->points[140].normal_y, -0.19499126, 1e-4);
00362 EXPECT_NEAR (normals->points[140].normal_z, -0.87091631, 1e-4);
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395 SHOTEstimation<PointXYZ, Normal, SHOT352> shot352;
00396 shot352.setInputNormals (normals);
00397 EXPECT_EQ (shot352.getInputNormals (), normals);
00398 shot352.setRadiusSearch (20 * mr);
00399
00400
00401 PointCloud<SHOT352>::Ptr shots352 (new PointCloud<SHOT352> ());
00402
00403
00404 shot352.setInputCloud (cloud.makeShared ());
00405 shot352.setIndices (indicesptr);
00406 shot352.setSearchMethod (tree);
00407
00408
00409 shot352.compute (*shots352);
00410 EXPECT_EQ (shots352->points.size (), indices.size ());
00411
00412 EXPECT_NEAR (shots352->points[103].descriptor[9 ], 0.0072018504, 1e-4);
00413 EXPECT_NEAR (shots352->points[103].descriptor[10], 0.0023103887, 1e-4);
00414 EXPECT_NEAR (shots352->points[103].descriptor[11], 0.0024724449, 1e-4);
00415 EXPECT_NEAR (shots352->points[103].descriptor[19], 0.0031367359, 1e-4);
00416 EXPECT_NEAR (shots352->points[103].descriptor[20], 0.17439659, 1e-4);
00417 EXPECT_NEAR (shots352->points[103].descriptor[21], 0.070665278, 1e-4);
00418 EXPECT_NEAR (shots352->points[103].descriptor[42], 0.013304681, 1e-4);
00419 EXPECT_NEAR (shots352->points[103].descriptor[53], 0.0073520984, 1e-4);
00420 EXPECT_NEAR (shots352->points[103].descriptor[54], 0.013584172, 1e-4);
00421 EXPECT_NEAR (shots352->points[103].descriptor[55], 0.0050609680, 1e-4);
00422
00423
00424
00425
00426 boost::shared_ptr<vector<int> > test_indices (new vector<int> (0));
00427 for (size_t i = 0; i < cloud.size (); i+=3)
00428 test_indices->push_back (static_cast<int> (i));
00429
00430
00431
00432
00433 testSHOTIndicesAndSearchSurface<SHOTEstimation<PointXYZ, Normal, SHOT352>, PointXYZ, Normal, SHOT352> (cloud.makeShared (), normals, test_indices);
00434 testSHOTLocalReferenceFrame<SHOTEstimation<PointXYZ, Normal, SHOT352>, PointXYZ, Normal, SHOT352> (cloud.makeShared (), normals, test_indices);
00435 }
00436
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00495 TEST (PCL, SHOTShapeAndColorEstimation)
00496 {
00497 double mr = 0.002;
00498
00499 NormalEstimation<PointXYZ, Normal> n;
00500 PointCloud<Normal>::Ptr normals (new PointCloud<Normal> ());
00501
00502 n.setInputCloud (cloud.makeShared ());
00503 boost::shared_ptr<vector<int> > indicesptr (new vector<int> (indices));
00504 n.setIndices (indicesptr);
00505 n.setSearchMethod (tree);
00506 n.setRadiusSearch (20 * mr);
00507 n.compute (*normals);
00508
00509 search::KdTree<PointXYZRGBA>::Ptr rgbaTree;
00510 rgbaTree.reset (new search::KdTree<PointXYZRGBA> (false));
00511
00512
00513 PointCloud<PointXYZRGBA> cloudWithColors;
00514 for (int i = 0; i < static_cast<int> (cloud.points.size ()); ++i)
00515 {
00516 PointXYZRGBA p;
00517 p.x = cloud.points[i].x;
00518 p.y = cloud.points[i].y;
00519 p.z = cloud.points[i].z;
00520
00521 p.rgba = ( (i%255) << 16 ) + ( ( (255 - i ) %255) << 8) + ( ( i*37 ) %255);
00522 cloudWithColors.push_back(p);
00523 }
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568 SHOTColorEstimation<PointXYZRGBA, Normal, SHOT1344> shot1344 (true, true);
00569 shot1344.setInputNormals (normals);
00570 EXPECT_EQ (shot1344.getInputNormals (), normals);
00571
00572 shot1344.setRadiusSearch ( 20 * mr);
00573
00574 PointCloud<SHOT1344>::Ptr shots1344 (new PointCloud<SHOT1344>);
00575
00576 shot1344.setInputCloud (cloudWithColors.makeShared ());
00577 shot1344.setIndices (indicesptr);
00578 shot1344.setSearchMethod (rgbaTree);
00579
00580
00581 shot1344.compute (*shots1344);
00582 EXPECT_EQ (shots1344->points.size (), indices.size ());
00583
00584 EXPECT_NEAR (shots1344->points[103].descriptor[10], 0.0020453099, 1e-5);
00585 EXPECT_NEAR (shots1344->points[103].descriptor[11], 0.0021887729, 1e-5);
00586 EXPECT_NEAR (shots1344->points[103].descriptor[21], 0.062557608, 1e-5);
00587 EXPECT_NEAR (shots1344->points[103].descriptor[42], 0.011778189, 1e-5);
00588 EXPECT_NEAR (shots1344->points[103].descriptor[53], 0.0065085669, 1e-5);
00589 EXPECT_NEAR (shots1344->points[103].descriptor[54], 0.012025614, 1e-5);
00590 EXPECT_NEAR (shots1344->points[103].descriptor[55], 0.0044803056, 1e-5);
00591 EXPECT_NEAR (shots1344->points[103].descriptor[64], 0.064429596, 1e-5);
00592 EXPECT_NEAR (shots1344->points[103].descriptor[65], 0.046486385, 1e-5);
00593 EXPECT_NEAR (shots1344->points[103].descriptor[86], 0.011518310, 1e-5);
00594
00595 EXPECT_NEAR (shots1344->points[103].descriptor[357], 0.0020453099, 1e-5);
00596 EXPECT_NEAR (shots1344->points[103].descriptor[360], 0.0027993850, 1e-5);
00597 EXPECT_NEAR (shots1344->points[103].descriptor[386], 0.045115642, 1e-5);
00598 EXPECT_NEAR (shots1344->points[103].descriptor[387], 0.059068538, 1e-5);
00599 EXPECT_NEAR (shots1344->points[103].descriptor[389], 0.0047547864, 1e-5);
00600 EXPECT_NEAR (shots1344->points[103].descriptor[453], 0.0051176427, 1e-5);
00601 EXPECT_NEAR (shots1344->points[103].descriptor[481], 0.0053625242, 1e-5);
00602 EXPECT_NEAR (shots1344->points[103].descriptor[482], 0.012025614, 1e-5);
00603 EXPECT_NEAR (shots1344->points[103].descriptor[511], 0.0057367259, 1e-5);
00604 EXPECT_NEAR (shots1344->points[103].descriptor[512], 0.048357654, 1e-5);
00605
00606
00607 boost::shared_ptr<vector<int> > test_indices (new vector<int> (0));
00608 for (size_t i = 0; i < cloud.size (); i+=3)
00609 test_indices->push_back (static_cast<int> (i));
00610
00611
00612
00613
00614 testSHOTIndicesAndSearchSurface<SHOTColorEstimation<PointXYZRGBA, Normal, SHOT1344>, PointXYZRGBA, Normal, SHOT1344> (cloudWithColors.makeShared (), normals, test_indices);
00615 testSHOTLocalReferenceFrame<SHOTColorEstimation<PointXYZRGBA, Normal, SHOT1344>, PointXYZRGBA, Normal, SHOT1344> (cloudWithColors.makeShared (), normals, test_indices);
00616 }
00617
00619 TEST (PCL, SHOTShapeEstimationOpenMP)
00620 {
00621
00622 double mr = 0.002;
00623 #ifdef _OPENMP
00624 NormalEstimationOMP<PointXYZ, Normal> n (omp_get_max_threads ());
00625 #else
00626 NormalEstimationOMP<PointXYZ, Normal> n;
00627 #endif
00628 PointCloud<Normal>::Ptr normals (new PointCloud<Normal> ());
00629
00630 n.setInputCloud (cloud.makeShared ());
00631 boost::shared_ptr<vector<int> > indicesptr (new vector<int> (indices));
00632 n.setIndices (indicesptr);
00633 n.setSearchMethod (tree);
00634 n.setRadiusSearch (20 * mr);
00635 n.compute (*normals);
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669 SHOTEstimationOMP<PointXYZ, Normal, SHOT352> shot352;
00670 shot352.setInputNormals (normals);
00671 EXPECT_EQ (shot352.getInputNormals (), normals);
00672
00673 shot352.setRadiusSearch ( 20 * mr);
00674
00675
00676 PointCloud<SHOT352>::Ptr shots352 (new PointCloud<SHOT352>);
00677
00678
00679 shot352.setInputCloud (cloud.makeShared ());
00680 shot352.setIndices (indicesptr);
00681 shot352.setSearchMethod (tree);
00682
00683
00684 shot352.compute (*shots352);
00685 EXPECT_EQ (shots352->points.size (), indices.size ());
00686
00687 EXPECT_NEAR (shots352->points[103].descriptor[9 ], 0.0072018504, 1e-4);
00688 EXPECT_NEAR (shots352->points[103].descriptor[10], 0.0023103887, 1e-4);
00689 EXPECT_NEAR (shots352->points[103].descriptor[11], 0.0024724449, 1e-4);
00690 EXPECT_NEAR (shots352->points[103].descriptor[19], 0.0031367359, 1e-4);
00691 EXPECT_NEAR (shots352->points[103].descriptor[20], 0.17439659, 1e-4);
00692 EXPECT_NEAR (shots352->points[103].descriptor[21], 0.070665278, 1e-4);
00693 EXPECT_NEAR (shots352->points[103].descriptor[42], 0.013304681, 1e-4);
00694 EXPECT_NEAR (shots352->points[103].descriptor[53], 0.0073520984, 1e-4);
00695 EXPECT_NEAR (shots352->points[103].descriptor[54], 0.013584172, 1e-4);
00696 EXPECT_NEAR (shots352->points[103].descriptor[55], 0.0050609680, 1e-4);
00697
00698
00699 boost::shared_ptr<vector<int> > test_indices (new vector<int> (0));
00700 for (size_t i = 0; i < cloud.size (); i+=3)
00701 test_indices->push_back (static_cast<int> (i));
00702
00703
00704
00705
00706 testSHOTIndicesAndSearchSurface<SHOTEstimationOMP<PointXYZ, Normal, SHOT352>, PointXYZ, Normal, SHOT352> (cloud.makeShared (), normals, test_indices);
00707 testSHOTLocalReferenceFrame<SHOTEstimationOMP<PointXYZ, Normal, SHOT352>, PointXYZ, Normal, SHOT352> (cloud.makeShared (), normals, test_indices);
00708 }
00709
00711 TEST (PCL,SHOTShapeAndColorEstimationOpenMP)
00712 {
00713 double mr = 0.002;
00714
00715 NormalEstimation<PointXYZ, Normal> n;
00716 PointCloud<Normal>::Ptr normals (new PointCloud<Normal> ());
00717
00718 n.setInputCloud (cloud.makeShared ());
00719 boost::shared_ptr<vector<int> > indicesptr (new vector<int> (indices));
00720 n.setIndices (indicesptr);
00721 n.setSearchMethod (tree);
00722 n.setRadiusSearch (20 * mr);
00723 n.compute (*normals);
00724
00725 search::KdTree<PointXYZRGBA>::Ptr rgbaTree;
00726
00727 rgbaTree.reset (new search::KdTree<PointXYZRGBA> (false));
00728
00729
00730 PointCloud<PointXYZRGBA> cloudWithColors;
00731 for (int i = 0; i < static_cast<int> (cloud.points.size ()); ++i)
00732 {
00733 PointXYZRGBA p;
00734 p.x = cloud.points[i].x;
00735 p.y = cloud.points[i].y;
00736 p.z = cloud.points[i].z;
00737
00738 p.rgba = ( (i%255) << 16 ) + ( ( (255 - i ) %255) << 8) + ( ( i*37 ) %255);
00739 cloudWithColors.push_back(p);
00740 }
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787 SHOTColorEstimationOMP<PointXYZRGBA, Normal, SHOT1344> shot1344 (true, true);
00788 shot1344.setInputNormals (normals);
00789
00790 EXPECT_EQ (shot1344.getInputNormals (), normals);
00791
00792 shot1344.setRadiusSearch ( 20 * mr);
00793
00794 PointCloud<SHOT1344>::Ptr shots1344 (new PointCloud<SHOT1344> ());
00795
00796 shot1344.setInputCloud (cloudWithColors.makeShared ());
00797 shot1344.setIndices (indicesptr);
00798 shot1344.setSearchMethod (rgbaTree);
00799
00800
00801 shot1344.compute (*shots1344);
00802 EXPECT_EQ (shots1344->points.size (), indices.size ());
00803
00804 EXPECT_NEAR (shots1344->points[103].descriptor[10], 0.0020453099, 1e-5);
00805 EXPECT_NEAR (shots1344->points[103].descriptor[11], 0.0021887729, 1e-5);
00806 EXPECT_NEAR (shots1344->points[103].descriptor[21], 0.062557608, 1e-5);
00807 EXPECT_NEAR (shots1344->points[103].descriptor[42], 0.011778189, 1e-5);
00808 EXPECT_NEAR (shots1344->points[103].descriptor[53], 0.0065085669, 1e-5);
00809 EXPECT_NEAR (shots1344->points[103].descriptor[54], 0.012025614, 1e-5);
00810 EXPECT_NEAR (shots1344->points[103].descriptor[55], 0.0044803056, 1e-5);
00811 EXPECT_NEAR (shots1344->points[103].descriptor[64], 0.064429596, 1e-5);
00812 EXPECT_NEAR (shots1344->points[103].descriptor[65], 0.046486385, 1e-5);
00813 EXPECT_NEAR (shots1344->points[103].descriptor[86], 0.011518310, 1e-5);
00814
00815 EXPECT_NEAR (shots1344->points[103].descriptor[357], 0.0020453099, 1e-5);
00816 EXPECT_NEAR (shots1344->points[103].descriptor[360], 0.0027993850, 1e-5);
00817 EXPECT_NEAR (shots1344->points[103].descriptor[386], 0.045115642, 1e-5);
00818 EXPECT_NEAR (shots1344->points[103].descriptor[387], 0.059068538, 1e-5);
00819 EXPECT_NEAR (shots1344->points[103].descriptor[389], 0.0047547864, 1e-5);
00820 EXPECT_NEAR (shots1344->points[103].descriptor[453], 0.0051176427, 1e-5);
00821 EXPECT_NEAR (shots1344->points[103].descriptor[481], 0.0053625242, 1e-5);
00822 EXPECT_NEAR (shots1344->points[103].descriptor[482], 0.012025614, 1e-5);
00823 EXPECT_NEAR (shots1344->points[103].descriptor[511], 0.0057367259, 1e-5);
00824 EXPECT_NEAR (shots1344->points[103].descriptor[512], 0.048357654, 1e-5);
00825
00826
00827 boost::shared_ptr<vector<int> > test_indices (new vector<int> (0));
00828 for (size_t i = 0; i < cloud.size (); i+=3)
00829 test_indices->push_back (static_cast<int> (i));
00830
00831
00832
00833
00834 testSHOTIndicesAndSearchSurface<SHOTColorEstimationOMP<PointXYZRGBA, Normal, SHOT1344>, PointXYZRGBA, Normal, SHOT1344> (cloudWithColors.makeShared (), normals, test_indices);
00835 testSHOTLocalReferenceFrame<SHOTColorEstimationOMP<PointXYZRGBA, Normal, SHOT1344>, PointXYZRGBA, Normal, SHOT1344> (cloudWithColors.makeShared (), normals, test_indices);
00836 }
00837
00839 TEST (PCL,3DSCEstimation)
00840 {
00841 float meshRes = 0.002f;
00842
00843
00844
00845 float radius = 20.0f * meshRes;
00846 float rmin = radius / 10.0f;
00847 float ptDensityRad = radius / 5.0f;
00848
00849 PointCloud<PointXYZ>::Ptr cloudptr = cloud.makeShared ();
00850
00851
00852 NormalEstimation<PointXYZ, Normal> ne;
00853 PointCloud<Normal>::Ptr normals (new PointCloud<Normal> ());
00854
00855 ne.setInputCloud (cloudptr);
00856 ne.setSearchMethod (tree);
00857 ne.setRadiusSearch (radius);
00858
00859 ne.compute (*normals);
00860
00861 ShapeContext3DEstimation<PointXYZ, Normal, ShapeContext1980> sc3d;
00862 sc3d.setInputCloud (cloudptr);
00863 sc3d.setInputNormals (normals);
00864 sc3d.setSearchMethod (tree);
00865 sc3d.setRadiusSearch (radius);
00866
00867
00868
00869 sc3d.setMinimalRadius (rmin);
00870 sc3d.setPointDensityRadius (ptDensityRad);
00871
00872 PointCloud<ShapeContext1980>::Ptr sc3ds (new PointCloud<ShapeContext1980> ());
00873 sc3d.compute (*sc3ds);
00874 EXPECT_EQ (sc3ds->size (), cloud.size ());
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887 EXPECT_NEAR ((*sc3ds)[0].rf[0], 0.0f, 1e-4f);
00888 EXPECT_NEAR ((*sc3ds)[0].rf[1], 0.0f, 1e-4f);
00889 EXPECT_NEAR ((*sc3ds)[0].rf[2], 0.0f, 1e-4f);
00890 EXPECT_NEAR ((*sc3ds)[0].rf[3], 0.0f, 1e-4f);
00891 EXPECT_NEAR ((*sc3ds)[0].rf[4], 0.0f, 1e-4f);
00892 EXPECT_NEAR ((*sc3ds)[0].rf[5], 0.0f, 1e-4f);
00893 EXPECT_NEAR ((*sc3ds)[0].rf[6], 0.0f, 1e-4f);
00894 EXPECT_NEAR ((*sc3ds)[0].rf[7], 0.0f, 1e-4f);
00895 EXPECT_NEAR ((*sc3ds)[0].rf[8], 0.0f, 1e-4f);
00896
00897
00898
00899 EXPECT_NEAR ((*sc3ds)[94].descriptor[88], 55.2712f, 1e-4f);
00900 EXPECT_NEAR ((*sc3ds)[94].descriptor[584], 71.1088f, 1e-4f);
00901 EXPECT_NEAR ((*sc3ds)[94].descriptor[1106], 79.5896f, 1e-4f);
00902 EXPECT_NEAR ((*sc3ds)[94].descriptor[1560], 0.f, 1e-4f);
00903 EXPECT_NEAR ((*sc3ds)[94].descriptor[1929], 36.0636f, 1e-4f);
00904
00905 EXPECT_NEAR ((*sc3ds)[108].descriptor[67], 0.f, 1e-4f);
00906 EXPECT_NEAR ((*sc3ds)[108].descriptor[548], 126.141f, 1e-4f);
00907 EXPECT_NEAR ((*sc3ds)[108].descriptor[1091], 30.4704f, 1e-4f);
00908 EXPECT_NEAR ((*sc3ds)[108].descriptor[1421], 38.088f, 1e-4f);
00909 EXPECT_NEAR ((*sc3ds)[108].descriptor[1900], 43.7994f, 1e-4f);
00910
00911
00912 boost::shared_ptr<vector<int> > test_indices (new vector<int> (0));
00913 for (size_t i = 0; i < cloud.size (); i++)
00914 test_indices->push_back (static_cast<int> (i));
00915
00916 testSHOTIndicesAndSearchSurface<ShapeContext3DEstimation<PointXYZ, Normal, ShapeContext1980>, PointXYZ, Normal, ShapeContext1980> (cloudptr, normals, test_indices);
00917 }
00918
00920 TEST (PCL, USCEstimation)
00921 {
00922 float meshRes = 0.002f;
00923
00924
00925
00926 float radius = 20.0f * meshRes;
00927 float rmin = radius / 10.0f;
00928 float ptDensityRad = radius / 5.0f;
00929
00930
00931 UniqueShapeContext<PointXYZ, ShapeContext1980> uscd;
00932 uscd.setInputCloud (cloud.makeShared ());
00933 uscd.setSearchMethod (tree);
00934 uscd.setRadiusSearch (radius);
00935
00936
00937
00938 uscd.setMinimalRadius (rmin);
00939 uscd.setPointDensityRadius (ptDensityRad);
00940 uscd.setLocalRadius (radius);
00941
00942 PointCloud<ShapeContext1980>::Ptr uscds (new PointCloud<ShapeContext1980>);
00943 uscd.compute (*uscds);
00944 EXPECT_EQ (uscds->size (), cloud.size ());
00945
00946 EXPECT_NEAR ((*uscds)[160].rf[0], -0.97767f, 1e-4f);
00947 EXPECT_NEAR ((*uscds)[160].rf[1], 0.0353674f, 1e-4f);
00948 EXPECT_NEAR ((*uscds)[160].rf[2], -0.20715f, 1e-4f);
00949 EXPECT_NEAR ((*uscds)[160].rf[3], 0.0125394f, 1e-4f);
00950 EXPECT_NEAR ((*uscds)[160].rf[4], 0.993798f, 1e-4f);
00951 EXPECT_NEAR ((*uscds)[160].rf[5], 0.110493f, 1e-4f);
00952 EXPECT_NEAR ((*uscds)[160].rf[6], 0.209773f, 1e-4f);
00953 EXPECT_NEAR ((*uscds)[160].rf[7], 0.105428f, 1e-4f);
00954 EXPECT_NEAR ((*uscds)[160].rf[8], -0.972049f, 1e-4f);
00955
00956
00957
00958 EXPECT_NEAR ((*uscds)[160].descriptor[56], 53.0597f, 1e-4f);
00959 EXPECT_NEAR ((*uscds)[160].descriptor[734], 80.1063f, 1e-4f);
00960 EXPECT_NEAR ((*uscds)[160].descriptor[1222], 93.8412f, 1e-4f);
00961 EXPECT_NEAR ((*uscds)[160].descriptor[1605], 0.f, 1e-4f);
00962 EXPECT_NEAR ((*uscds)[160].descriptor[1887], 32.6679f, 1e-4f);
00963
00964 EXPECT_NEAR ((*uscds)[168].descriptor[72], 65.3358f, 1e-4f);
00965 EXPECT_NEAR ((*uscds)[168].descriptor[430], 88.8147f, 1e-4f);
00966 EXPECT_NEAR ((*uscds)[168].descriptor[987], 0.f, 1e-4f);
00967 EXPECT_NEAR ((*uscds)[168].descriptor[1563], 128.273f, 1e-4f);
00968 EXPECT_NEAR ((*uscds)[168].descriptor[1915], 59.2098f, 1e-4f);
00969
00970
00971 boost::shared_ptr<vector<int> > test_indices (new vector<int> (0));
00972 for (size_t i = 0; i < cloud.size (); i+=3)
00973 test_indices->push_back (static_cast<int> (i));
00974
00975 PointCloud<Normal>::Ptr normals (new PointCloud<Normal> ());
00976 testSHOTIndicesAndSearchSurface<UniqueShapeContext<PointXYZ, ShapeContext1980>, PointXYZ, Normal, ShapeContext1980> (cloud.makeShared (), normals, test_indices);
00977 testSHOTLocalReferenceFrame<UniqueShapeContext<PointXYZ, ShapeContext1980>, PointXYZ, Normal, ShapeContext1980> (cloud.makeShared (), normals, test_indices);
00978 }
00979
00980
00981 int
00982 main (int argc, char** argv)
00983 {
00984 if (argc < 2)
00985 {
00986 std::cerr << "No test file given. Please download `bun0.pcd` and pass its path to the test." << std::endl;
00987 return (-1);
00988 }
00989
00990 if (loadPCDFile<PointXYZ> (argv[1], cloud) < 0)
00991 {
00992 std::cerr << "Failed to read test file. Please download `bun0.pcd` and pass its path to the test." << std::endl;
00993 return (-1);
00994 }
00995
00996 indices.resize (cloud.points.size ());
00997 for (size_t i = 0; i < indices.size (); ++i)
00998 indices[i] = static_cast<int> (i);
00999
01000 tree.reset (new search::KdTree<PointXYZ> (false));
01001 tree->setInputCloud (cloud.makeShared ());
01002
01003 testing::InitGoogleTest (&argc, argv);
01004 return (RUN_ALL_TESTS ());
01005 }
01006