00001 #include "../utest.h"
00002 #include <ciso646>
00003 #include <cmath>
00004
00005 using namespace std;
00006 using namespace PointMatcherSupport;
00007
00008
00009
00010
00011
00012
00013 class DataFilterTest: public IcpHelper
00014 {
00015 public:
00016
00017 virtual void SetUp()
00018 {
00019 icp.setDefault();
00020
00021
00022
00023
00024 icp.readingDataPointsFilters.clear();
00025 }
00026
00027
00028 virtual void TearDown() {}
00029
00030 void addFilter(string name, PM::Parameters params)
00031 {
00032 std::shared_ptr<PM::DataPointsFilter> testedDataPointFilter =
00033 PM::get().DataPointsFilterRegistrar.create(name, params);
00034
00035 icp.readingDataPointsFilters.push_back(testedDataPointFilter);
00036 }
00037
00038 void addFilter(string name)
00039 {
00040 std::shared_ptr<PM::DataPointsFilter> testedDataPointFilter =
00041 PM::get().DataPointsFilterRegistrar.create(name);
00042
00043 icp.readingDataPointsFilters.push_back(testedDataPointFilter);
00044 }
00045
00046 DP generateRandomDataPoints(int nbPoints = 100)
00047 {
00048 const int dimFeatures = 4;
00049 const int dimDescriptors = 3;
00050 const int dimTime = 2;
00051
00052 PM::Matrix randFeat = PM::Matrix::Random(dimFeatures, nbPoints);
00053 DP::Labels featLabels;
00054 featLabels.push_back(DP::Label("x", 1));
00055 featLabels.push_back(DP::Label("y", 1));
00056 featLabels.push_back(DP::Label("z", 1));
00057 featLabels.push_back(DP::Label("pad", 1));
00058
00059 PM::Matrix randDesc = PM::Matrix::Random(dimDescriptors, nbPoints);
00060 DP::Labels descLabels;
00061 descLabels.push_back(DP::Label("dummyDesc", 3));
00062
00063 PM::Int64Matrix randTimes = PM::Int64Matrix::Random(dimTime, nbPoints);
00064 DP::Labels timeLabels;
00065 timeLabels.push_back(DP::Label("dummyTime", 2));
00066
00067
00068 DP pointCloud = DP(randFeat, featLabels, randDesc, descLabels, randTimes, timeLabels);
00069
00070 return pointCloud;
00071 }
00072 };
00073
00074 TEST_F(DataFilterTest, IdentityDataPointsFilter)
00075 {
00076
00077 DP ref2DCopy(ref2D);
00078
00079
00080 addFilter("IdentityDataPointsFilter");
00081 icp.readingDataPointsFilters.apply(ref2DCopy);
00082 EXPECT_TRUE(ref2D == ref2DCopy);
00083 }
00084
00085 TEST_F(DataFilterTest, RemoveNaNDataPointsFilter)
00086 {
00087
00088 DP ref2DCopy(ref2D);
00089 int goodCount(0);
00090 const float nan(std::numeric_limits<float>::quiet_NaN());
00091 for (int i(0); i < ref2DCopy.features.cols(); ++i)
00092 {
00093 if (rand() % 3 == 0)
00094 {
00095 ref2DCopy.features(rand() % ref2DCopy.features.rows(), i) = nan;
00096 }
00097 else
00098 ++goodCount;
00099 }
00100
00101
00102 addFilter("RemoveNaNDataPointsFilter");
00103 icp.readingDataPointsFilters.apply(ref2DCopy);
00104 EXPECT_TRUE(ref2DCopy.features.cols() == goodCount);
00105 }
00106
00107 TEST_F(DataFilterTest, MaxDistDataPointsFilter)
00108 {
00109
00110 params = PM::Parameters();
00111 params["dim"] = "0";
00112 params["maxDist"] = toParam(6.0);
00113
00114
00115 params["dim"] = "0";
00116 icp.readingDataPointsFilters.clear();
00117 addFilter("MaxDistDataPointsFilter", params);
00118 validate2dTransformation();
00119 validate3dTransformation();
00120
00121
00122 params["dim"] = "1";
00123 icp.readingDataPointsFilters.clear();
00124 addFilter("MaxDistDataPointsFilter", params);
00125 validate2dTransformation();
00126 validate3dTransformation();
00127
00128
00129 params["dim"] = "2";
00130 icp.readingDataPointsFilters.clear();
00131 addFilter("MaxDistDataPointsFilter", params);
00132 EXPECT_ANY_THROW(validate2dTransformation());
00133 validate3dTransformation();
00134
00135
00136 params["dim"] = "-1";
00137 icp.readingDataPointsFilters.clear();
00138 addFilter("MaxDistDataPointsFilter", params);
00139 validate2dTransformation();
00140 validate3dTransformation();
00141
00142
00143 params["dim"] = "3";
00144
00145 EXPECT_ANY_THROW(addFilter("MaxDistDataPointsFilter", params));
00146
00147 }
00148
00149 TEST_F(DataFilterTest, MinDistDataPointsFilter)
00150 {
00151
00152 params = PM::Parameters();
00153 params["dim"] = "0";
00154 params["minDist"] = toParam(0.05);
00155
00156
00157 params["dim"] = "0";
00158 icp.readingDataPointsFilters.clear();
00159 addFilter("MinDistDataPointsFilter", params);
00160 validate2dTransformation();
00161 validate3dTransformation();
00162
00163
00164 params["dim"] = "1";
00165 icp.readingDataPointsFilters.clear();
00166 addFilter("MinDistDataPointsFilter", params);
00167 validate2dTransformation();
00168 validate3dTransformation();
00169
00170
00171
00172 params["dim"] = "2";
00173 icp.readingDataPointsFilters.clear();
00174 addFilter("MinDistDataPointsFilter", params);
00175 EXPECT_ANY_THROW(validate2dTransformation());
00176 validate3dTransformation();
00177
00178
00179 params["dim"] = "-1";
00180 icp.readingDataPointsFilters.clear();
00181 addFilter("MinDistDataPointsFilter", params);
00182 validate2dTransformation();
00183 validate3dTransformation();
00184
00185 }
00186
00187 TEST_F(DataFilterTest, MaxQuantileOnAxisDataPointsFilter)
00188 {
00189
00190 string ratio = "0.95";
00191 params = PM::Parameters();
00192 params["dim"] = "0";
00193 params["ratio"] = ratio;
00194
00195
00196 params["dim"] = "0";
00197 icp.readingDataPointsFilters.clear();
00198 addFilter("MaxQuantileOnAxisDataPointsFilter", params);
00199 validate2dTransformation();
00200 validate3dTransformation();
00201
00202
00203 params["dim"] = "1";
00204 icp.readingDataPointsFilters.clear();
00205 addFilter("MaxQuantileOnAxisDataPointsFilter", params);
00206 validate2dTransformation();
00207 validate3dTransformation();
00208
00209
00210 params["dim"] = "2";
00211 icp.readingDataPointsFilters.clear();
00212 addFilter("MaxQuantileOnAxisDataPointsFilter", params);
00213 EXPECT_ANY_THROW(validate2dTransformation());
00214 validate3dTransformation();
00215 }
00216
00217
00218
00219 TEST_F(DataFilterTest, SurfaceNormalDataPointsFilter)
00220 {
00221
00222 params = PM::Parameters();
00223 params["knn"] = "5";
00224 params["epsilon"] = "0.1";
00225 params["keepNormals"] = "1";
00226 params["keepDensities"] = "1";
00227 params["keepEigenValues"] = "1";
00228 params["keepEigenVectors"] = "1" ;
00229 params["keepMatchedIds"] = "1" ;
00230
00231
00232 addFilter("SurfaceNormalDataPointsFilter", params);
00233 validate2dTransformation();
00234 validate3dTransformation();
00235
00236
00237
00238
00239
00240 }
00241
00242 TEST_F(DataFilterTest, MaxDensityDataPointsFilter)
00243 {
00244
00245 vector<double> ratio = {100, 1000, 5000};
00246
00247 for(unsigned i=0; i < ratio.size(); i++)
00248 {
00249 icp.readingDataPointsFilters.clear();
00250 params = PM::Parameters();
00251 params["knn"] = "5";
00252 params["epsilon"] = "0.1";
00253 params["keepNormals"] = "0";
00254 params["keepDensities"] = "1";
00255 params["keepEigenValues"] = "0";
00256 params["keepEigenVectors"] = "0" ;
00257 params["keepMatchedIds"] = "0" ;
00258
00259 addFilter("SurfaceNormalDataPointsFilter", params);
00260
00261 params = PM::Parameters();
00262 params["maxDensity"] = toParam(ratio[i]);
00263
00264 addFilter("MaxDensityDataPointsFilter", params);
00265
00266
00267
00268
00269
00270
00271
00272
00273 validate3dTransformation();
00274
00275 double nbInitPts = data3D.features.cols();
00276 double nbRemainingPts = icp.getPrefilteredReadingPtsCount();
00277 EXPECT_TRUE(nbRemainingPts < nbInitPts);
00278 }
00279 }
00280
00281 TEST_F(DataFilterTest, SamplingSurfaceNormalDataPointsFilter)
00282 {
00283
00284 params = PM::Parameters();
00285 params["knn"] = "5";
00286 params["averageExistingDescriptors"] = "1";
00287 params["keepNormals"] = "1";
00288 params["keepDensities"] = "1";
00289 params["keepEigenValues"] = "1";
00290 params["keepEigenVectors"] = "1";
00291
00292 addFilter("SamplingSurfaceNormalDataPointsFilter", params);
00293 validate2dTransformation();
00294 validate3dTransformation();
00295
00296 }
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325 TEST_F(DataFilterTest, GestaltDataPointsFilter)
00326 {
00327
00328 params = PM::Parameters();
00329 params["knn"] = "5";
00330 params["averageExistingDescriptors"] = "1";
00331 params["keepNormals"] = "1";
00332 params["keepEigenValues"] = "1";
00333 params["keepEigenVectors"] = "1";
00334 params["maxBoxDim"] = "1";
00335 params["keepMeans"] = "1";
00336 params["keepCovariances"] = "1";
00337 params["keepGestaltFeatures"] = "1";
00338 params["radius"] = "1";
00339 params["ratio"] = "0.5";
00340
00341 addFilter("GestaltDataPointsFilter", params);
00342 validate3dTransformation();
00343 }
00344
00345 TEST_F(DataFilterTest, OrientNormalsDataPointsFilter)
00346 {
00347
00348 std::shared_ptr<PM::DataPointsFilter> extraDataPointFilter;
00349 extraDataPointFilter = PM::get().DataPointsFilterRegistrar.create(
00350 "SurfaceNormalDataPointsFilter");
00351 icp.readingDataPointsFilters.push_back(extraDataPointFilter);
00352 addFilter("ObservationDirectionDataPointsFilter");
00353 addFilter("OrientNormalsDataPointsFilter", {
00354 {"towardCenter", toParam(false)}
00355 }
00356 );
00357 validate2dTransformation();
00358 validate3dTransformation();
00359 }
00360
00361
00362 TEST_F(DataFilterTest, RandomSamplingDataPointsFilter)
00363 {
00364 vector<double> prob = {0.80, 0.85, 0.90, 0.95};
00365 for(unsigned i = 0; i < prob.size(); i++)
00366 {
00367
00368 params = PM::Parameters();
00369 params["prob"] = toParam(prob[i]);
00370
00371 icp.readingDataPointsFilters.clear();
00372 addFilter("RandomSamplingDataPointsFilter", params);
00373 validate2dTransformation();
00374 validate3dTransformation();
00375 }
00376 }
00377
00378 TEST_F(DataFilterTest, FixStepSamplingDataPointsFilter)
00379 {
00380 vector<unsigned> steps = {1, 2, 3};
00381 for(unsigned i=0; i<steps.size(); i++)
00382 {
00383
00384 params = PM::Parameters();
00385 params["startStep"] = toParam(steps[i]);
00386
00387 icp.readingDataPointsFilters.clear();
00388 addFilter("FixStepSamplingDataPointsFilter", params);
00389 validate2dTransformation();
00390 validate3dTransformation();
00391 }
00392 }
00393
00394 TEST_F(DataFilterTest, MaxPointCountDataPointsFilter)
00395 {
00396 DP cloud = ref3D;
00397
00398 const size_t maxCount = 1000;
00399
00400 params = PM::Parameters();
00401 params["seed"] = "42";
00402 params["maxCount"] = toParam(maxCount);
00403
00404 std::shared_ptr<PM::DataPointsFilter> maxPtsFilter =
00405 PM::get().DataPointsFilterRegistrar.create("MaxPointCountDataPointsFilter", params);
00406
00407 DP filteredCloud = maxPtsFilter->filter(cloud);
00408
00409
00410 EXPECT_GT(cloud.getNbPoints(), filteredCloud.getNbPoints());
00411 EXPECT_EQ(cloud.getDescriptorDim(), filteredCloud.getDescriptorDim());
00412 EXPECT_EQ(cloud.getTimeDim(), filteredCloud.getTimeDim());
00413
00414 EXPECT_EQ(filteredCloud.getNbPoints(), maxCount);
00415
00416
00417 DP filteredCloud2 = maxPtsFilter->filter(cloud);
00418
00419 EXPECT_TRUE(filteredCloud == filteredCloud2);
00420
00421
00422 params.clear();
00423 params["seed"] = "1";
00424 params["maxCount"] = toParam(maxCount);
00425
00426 std::shared_ptr<PM::DataPointsFilter> maxPtsFilter2 =
00427 PM::get().DataPointsFilterRegistrar.create("MaxPointCountDataPointsFilter", params);
00428
00429 DP filteredCloud3 = maxPtsFilter2->filter(cloud);
00430
00431 EXPECT_FALSE(filteredCloud3 == filteredCloud2);
00432
00433 EXPECT_EQ(filteredCloud3.getNbPoints(), maxCount);
00434
00435 EXPECT_EQ(filteredCloud3.getNbPoints(), filteredCloud2.getNbPoints());
00436 EXPECT_EQ(filteredCloud3.getDescriptorDim(), filteredCloud2.getDescriptorDim());
00437 EXPECT_EQ(filteredCloud3.getTimeDim(), filteredCloud2.getTimeDim());
00438
00439
00440 icp.readingDataPointsFilters.clear();
00441 addFilter("MaxPointCountDataPointsFilter", params);
00442 validate2dTransformation();
00443 validate3dTransformation();
00444 }
00445
00446 TEST_F(DataFilterTest, OctreeGridDataPointsFilter)
00447 {
00448 const unsigned int nbPts = 60000;
00449 const DP cloud = generateRandomDataPoints(nbPts);
00450 params = PM::Parameters();
00451
00452 std::shared_ptr<PM::DataPointsFilter> octreeFilter;
00453
00454 for(const int meth : {0,1,2,3})
00455 for(const size_t maxData : {1,5})
00456 for(const float maxSize : {0.,0.05})
00457 {
00458 params.clear();
00459 params["maxPointByNode"] = toParam(maxData);
00460 params["maxSizeByNode"] = toParam(maxSize);
00461 params["samplingMethod"] = toParam(meth);
00462 params["buildParallel"] = "1";
00463
00464 octreeFilter = PM::get().DataPointsFilterRegistrar.create("OctreeGridDataPointsFilter", params);
00465
00466 const DP filteredCloud = octreeFilter->filter(cloud);
00467
00468 if(maxData==1 and maxSize==0.)
00469 {
00470
00471
00472
00473
00474 EXPECT_EQ(cloud.getNbPoints(), filteredCloud.getNbPoints());
00475 EXPECT_EQ(cloud.getDescriptorDim(), filteredCloud.getDescriptorDim());
00476 EXPECT_EQ(cloud.getTimeDim(), filteredCloud.getTimeDim());
00477
00478 EXPECT_EQ(filteredCloud.getNbPoints(), nbPts);
00479 }
00480 else
00481 {
00482
00483 EXPECT_GT(cloud.getNbPoints(), filteredCloud.getNbPoints());
00484 }
00485
00486 icp.readingDataPointsFilters.clear();
00487 addFilter("OctreeGridDataPointsFilter", params);
00488 validate2dTransformation();
00489 validate3dTransformation();
00490 }
00491 }
00492
00493 TEST_F(DataFilterTest, NormalSpaceDataPointsFilter)
00494 {
00495 const size_t nbPts = 60000;
00496 DP cloud = generateRandomDataPoints(nbPts);
00497 params = PM::Parameters();
00498
00499
00500 const size_t nbPts3D = ref3D.getNbPoints();
00501
00502 std::shared_ptr<PM::DataPointsFilter> nssFilter;
00503
00504
00505 auto paramsNorm = PM::Parameters();
00506 paramsNorm["knn"] = "5";
00507 paramsNorm["epsilon"] = "0.1";
00508 paramsNorm["keepNormals"] = "1";
00509 std::shared_ptr<PM::DataPointsFilter> normalFilter = PM::get().DataPointsFilterRegistrar.create("SurfaceNormalDataPointsFilter", paramsNorm);
00510
00511 normalFilter->inPlaceFilter(cloud);
00512
00513
00514 std::vector<size_t> samples = { 1500, 5000, nbPts, nbPts3D};
00515 for(const float epsilon : {M_PI/6., M_PI/32., M_PI/64.})
00516 for(const size_t nbSample : samples)
00517 {
00518 icp.readingDataPointsFilters.clear();
00519
00520 params.clear();
00521 params["epsilon"] = toParam(epsilon);
00522 params["nbSample"] = toParam(nbSample);
00523
00524 nssFilter = PM::get().DataPointsFilterRegistrar.create("NormalSpaceDataPointsFilter", params);
00525
00526 addFilter("SurfaceNormalDataPointsFilter", paramsNorm);
00527 addFilter("NormalSpaceDataPointsFilter", params);
00528
00529 const DP filteredCloud = nssFilter->filter(cloud);
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543 if (nbSample == nbPts)
00544 {
00545
00546 EXPECT_EQ(cloud.getNbPoints(), filteredCloud.getNbPoints());
00547 EXPECT_EQ(cloud.getDescriptorDim(), filteredCloud.getDescriptorDim());
00548 EXPECT_EQ(cloud.getTimeDim(), filteredCloud.getTimeDim());
00549
00550 EXPECT_EQ(filteredCloud.getNbPoints(), nbPts);
00551 }
00552
00553 validate3dTransformation();
00554 EXPECT_GE(cloud.getNbPoints(), filteredCloud.getNbPoints());
00555 }
00556 }
00557
00558 TEST_F(DataFilterTest, CovarianceSamplingDataPointsFilter)
00559 {
00560 const size_t nbPts = 60000;
00561 DP cloud = generateRandomDataPoints(nbPts);
00562 params = PM::Parameters();
00563
00564 const size_t nbPts3D = ref3D.getNbPoints();
00565
00566 std::shared_ptr<PM::DataPointsFilter> covsFilter;
00567
00568
00569 auto paramsNorm = PM::Parameters();
00570 paramsNorm["knn"] = "5";
00571 paramsNorm["epsilon"] = "0.1";
00572 paramsNorm["keepNormals"] = "1";
00573 std::shared_ptr<PM::DataPointsFilter> normalFilter = PM::get().DataPointsFilterRegistrar.create("SurfaceNormalDataPointsFilter", paramsNorm);
00574
00575 normalFilter->inPlaceFilter(cloud);
00576
00577
00578 std::vector<size_t> samples = {500, 1500, 5000, nbPts, nbPts3D};
00579 for(const size_t nbSample : samples)
00580 {
00581 icp.readingDataPointsFilters.clear();
00582
00583 params.clear();
00584 params["nbSample"] = toParam(nbSample);
00585
00586 covsFilter = PM::get().DataPointsFilterRegistrar.create("CovarianceSamplingDataPointsFilter", params);
00587
00588 addFilter("SurfaceNormalDataPointsFilter", paramsNorm);
00589 addFilter("CovarianceSamplingDataPointsFilter", params);
00590
00591 const DP filteredCloud = covsFilter->filter(cloud);
00592
00593 if (nbSample == nbPts3D)
00594 {
00595 EXPECT_EQ(filteredCloud.getNbPoints(), nbPts3D);
00596 }
00597 else if (nbSample == nbPts)
00598 {
00599
00600 EXPECT_EQ(cloud.getNbPoints(), filteredCloud.getNbPoints());
00601 EXPECT_EQ(cloud.getDescriptorDim(), filteredCloud.getDescriptorDim());
00602 EXPECT_EQ(cloud.getTimeDim(), filteredCloud.getTimeDim());
00603
00604 EXPECT_EQ(filteredCloud.getNbPoints(), nbPts);
00605 }
00606
00607 validate3dTransformation();
00608 EXPECT_GE(cloud.getNbPoints(), filteredCloud.getNbPoints());
00609 }
00610 }
00611
00612 TEST_F(DataFilterTest, VoxelGridDataPointsFilter)
00613 {
00614
00615 DP cloud = generateRandomDataPoints();
00616
00617 params = PM::Parameters();
00618 params["vSizeX"] = "0.5";
00619 params["vSizeY"] = "0.5";
00620 params["vSizeZ"] = "0.5";
00621 params["useCentroid"] = toParam(true);
00622 params["averageExistingDescriptors"] = toParam(true);
00623
00624 std::shared_ptr<PM::DataPointsFilter> voxelFilter =
00625 PM::get().DataPointsFilterRegistrar.create("VoxelGridDataPointsFilter", params);
00626
00627 DP filteredCloud = voxelFilter->filter(cloud);
00628
00629 EXPECT_GT(cloud.getNbPoints(), filteredCloud.getNbPoints());
00630 EXPECT_EQ(cloud.getDescriptorDim(), filteredCloud.getDescriptorDim());
00631 EXPECT_EQ(cloud.getTimeDim(), filteredCloud.getTimeDim());
00632
00633
00634 vector<bool> useCentroid = {false, true};
00635 vector<bool> averageExistingDescriptors = {false, true};
00636 for (unsigned i = 0 ; i < useCentroid.size() ; i++)
00637 {
00638 for (unsigned j = 0; j < averageExistingDescriptors.size(); j++)
00639 {
00640 params = PM::Parameters();
00641 params["vSizeX"] = "0.02";
00642 params["vSizeY"] = "0.02";
00643 params["vSizeZ"] = "0.02";
00644 params["useCentroid"] = toParam(true);
00645 params["averageExistingDescriptors"] = toParam(true);
00646
00647 icp.readingDataPointsFilters.clear();
00648 addFilter("VoxelGridDataPointsFilter", params);
00649 validate2dTransformation();
00650 }
00651 }
00652
00653 for (unsigned i = 0 ; i < useCentroid.size() ; i++)
00654 {
00655 for (unsigned j = 0; j < averageExistingDescriptors.size(); j++)
00656 {
00657 params = PM::Parameters();
00658 params["vSizeX"] = "1";
00659 params["vSizeY"] = "1";
00660 params["vSizeZ"] = "1";
00661 params["useCentroid"] = toParam(true);
00662 params["averageExistingDescriptors"] = toParam(true);
00663
00664 icp.readingDataPointsFilters.clear();
00665 addFilter("VoxelGridDataPointsFilter", params);
00666 validate3dTransformation();
00667 }
00668 }
00669 }
00670
00671 TEST_F(DataFilterTest, CutAtDescriptorThresholdDataPointsFilter)
00672 {
00673
00674 vector<double> thresholds = {100, 1000, 5000};
00675
00676 DP ref3Ddensities = ref3D;
00677
00678 icp.readingDataPointsFilters.clear();
00679 params = PM::Parameters();
00680 params["knn"] = "5";
00681 params["epsilon"] = "0.1";
00682 params["keepNormals"] = "0";
00683 params["keepDensities"] = "1";
00684 params["keepEigenValues"] = "0";
00685 params["keepEigenVectors"] = "0";
00686 params["keepMatchedIds"] = "0";
00687
00688
00689 addFilter("SurfaceNormalDataPointsFilter", params);
00690 icp.readingDataPointsFilters.apply(ref3Ddensities);
00691
00692 for(unsigned i=0; i < thresholds.size(); i++)
00693 {
00694 int belowCount=0;
00695 int aboveCount=0;
00696
00697
00698 PM::DataPoints::View densities = ref3Ddensities.getDescriptorViewByName("densities");
00699 for (unsigned j=0; j < densities.cols(); ++j)
00700 {
00701 if (densities(0, j) <= thresholds[i])
00702 {
00703 ++belowCount;
00704 }
00705 if (densities(0, j) >= thresholds[i])
00706 {
00707 ++aboveCount;
00708 }
00709 }
00710
00711 for(bool useLargerThan(true); useLargerThan; useLargerThan=false)
00712 {
00713 DP ref3DCopy = ref3Ddensities;
00714
00715 icp.readingDataPointsFilters.clear();
00716 params = PM::Parameters();
00717 params["descName"] = toParam("densities");
00718 params["useLargerThan"] = toParam(useLargerThan);
00719 params["threshold"] = toParam(thresholds[i]);
00720
00721
00722 addFilter("CutAtDescriptorThresholdDataPointsFilter", params);
00723 icp.readingDataPointsFilters.apply(ref3DCopy);
00724 if (useLargerThan)
00725 {
00726 EXPECT_TRUE(ref3DCopy.features.cols() == belowCount);
00727 }
00728 else
00729 {
00730 EXPECT_TRUE(ref3DCopy.features.cols() == aboveCount);
00731 }
00732 }
00733 }
00734 }
00735
00736 TEST_F(DataFilterTest, DistanceLimitDataPointsFilter)
00737 {
00738 params = PM::Parameters();
00739 params["dim"] = "0";
00740 params["dist"] = toParam(6.0);
00741 params["removeInside"] = "0";
00742
00743
00744 params["dim"] = "0";
00745 icp.readingDataPointsFilters.clear();
00746 addFilter("DistanceLimitDataPointsFilter", params);
00747 validate2dTransformation();
00748 validate3dTransformation();
00749
00750
00751 params["dim"] = "1";
00752 icp.readingDataPointsFilters.clear();
00753 addFilter("DistanceLimitDataPointsFilter", params);
00754 validate2dTransformation();
00755 validate3dTransformation();
00756
00757
00758 params["dim"] = "2";
00759 icp.readingDataPointsFilters.clear();
00760 addFilter("DistanceLimitDataPointsFilter", params);
00761 EXPECT_ANY_THROW(validate2dTransformation());
00762 validate3dTransformation();
00763
00764
00765 params["dim"] = "-1";
00766 icp.readingDataPointsFilters.clear();
00767 addFilter("DistanceLimitDataPointsFilter", params);
00768 validate2dTransformation();
00769 validate3dTransformation();
00770
00771
00772 params["dim"] = "3";
00773
00774 EXPECT_ANY_THROW(addFilter("DistanceLimitDataPointsFilter", params));
00775
00776
00777 params = PM::Parameters();
00778 params["dim"] = "0";
00779 params["dist"] = toParam(0.05);
00780 params["removeInside"] = "1";
00781
00782
00783 params["dim"] = "0";
00784 icp.readingDataPointsFilters.clear();
00785 addFilter("DistanceLimitDataPointsFilter", params);
00786 validate2dTransformation();
00787 validate3dTransformation();
00788
00789
00790 params["dim"] = "1";
00791 icp.readingDataPointsFilters.clear();
00792 addFilter("DistanceLimitDataPointsFilter", params);
00793 validate2dTransformation();
00794 validate3dTransformation();
00795
00796
00797
00798 params["dim"] = "2";
00799 icp.readingDataPointsFilters.clear();
00800 addFilter("DistanceLimitDataPointsFilter", params);
00801 EXPECT_ANY_THROW(validate2dTransformation());
00802 validate3dTransformation();
00803
00804
00805 params["dim"] = "-1";
00806 icp.readingDataPointsFilters.clear();
00807 addFilter("DistanceLimitDataPointsFilter", params);
00808 validate2dTransformation();
00809 validate3dTransformation();
00810 }
00811
00812 TEST_F(DataFilterTest, SameFilterInstanceTwice)
00813 {
00814 params = PM::Parameters();
00815
00816 std::shared_ptr<PM::DataPointsFilter> df = PM::get().DataPointsFilterRegistrar.create("MaxPointCountDataPointsFilter", params);
00817
00818 icp.referenceDataPointsFilters.push_back(df);
00819 icp.readingDataPointsFilters.push_back(df);
00820 }
00821
00822 TEST_F(DataFilterTest, RemoveSensorBiasDataPointsFilter)
00823 {
00824 const size_t nbPts = 6;
00825 const double expectedErrors_LMS1xx[6] = {0., -0.0015156, -0.059276,
00826 0., -0.002311, -0.163689};
00827 const double expectedErrors_HDL32E[6] = {0., -0.002945, -0.075866,
00828 0., -0.002998,-0.082777 };
00829
00830 PM::Matrix points = (PM::Matrix(3,6) << 1, 1, 1, 5, 5, 5,
00831 0, 0, 0, 0, 0, 0,
00832 0, 0, 0, 0, 0, 0).finished();
00833 DP::Labels pointsLabels;
00834 pointsLabels.push_back(DP::Label("x", 1));
00835 pointsLabels.push_back(DP::Label("y", 1));
00836 pointsLabels.push_back(DP::Label("z", 1));
00837 pointsLabels.push_back(DP::Label("pad", 1));
00838
00839 PM::Matrix desc = (PM::Matrix(4,6) << 0., 0.7854, 1.4835, 0., 0.7854, 1.4835,
00840 -1, -1, -1, -5, -5, -5,
00841 0, 0, 0, 0, 0, 0,
00842 0, 0, 0, 0, 0, 0).finished();
00843
00844 PM::Matrix desc2 = (PM::Matrix(4,6) << 0., 0.7854, std::nanf(""), 0., 0.7854, M_PI_2,
00845 -1, -1, -1, -5, -5, -5,
00846 0, 0, 0, 0, 0, 0,
00847 0, 0, 0, 0, 0, 0).finished();
00848 DP::Labels descLabels;
00849 descLabels.push_back(DP::Label("incidenceAngles", 1));
00850 descLabels.push_back(DP::Label("observationDirections", 3));
00851
00852 PM::Int64Matrix randTimes = PM::Int64Matrix::Random(2, nbPts);
00853 DP::Labels timeLabels;
00854 timeLabels.push_back(DP::Label("dummyTime", 2));
00855
00856
00857 DP pointCloud = DP(points, pointsLabels, desc, descLabels, randTimes, timeLabels);
00858
00859
00860 PM::Parameters parameters;
00861 parameters["sensorType"] = toParam(0);
00862 std::shared_ptr<PM::DataPointsFilter> removeSensorBiasFilter = PM::get().DataPointsFilterRegistrar.create("RemoveSensorBiasDataPointsFilter", parameters);
00863 DP resultCloud = removeSensorBiasFilter->filter(pointCloud);
00864 EXPECT_EQ(pointCloud.getNbPoints(), resultCloud.getNbPoints());
00865
00866 for(std::size_t i = 0; i< nbPts; ++i)
00867 {
00868 const double error = pointCloud.features.col(i).norm() - resultCloud.features.col(i).norm();
00869 EXPECT_NEAR(expectedErrors_LMS1xx[i], error, 1e-3);
00870 }
00871
00872 parameters["sensorType"] = toParam(1);
00873 removeSensorBiasFilter = PM::get().DataPointsFilterRegistrar.create("RemoveSensorBiasDataPointsFilter", parameters);
00874 resultCloud = removeSensorBiasFilter->filter(pointCloud);
00875
00876 for(std::size_t i = 0; i< nbPts; ++i)
00877 {
00878 const double error = pointCloud.features.col(i).norm() - resultCloud.features.col(i).norm();
00879 EXPECT_NEAR(expectedErrors_HDL32E[i], error, 1e-4);
00880 }
00881
00882
00883
00884 pointCloud = DP(points, pointsLabels, desc2, descLabels, randTimes, timeLabels);
00885
00886 parameters["sensorType"] = toParam(0);
00887 parameters["angleThreshold"] = toParam(30.);
00888 removeSensorBiasFilter = PM::get().DataPointsFilterRegistrar.create("RemoveSensorBiasDataPointsFilter", parameters);
00889 resultCloud = removeSensorBiasFilter->filter(pointCloud);
00890
00891
00892 EXPECT_EQ(pointCloud.getNbPoints()-4, resultCloud.getNbPoints());
00893 }