00001 #include <ndt_map.h>
00002 #include <oc_tree.h>
00003 #include <pointcloud_utils.h>
00004
00005 #include "pcl/point_cloud.h"
00006 #include "sensor_msgs/PointCloud2.h"
00007 #include "pcl/io/pcd_io.h"
00008 #include "pcl/features/feature.h"
00009 #include <cstdio>
00010
00011 #include <pcl/filters/radius_outlier_removal.h>
00012 #include<iostream>
00013
00014 #include <pcl/kdtree/kdtree_flann.h>
00015
00016 using namespace std;
00017
00018 class OneTestResult
00019 {
00020 public:
00021 Eigen::VectorXi tp, fp, tn, fn;
00022 };
00023
00024 class Tester
00025 {
00026 private:
00027 pcl::PointCloud<pcl::PointXYZ> filterRange(pcl::PointCloud<pcl::PointXYZ> &rawCloud);
00028 pcl::PointCloud<pcl::PointXYZ> filterDensity(pcl::PointCloud<pcl::PointXYZ> &rawCloud);
00029 void computePartition(pcl::PointCloud<pcl::PointXYZ> &rawCloud);
00030 pcl::PointCloud<pcl::PointXYZ> generateNegatives(pcl::PointCloud<pcl::PointXYZ> &rawCloud);
00031
00032 void countResults(OneTestResult &res, std::vector<double> &scoresPositives, std::vector<double> &scoresNegatives);
00033
00034 int nPartitions, nThresholdDiscretisations;
00035 double fixed_threshold;
00036 pcl::PointXYZ origin;
00037 pcl::PointCloud<pcl::PointXYZ> negCloud;
00038 double min_offset, max_offset, maxScannerRange;
00039
00040 public:
00041 Tester() : nPartitions(10),fixed_threshold(0.05),min_offset(0.1),max_offset(2),nThresholdDiscretisations(100)
00042 {
00043 maxScannerRange = 100;
00044 }
00045 Tester(int _nPartitions, double _min_offset, double _max_offset, int _threshold, double _maxScannerRange, int ndiscr = 100) : nPartitions(_nPartitions),
00046 fixed_threshold(_threshold),min_offset(_min_offset),max_offset(_max_offset),maxScannerRange(_maxScannerRange),nThresholdDiscretisations(ndiscr)
00047 {
00048 }
00049
00050 ~Tester()
00051 {
00052 }
00053
00054 void runTestsNDTTree(pcl::PointCloud<pcl::PointXYZ> &modelCloud, pcl::PointCloud<pcl::PointXYZ> &testCloud,
00055 double resolutionMin, double resolutionMax, pcl::PointXYZ _origin, OneTestResult &res);
00056
00057 public:
00058 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
00059 };
00060
00061 pcl::PointCloud<pcl::PointXYZ> Tester::filterRange(pcl::PointCloud<pcl::PointXYZ> &rawCloud)
00062 {
00063 pcl::PointCloud<pcl::PointXYZ> pc;
00064 for(unsigned int i=0; i<rawCloud.points.size(); i++)
00065 {
00066 pcl::PointXYZ pt = rawCloud.points[i];
00067 double d = sqrt(pt.x*pt.x+pt.y*pt.y+pt.z*pt.z);
00068 if(d<this->maxScannerRange)
00069 {
00070 pc.points.push_back(pt);
00071 }
00072 }
00073 return pc;
00074 }
00075
00076
00077 pcl::PointCloud<pcl::PointXYZ> Tester::filterDensity(pcl::PointCloud<pcl::PointXYZ> &rawCloud)
00078 {
00079 pcl::KdTreeFLANN<pcl::PointXYZ> pointsTree;
00080 pcl::PointCloud<pcl::PointXYZ> pc;
00081 double radius = 1;
00082 int n_neigh = 3;
00083 std::vector<int> id;
00084 std::vector<float> dist;
00085 id.reserve(n_neigh);
00086 dist.reserve(n_neigh);
00087
00088
00089
00090
00091 pcl::PointCloud<pcl::PointXYZ>::Ptr pcptr(new pcl::PointCloud<pcl::PointXYZ>());
00092 *pcptr = rawCloud;
00093
00094 pointsTree.setInputCloud(pcptr);
00095
00096 std::cout<<"filtering on density....\n before: "<<pc.points.size()<<" "<<pcptr->points.size()<<std::endl;
00097 for (int i=0; i<pcptr->points.size(); ++i)
00098 {
00099 if(!pointsTree.nearestKSearch(pcptr->points[i],n_neigh,id,dist)) continue;
00100 if(dist.back() > radius) continue;
00101 pc.push_back(pcptr->points[i]);
00102 }
00103
00104 std::cout<<"after: "<<pc.points.size()<<std::endl;
00105
00106 return pc;
00107 }
00108
00109
00110 pcl::PointCloud<pcl::PointXYZ> Tester::generateNegatives(pcl::PointCloud<pcl::PointXYZ> &rawCloud)
00111 {
00112
00113 pcl::PointCloud<pcl::PointXYZ> res;
00114 res.points.clear();
00115 pcl::PointXYZ neg;
00116 for(unsigned int i=0; i<rawCloud.points.size(); i++)
00117 {
00118
00119 double rand_offset = min_offset + (max_offset-min_offset)*
00120 (double)rand()/(double)RAND_MAX;
00121
00122 neg.x = (rawCloud.points[i].x-origin.x);
00123 neg.y = (rawCloud.points[i].y-origin.y);
00124 neg.z = (rawCloud.points[i].z-origin.z);
00125 double len = sqrt(neg.x*neg.x + neg.y*neg.y + neg.z*neg.z);
00126 double factor = (len - rand_offset) / len;
00127 factor = (factor < 0) ? 0 : factor;
00128
00129 neg.x = factor*(rawCloud.points[i].x-origin.x) + origin.x;
00130 neg.y = factor*(rawCloud.points[i].y-origin.y) + origin.y;
00131 neg.z = factor*(rawCloud.points[i].z-origin.z) + origin.z;
00132
00133 res.points.push_back(neg);
00134 }
00135 return res;
00136 }
00137
00138 void Tester::countResults(OneTestResult &res, std::vector<double> &scoresPositives, std::vector<double> &scoresNegatives)
00139 {
00140
00141 res.tp = Eigen::VectorXi (nThresholdDiscretisations,1);
00142 res.fp = Eigen::VectorXi (nThresholdDiscretisations,1);
00143 res.tn = Eigen::VectorXi (nThresholdDiscretisations,1);
00144 res.fn = Eigen::VectorXi (nThresholdDiscretisations,1);
00145
00146 res.tp.setZero();
00147 res.fp.setZero();
00148 res.tn.setZero();
00149 res.fn.setZero();
00150
00151 Eigen::VectorXi tmpVec (nThresholdDiscretisations,1);
00152 Eigen::Block<Eigen::VectorXi> *bl;
00153
00154
00155 for(unsigned int i=0; i<scoresPositives.size(); i++)
00156 {
00157 if(scoresPositives[i] <0 || scoresPositives[i]>1)
00158 {
00159 std::cout<<"The horror! "<<scoresPositives[i]<<std::endl;
00160 }
00161 int idx = floor(scoresPositives[i]*nThresholdDiscretisations);
00162
00163 tmpVec.setZero();
00164 bl = new Eigen::Block<Eigen::VectorXi>(tmpVec,0,0,idx,1);
00165 bl->setOnes();
00166 res.tp += tmpVec;
00167 delete bl;
00168
00169
00170 tmpVec.setZero();
00171 bl = new Eigen::Block<Eigen::VectorXi>(tmpVec,idx,0,nThresholdDiscretisations-idx,1);
00172 bl->setOnes();
00173 res.fn += tmpVec;
00174 delete bl;
00175 }
00176
00177 for(unsigned int i=0; i<scoresNegatives.size(); i++)
00178 {
00179 if(scoresNegatives[i] <0 || scoresNegatives[i]>1)
00180 {
00181 std::cout<<"The horror! "<<scoresNegatives[i]<<std::endl;
00182 }
00183 int idx = floor(scoresNegatives[i]*nThresholdDiscretisations);
00184
00185 tmpVec.setZero();
00186 bl = new Eigen::Block<Eigen::VectorXi>(tmpVec,0,0,idx,1);
00187 bl->setOnes();
00188 res.fp += tmpVec;
00189 delete bl;
00190
00191
00192 tmpVec.setZero();
00193 bl = new Eigen::Block<Eigen::VectorXi>(tmpVec,idx,0,nThresholdDiscretisations-idx,1);
00194 bl->setOnes();
00195 res.tn += tmpVec;
00196 delete bl;
00197 }
00198 }
00199
00200 void Tester::runTestsNDTTree(pcl::PointCloud<pcl::PointXYZ> &rawCloud, pcl::PointCloud<pcl::PointXYZ> >Cloud,
00201 double resolutionMin, double resolutionMax, pcl::PointXYZ _origin, OneTestResult &res)
00202 {
00203
00204 std::vector<double> scoresPositives, scoresNegatives;
00205
00206 gtCloud = filterRange(gtCloud);
00207 gtCloud = filterDensity(gtCloud);
00208 negCloud = generateNegatives(gtCloud);
00209
00210 rawCloud = filterRange(rawCloud);
00211
00212 lslgeneric::OctTree<pcl::PointXYZ> prototype;
00213 prototype.setParameters(resolutionMax,resolutionMin,10);
00214
00215
00216
00217
00218
00219 lslgeneric::NDTMap<pcl::PointXYZ> map(&prototype);
00220 map.loadPointCloud(rawCloud);
00221 map.computeNDTCells();
00222
00223 for(unsigned int i =0; i<gtCloud.points.size(); i++)
00224 {
00225 scoresPositives.push_back(map.getLikelihoodForPoint(gtCloud.points[i]));
00226 }
00227 for(unsigned int i =0; i<negCloud.points.size(); i++)
00228 {
00229 scoresNegatives.push_back(map.getLikelihoodForPoint(negCloud.points[i]));
00230 }
00231
00232 this->countResults(res,scoresPositives,scoresNegatives);
00233
00234 }
00235
00236 static int ctr = 0;
00237 int
00238 main (int argc, char** argv)
00239 {
00240
00241 if(argc!=3)
00242 {
00243 cout<<"usage: ltest point_cloud1 point_cloud2\n";
00244 return(-1);
00245 }
00246 pcl::PointCloud<pcl::PointXYZ> cloud, cloud2;
00247 pcl::PointCloud<pcl::PointXYZI> outCloud;
00248
00249 cloud = lslgeneric::readVRML<pcl::PointXYZ>(argv[1]);
00250 cloud2 = lslgeneric::readVRML<pcl::PointXYZ>(argv[2]);
00251
00252 OneTestResult res;
00253 int ndiscr = 100;
00254 double threshold = 0.05;
00255 Tester tester(10,0.3,1,0.05,40,ndiscr);
00256 pcl::PointXYZ scannerOriginModel;
00257 scannerOriginModel.x = 0;
00258 scannerOriginModel.y = 0;
00259 scannerOriginModel.z = 0;
00260 tester.runTestsNDTTree(cloud,cloud2,0.5,4,scannerOriginModel,res);
00261
00262 int index = threshold*ndiscr;
00263
00264
00265 cout<<"tp = ["<<res.tp.transpose()<<"];\n fp = ["<<res.fp.transpose()<<"];\n tn = ["<<res.tn.transpose()<<"];\n fn = ["<<res.fn.transpose()<<"];\n";
00266
00267 cout<<"tp = ["<<res.tp(index)<<"];\n fp = ["<<res.fp(index)<<"];\n tn = ["<<res.tn(index)<<"];\n fn = ["<<res.fn(index)<<"];\n";
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298 return (0);
00299 }
00300
00301
00302