evaluate_plane_segmentation.cpp
Go to the documentation of this file.
00001 
00063 #include <map>
00064 #include <iostream>
00065 #include <iomanip>
00066 
00067 #include <boost/program_options.hpp>
00068 
00069 #include <pcl/io/pcd_io.h>
00070 #include <pcl/common/eigen.h>
00071 #include <pcl/filters/voxel_grid.h>
00072 
00073 #include "cob_3d_mapping_common/label_defines.h"
00074 #include "cob_3d_mapping_common/polygon.h"
00075 #include "cob_3d_mapping_tools/io.h"
00076 #include "cob_3d_segmentation/polygon_extraction/polygon_types.h"
00077 #include "cob_3d_segmentation/polygon_extraction/polygon_extraction.h"
00078 #include "cob_3d_segmentation/plane_extraction.h"
00079 
00080 typedef pcl::PointXYZRGB PointT;
00081 typedef pcl::PointCloud<PointT> PointCloud;
00082 
00083 std::string pc_in, ppm_exp, ppm_pred;
00084 
00085 // --------- forward declarations:
00086 class Cluster;
00087 typedef std::map<int,Cluster> ClusterMap;
00088 std::ostream& operator<< (std::ostream&, Cluster&);
00089 std::string colorHumanReadable(int);
00090 
00091 void printNoMatch(Cluster&);
00092 void compare(std::map<int,Cluster>&, std::map<int,Cluster>&);
00093 void pca(PointCloud::Ptr, Cluster&);
00094 void fillPolygonPtr(Cluster& c, cob_3d_segmentation::PolygonContours<cob_3d_segmentation::PolygonPoint>& contour);
00095 void createClusters(PointCloud::Ptr, std::map<int,Cluster>&);
00096 
00097 // --------- definition:
00098 void readOptions(int argc, char* argv[])
00099 {
00100   using namespace boost::program_options;
00101   options_description options("Options");
00102   options.add_options()
00103     ("help", "produce help message")
00104     ("pc_in", value<std::string>(&pc_in), "pcd")
00105     ("ppm_exp", value<std::string>(&ppm_exp), "ppm expected")
00106     ("ppm_pred", value<std::string>(&ppm_pred), "ppm predicted")
00107     ;
00108 
00109   positional_options_description p_opt;
00110   p_opt.add("pc_in", 1).add("ppm_exp", 1).add("ppm_pred", 1);
00111   variables_map vm;
00112   store(command_line_parser(argc, argv).options(options).positional(p_opt).run(), vm);
00113   notify(vm);
00114 
00115   if (vm.count("help") || !vm.count("pc_in") || !vm.count("ppm_exp") || !vm.count("ppm_pred"))
00116   {
00117     std::cout <<"Compare plane segments" << std::endl;
00118     std::cout <<"<point cloud pcd> <ppm expected> <ppm predicted>" << std::endl;
00119     std::cout << options << std::endl;
00120     exit(0);
00121   }
00122 }
00123 
00124 class Cluster
00125 {
00126 public:
00127   Cluster(int id_)
00128   : id(id_)
00129   , centroid(Eigen::Vector3f::Zero())
00130   , comp1(Eigen::Vector3f::Zero())
00131   , comp2(Eigen::Vector3f::Zero())
00132   , comp3(Eigen::Vector3f::Zero())
00133   , values(Eigen::Vector3f::Zero())
00134   , poly(new cob_3d_mapping::Polygon)
00135     { }
00136 
00137   inline void addBorder(int x, int y) { borders.push_back(cob_3d_segmentation::PolygonPoint(x,y)); }
00138   inline void addPoint(int idx) { indices.push_back(idx); }
00139 
00140   friend std::ostream& operator<<( std::ostream& out, Cluster& c);
00141 
00142   int id;
00143   std::vector<int> indices;
00144   std::vector<cob_3d_segmentation::PolygonPoint> borders;
00145   //cob_3d_segmentation::PolygonContours<cob_3d_segmentation::PolygonPoint> poly;
00146   Eigen::Vector3f centroid;
00147   Eigen::Vector3f comp1;
00148   Eigen::Vector3f comp2;
00149   Eigen::Vector3f comp3;
00150   Eigen::Vector3f values;
00151   cob_3d_mapping::Polygon::Ptr poly;
00152 };
00153 
00154 std::string colorHumanReadable(int id)
00155 {
00156   std::stringstream ss;
00157   ss << "0x" << std::setfill('0') << std::setw(6) << std::right << std::hex << id << std::dec;
00158   return ss.str();
00159 }
00160 
00161 std::ostream& operator<< (std::ostream& out, Cluster& c)
00162 {
00163   out << colorHumanReadable(c.id) << " {";
00164 
00165   // --- Begin Properties ---
00166   out << "Size: " << std::setw(6) << std::right << c.indices.size();
00167   out << " N: " << std::setiosflags(std::ios::fixed) << std::setprecision(6)
00168       << std::setw(9) << std::right << c.comp3(0) <<","
00169       << std::setw(9) << std::right << c.comp3(1) <<","
00170       << std::setw(9) << std::right << c.comp3(2);
00171   //out<< " Comp: " << c.values(2) << ", " << c.values(1) << ", " << c.values(0) << "}";
00172   // --- End Properties ---
00173 
00174   out<<"}";
00175   return out;
00176 }
00177 
00178 void printNoMatch(Cluster& c)
00179 {
00180   std::cout << "No Match: " << c << std::endl;
00181 }
00182 
00183 void printForFile(ClusterMap& exp, ClusterMap& pred)
00184 {
00185   int count_no = 0;
00186 
00187   // format config:
00188   const int padding = 3;
00189   std::stringstream ss;
00190   ss << exp.begin()->second;
00191   int col = ss.str().length() + padding;
00192   std::string sep = "|   ";
00193   std::cout <<"  -  \t"<<"  - \t"<<"labeled\t"<<" - \t"<<" - \t"<<"-\t"<<"  - \t\t"
00194             <<"plane extraction" << std::endl;
00195   std::cout <<"color\t"<<"size\t"<<"    n_x\t"<<"n_y\t"<<"n_z\t"<<"d\t"<<"area\t\t"
00196             <<"    n_x\t"<<"n_y\t"<<"n_z\t"<<"d\t"<<"area\t"<<"A_diff\t"<<"dot"<<std::endl;
00197   for(ClusterMap::iterator it=exp.begin(); it!= exp.end(); ++it)
00198   {
00199     cob_3d_mapping::Polygon::Ptr p1 = it->second.poly;
00200     float area1 = p1->computeArea3d();
00201     std::cout << colorHumanReadable(it->second.id) << "\t"
00202               << it->second.indices.size() << "\t"
00203               << it->second.comp3[0] << "\t"
00204               << it->second.comp3[1] << "\t"
00205               << it->second.comp3[2] << "\t"
00206               << it->second.centroid.dot(it->second.comp3) << "\t"
00207               << area1 << "\t\t";
00208     ClusterMap::iterator match = pred.find(it->first);
00209     if (match == pred.end())
00210     {
00211       std::cout << "no match" << std::endl;
00212       ++count_no;
00213       continue;
00214     }
00215     float alpha = it->second.comp3.dot(match->second.comp3);
00216     cob_3d_mapping::Polygon::Ptr p2 = match->second.poly;
00217     float area2 = p2->computeArea3d();
00218     float area_diff = 0;
00219     /*gpc_polygon gpc_a, gpc_b, gpc_diff;
00220     p1->getGpcStructure(p1->transform_from_world_to_plane, &gpc_a);
00221     p2->getGpcStructure(p2->transform_from_world_to_plane, &gpc_b);
00222     gpc_polygon_clip(GPC_XOR, &gpc_a, &gpc_b, &gpc_diff);*/
00223 
00224     //cob_3d_mapping::Polygon::Ptr p_diff(new cob_3d_mapping::Polygon);
00225     if(p1->isIntersectedWith(p2))
00226     {
00227       area_diff = std::abs(area1 - area2);
00228     }
00229 
00230     std::cout << match->second.comp3[0] << "\t"
00231               << match->second.comp3[1] << "\t"
00232               << match->second.comp3[2] << "\t"
00233               << match->second.centroid.dot(match->second.comp3) << "\t"
00234               << area2 << "\t"
00235               << area_diff << "\t"
00236               << alpha << std::endl;
00237   }
00238 }
00239 
00240 void compare(ClusterMap& exp, ClusterMap& pred)
00241 {
00242   int count_no = 0;
00243 
00244   // format config:
00245   const int padding = 3;
00246   std::stringstream ss;
00247   ss << exp.begin()->second;
00248   int col = ss.str().length() + padding;
00249   std::string sep = "|   ";
00250 
00251   for(ClusterMap::iterator it=exp.begin(); it!= exp.end(); ++it)
00252   {
00253     ClusterMap::iterator match = pred.find(it->first);
00254     if (match == pred.end())
00255     {
00256       std::stringstream ss1;
00257       ss1 << it->second;
00258       std::cout << std::setw(col) << std::left << ss1.str() << sep
00259                 << std::setw(round(0.3*col)) << " "
00260                 << std::setw(round(0.7*col)) << std::left << "--- No Match ---" << sep << std::endl;
00261       ++count_no;
00262       continue;
00263     }
00264     float alpha = it->second.comp3.dot(match->second.comp3);
00265 
00266     cob_3d_mapping::Polygon::Ptr p1 = it->second.poly;
00267     cob_3d_mapping::Polygon::Ptr p2 = match->second.poly;
00268     float area1 = p1->computeArea3d();
00269     float area2 = p2->computeArea3d();
00270     float area_diff = 0;
00271     if(p1->isIntersectedWith(p2))
00272     {
00273       area_diff = std::abs(area1 - area2);
00274     }
00275 
00276     std::stringstream ss1, ss2;
00277     ss1 << it->second;
00278     ss2 << match->second;
00279     std::cout << std::setw(col) << std::left << ss1.str() << sep
00280               << std::setw(col) << std::left << ss2.str() << sep
00281               << "Dot: " << std::setw(9) << std::left << std::setiosflags(std::ios::fixed) << std::setprecision(6) << alpha
00282               << " A1: "<< area1 << "  A2: "<< area2 << "  A_Diff: " << area_diff << std::endl;
00283   }
00284   count_no = exp.size() - count_no;
00285   std::cout << "Results:" << std::endl
00286             << std::setw(30) << std::left << "Matching Accuracy"<<"= ("<<count_no<<"/"<<exp.size()<<") "
00287             << std::setiosflags(std::ios::fixed)<<std::setprecision(2)<<(float)count_no/(float)exp.size()*100.0f << "%" << std::endl;
00288 }
00289 
00290 void pca(PointCloud::Ptr cloud, Cluster& c)
00291 {
00292   for(std::vector<int>::iterator it=c.indices.begin(); it!=c.indices.end(); ++it)
00293     c.centroid += (*cloud)[*it].getVector3fMap();
00294   c.centroid /= c.indices.size();
00295 
00296   Eigen::Matrix3f cov(Eigen::Matrix3f::Zero());
00297   for(std::vector<int>::iterator it=c.indices.begin(); it!=c.indices.end(); ++it)
00298   {
00299     Eigen::Vector3f demean = (*cloud)[*it].getVector3fMap() - c.centroid;
00300     cov += demean * demean.transpose();
00301   }
00302 
00303   Eigen::Matrix3f eigenvectors;
00304   pcl::eigen33(cov, eigenvectors, c.values);
00305   c.values /= c.indices.size();
00306   c.comp1 = eigenvectors.col(2);
00307   c.comp2 = eigenvectors.col(1);
00308   c.comp3 = eigenvectors.col(0);
00309 }
00310 
00311 void fillPolygonPtr(Cluster& c, cob_3d_segmentation::PolygonContours<cob_3d_segmentation::PolygonPoint>& contour, PointCloud::Ptr cloud)
00312 {
00313   c.poly->centroid << c.centroid, 0;
00314   c.poly->computeAttributes(c.comp3, c.poly->centroid);
00315   int max_points = -1, max_idx = -1;
00316   for (size_t i=0; i<contour.polys_.size(); ++i)
00317   {
00318     if ((int)contour.polys_[i].size() > max_points) { max_points = contour.polys_[i].size(); max_idx = i; }
00319   }
00320 
00321   for (size_t i=0; i<contour.polys_.size(); ++i)
00322   {
00323     c.poly->contours.push_back(std::vector<Eigen::Vector3f>());
00324     if ((int)i == max_idx)
00325     {
00326       c.poly->holes.push_back(false);
00327       std::vector<cob_3d_segmentation::PolygonPoint>::iterator it = contour.polys_[i].begin();
00328       for( ; it != contour.polys_[i].end(); ++it)
00329         c.poly->contours.back().push_back( (*cloud)[cob_3d_segmentation::PolygonPoint::getInd(it->x, it->y)].getVector3fMap() );
00330     }
00331     else
00332     {
00333       c.poly->holes.push_back(true);
00334       std::vector<cob_3d_segmentation::PolygonPoint>::reverse_iterator it = contour.polys_[i].rbegin();
00335       for( ; it != contour.polys_[i].rend(); ++it)
00336         c.poly->contours.back().push_back( (*cloud)[cob_3d_segmentation::PolygonPoint::getInd(it->x, it->y)].getVector3fMap() );
00337     }
00338   }
00339 }
00340 
00341 void createClusters(PointCloud::Ptr cloud, ClusterMap& cmap)
00342 {
00343   int w = cloud->width, h = cloud->height, s = cloud->size();
00344   int mask[] = { -w, 1, w, -1 };
00345   int mask_size = 4;
00346 
00347   for(int idx=0; idx < s; ++idx)
00348   {
00349     int id = (*cloud)[idx].rgba;
00350     int x = idx % w;
00351     int y = idx / w;
00352     int count = 0;
00353 
00354     ClusterMap::iterator it = cmap.find(id);
00355     if (it == cmap.end())
00356     {
00357       //std::cout << "Create new cluster: " << colorHumanReadable(id) << std::endl;
00358       it = cmap.insert( std::pair<int,Cluster>(id, Cluster(id)) ).first;
00359     }
00360     if (y == 0 || y == h-1 || x == 0 || x == w-1)
00361     {
00362       it->second.addBorder(x,y);
00363     }
00364     else
00365     {
00366       for(int i=0;i<mask_size;++i) { if (id != (*cloud)[idx+mask[i]].rgba) { ++count; } }
00367       if (count < 1) { it->second.addPoint(idx); }
00368       else { it->second.addBorder(x,y); }
00369     }
00370   }
00371 
00372   cob_3d_segmentation::PolygonExtraction pe;
00373   ClusterMap::iterator it=cmap.begin();
00374   while(it!=cmap.end())
00375   {
00376     if (it->first == 0xFFFFFF || it->first == LBL_UNDEF || it->second.indices.size() <= 5)
00377     {
00378       //std::cout << "Delete Cluster " << colorHumanReadable(it->first) << std::endl;
00379       cmap.erase(it++);
00380     }
00381     else
00382     {
00383       //std::cout<< it->second << std::endl;
00384       cob_3d_segmentation::PolygonContours<cob_3d_segmentation::PolygonPoint> poly;
00385       pe.outline(w, h, it->second.borders, poly);
00386       pca(cloud, it->second);
00387       fillPolygonPtr(it->second, poly, cloud);
00388       ++it;
00389     }
00390   }
00391 }
00392 
00393 int main(int argc, char** argv)
00394 {
00395   readOptions(argc, argv);
00396 
00397   PointCloud::Ptr pc_exp(new PointCloud);
00398   PointCloud::Ptr pc_pred(new PointCloud);
00399   pcl::PCDReader pcd;
00400   cob_3d_mapping_tools::PPMReader ppm;
00401   if (pcd.read(pc_in, *pc_exp) == -1) exit(0);
00402   *pc_pred = *pc_exp;
00403   if (ppm.mapRGB(ppm_exp, *pc_exp, false) == -1) { std::cout<<"Mapping error ["<<ppm_exp<<"]"<<std::endl; exit(0); }
00404   if (ppm.mapRGB(ppm_pred, *pc_pred, false) == -1) { std::cout<<"Mapping error ["<<ppm_pred<<"]"<<std::endl; exit(0); }
00405 
00406   ClusterMap exp;
00407   createClusters(pc_exp, exp);
00408 
00409   ClusterMap pred;
00410   createClusters(pc_pred, pred);
00411 
00412   printForFile(exp, pred);
00413 
00414   return 0;
00415 }


cob_3d_segmentation
Author(s): Georg Arbeiter
autogenerated on Wed Aug 26 2015 11:03:03