likelihoodSingleScan.cc
Go to the documentation of this file.
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     //pcl::RadiusOutlierRemoval<pcl::PointXYZ> filter;
00089     //filter.setRadiusSearch(1);
00090     //filter.setMinNeighborsInRadius(3);
00091     pcl::PointCloud<pcl::PointXYZ>::Ptr pcptr(new pcl::PointCloud<pcl::PointXYZ>());
00092     *pcptr = rawCloud;
00093     //filter.setInputCloud(pcptr);
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     //filter.filter(pc);
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         //generate a random false point on the ray
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     //book-keeping: count TP, FP etc. for each threshold value
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         //using a threshold below idx => point is a positive
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         //above idx => point is a negative
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         //using a threshold below idx => point is a positive
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         //above idx => point is a negative
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> &gtCloud,
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     //we construct one model from rawcloud and test on gt and negatives
00212     lslgeneric::OctTree<pcl::PointXYZ> prototype;
00213     prototype.setParameters(resolutionMax,resolutionMin,10);
00214     /*
00215     lslgeneric::OctTree<pcl::PointXYZ>::SMALL_CELL_SIZE = resolutionMin;
00216     lslgeneric::OctTree<pcl::PointXYZ>::BIG_CELL_SIZE = resolutionMax;
00217     lslgeneric::OctTree<pcl::PointXYZ>::MAX_POINTS = 10;
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     //full ROC curve
00265     cout<<"tp = ["<<res.tp.transpose()<<"];\n fp = ["<<res.fp.transpose()<<"];\n tn = ["<<res.tn.transpose()<<"];\n fn = ["<<res.fn.transpose()<<"];\n";
00266     //just the fixed threshold
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         //loop through points and compute likelihoods LASER
00272         for(int i=0; i<cloud.points.size(); i++) {
00273         pcl::PointXYZ thisPt = cloud.points[i];
00274         //double likelihood = nd.getLikelihoodForPointWithInterpolation(thisPt);
00275         double likelihood = nd.getLikelihoodForPoint(thisPt);
00276         pcl::PointXYZI outPt;
00277         outPt.x = thisPt.x;
00278         outPt.y = thisPt.y;
00279         outPt.z = thisPt.z;
00280         outPt.intensity = likelihood;
00281         sumLikelihoods += likelihood;
00282         maxLikelihood = (likelihood > maxLikelihood) ?
00283                             likelihood : maxLikelihood;
00284         outCloud.points[i] = outPt;
00285         }
00286         cout<<endl;
00287         cout<<"max likelihood "<<maxLikelihood<<endl;
00288         cout<<"sum likelihoods "<<sumLikelihoods<<endl;
00289         cout<<"average likelihood "<<sumLikelihoods/cloud.points.size()<<endl;
00290         //normalize for display
00291         //compute standart deviation
00292         for(int i=0; i<outCloud.points.size(); i++) {
00293         outCloud.points[i].intensity /= (maxLikelihood);
00294         }
00295         snprintf(fname,49,"/home/tsv/ndt_tmp/likelihood.wrl");
00296         lslgeneric::writeToVRML(fname,outCloud);
00297         */
00298     return (0);
00299 }
00300 
00301 
00302 


ndt_map
Author(s): Todor Stoyanov, Jari Saarinen, Henrik Andreasson
autogenerated on Mon Jan 6 2014 11:31:57