ObjectDetectorProvider.cpp
Go to the documentation of this file.
00001 
00034 #include "ros/ros.h"
00035 #include "std_msgs/String.h"
00036 #include "sensor_msgs/Image.h"
00037 #include "geometry_msgs/Point.h"
00038 #include "image_transport/image_transport.h"
00039 #include "cv_bridge/CvBridge.h"
00040 #include <opencv/cv.h>
00041 #include <opencv/highgui.h>
00042 
00043 #include <cstdlib>
00044 #include <string>
00045 #include <sstream>
00046 #include <vector>
00047 
00048 #include "re_vision/SearchFor.h"
00049 #include "re_msgs/DetectedObject.h"
00050 #include "ObjectDetectorProvider.h"
00051 
00052 #include "ObjectDetectorMethod.h"
00053 #include "ObjectModel.h"
00054 #include "SurfPlanarDetector.h"
00055 #include "Surf3DDetector.h"
00056 #include "VisualizationManager.h"
00057 
00058 #include "DUtils.h"
00059 
00060 
00061 using namespace std;
00062 
00063 // ---------------------------------------------------------------------------
00064 
00065 
00066 ObjectDetectorProvider::ObjectDetectorProvider(
00067   const ros::NodeHandle& node_handle)
00068   : m_node_handle(node_handle),
00069     m_camera_info_sub(NULL), m_camera_info_got(false), m_debug(false),
00070     m_visualizer(NULL), m_visualization(false)
00071 {
00072   createDetectionAlgorithms();
00073 }
00074 
00075 // ---------------------------------------------------------------------------
00076 
00077 ObjectDetectorProvider::ObjectDetectorProvider(
00078   const ros::NodeHandle& node_handle, const CameraBridge &camera)
00079   : m_node_handle(node_handle),
00080   m_camera_info_sub(NULL), m_camera(camera), m_camera_info_got(true),
00081   m_debug(false), m_visualizer(NULL), m_visualization(false)
00082 {
00083   createDetectionAlgorithms();
00084 }
00085 
00086 // ---------------------------------------------------------------------------
00087 
00088 inline void ObjectDetectorProvider::createDetectionAlgorithms()
00089 {
00090   m_algorithms.insert(make_pair("planar", new SurfPlanarDetector));
00091   m_algorithms.insert(make_pair("3D", new Surf3DDetector));
00092 }
00093 
00094 // ---------------------------------------------------------------------------
00095 
00096 bool ObjectDetectorProvider::ServiceSearchFor(
00097                 re_vision::SearchFor::Request  &req,
00098         re_vision::SearchFor::Response &res )
00099 {
00100   cv::Mat image = getImage(req);
00101 
00102   showRequestInformation(req, image);
00103 
00104   if(m_camera_info_got)
00105     processRequest(req, image, res);
00106   else
00107     emptyResponse(req, res);
00108 
00109         return true;
00110 }
00111 
00112 // ---------------------------------------------------------------------------
00113 
00114 void ObjectDetectorProvider::TopicNewModel
00115   (const std_msgs::String::ConstPtr& msg)
00116 {
00117   ROS_INFO("New model path: %s", msg->data.c_str());
00118   learnNewModel(msg->data);
00119 }
00120 
00121 // ---------------------------------------------------------------------------
00122 
00123 void ObjectDetectorProvider::TopicCameraInfo
00124   (const sensor_msgs::CameraInfo::ConstPtr& caminfo)
00125 {
00126   if(!m_camera_info_got)
00127   {
00128     // unsubscribe
00129     delete m_camera_info_sub;
00130     m_camera_info_sub = NULL;
00131 
00132     /*
00133     CameraBridge::ImageType imgtype = CameraBridge::BW;
00134 
00135     if(m_color_model == "bw") imgtype = CameraBridge::BW;
00136     else if(m_color_model == "rgb") imgtype = CameraBridge::RGB;
00137     else if(m_color_model == "bgr") imgtype = CameraBridge::BGR;
00138     else if(m_color_model == "bayer_bg") imgtype = CameraBridge::BAYER_BG;
00139     else if(m_color_model == "bayer_gb") imgtype = CameraBridge::BAYER_GB;
00140     else if(m_color_model == "bayer_rg") imgtype = CameraBridge::BAYER_RG;
00141     else if(m_color_model == "bayer_gr") imgtype = CameraBridge::BAYER_GR;
00142     */
00143 
00144     int w = caminfo->width;
00145     int h = caminfo->height;
00146     float fx = caminfo->K[0];
00147     float fy = caminfo->K[4];
00148     float cx = caminfo->K[2];
00149     float cy = caminfo->K[5];
00150     float k1, k2, p1, p2;
00151 
00152     k1 = caminfo->D[0];
00153     k2 = caminfo->D[1];
00154     p1 = caminfo->D[2];
00155     p2 = caminfo->D[3];
00156 
00157     //m_camera.SetParameters(imgtype, w, h, cx, cy, fx, fy, k1, k2, p1, p2);
00158     m_camera.SetParameters(w, h, cx, cy, fx, fy, k1, k2, p1, p2);
00159 
00160     ROS_INFO("Camera info got");
00161 
00162     ROS_DEBUG("width %d, height %d, "
00163       "fx %f, fy %f, cx %f, cy %f, k1 %f, k2 %f, p1 %f, p2 %f",
00164       w, h, fx, fy, cx, cy, k1, k2, p1, p2);
00165 
00166     m_camera_info_got = true;
00167   }
00168 }
00169 
00170 // ---------------------------------------------------------------------------
00171 
00172 void ObjectDetectorProvider::init()
00173 {
00174   m_service = m_node_handle.advertiseService("/re_vision/search_for",
00175         &ObjectDetectorProvider::ServiceSearchFor, this);
00176 
00177   m_new_model_sub = m_node_handle.subscribe("/re_vslam/new_model",
00178     100, &ObjectDetectorProvider::TopicNewModel, this);
00179 
00180   m_visualization_pub = m_node_handle.advertise<sensor_msgs::Image>
00181     ("/re_vision/detector_visualization", 100);
00182 
00183   if(m_visualizer) delete m_visualizer;
00184   m_visualizer = new VisualizationManager(m_visualization_pub);
00185 
00186   if(!m_camera_info_got)
00187   {
00188     m_camera_info_sub = new ros::Subscriber(
00189       m_node_handle.subscribe("/camera_info",
00190         100, &ObjectDetectorProvider::TopicCameraInfo, this));
00191   }
00192 
00193 }
00194 
00195 // ---------------------------------------------------------------------------
00196 
00197 void ObjectDetectorProvider::SetVisualizationMode(bool onoff)
00198 {
00199   m_visualization = onoff;
00200 
00201   tAlgorithmMap::iterator ait;
00202   if(m_visualization)
00203   {
00204     for(ait = m_algorithms.begin(); ait != m_algorithms.end(); ++ait)
00205     {
00206       ait->second->setVisualizationManager(m_visualizer);
00207     }
00208   }
00209   else
00210   {
00211     for(ait = m_algorithms.begin(); ait != m_algorithms.end(); ++ait)
00212     {
00213       ait->second->setVisualizationManager(NULL);
00214     }
00215   }
00216 }
00217 
00218 // ---------------------------------------------------------------------------
00219 
00220 void ObjectDetectorProvider::SetDebugMode(bool onoff,
00221   const std::string &dir)
00222 {
00223   tAlgorithmMap::iterator ait;
00224   for(ait = m_algorithms.begin(); ait != m_algorithms.end(); ++ait)
00225   {
00226     ait->second->setDebugMode(onoff, dir);
00227   }
00228   m_debug = onoff;
00229 }
00230 
00231 // ---------------------------------------------------------------------------
00232 
00233 ObjectDetectorProvider::~ObjectDetectorProvider()
00234 {
00235   delete m_camera_info_sub;
00236   delete m_visualizer;
00237 
00238   tAlgorithmMap::iterator ait;
00239   for(ait = m_algorithms.begin(); ait != m_algorithms.end(); ++ait)
00240   {
00241     delete ait->second;
00242   }
00243 
00244   tModelMap::iterator mit;
00245   for(mit = m_models.begin(); mit != m_models.end(); ++mit)
00246   {
00247     delete mit->second;
00248   }
00249 }
00250 
00251 // ---------------------------------------------------------------------------
00252 
00253 void ObjectDetectorProvider::getValidObjects(const std::vector<std::string> &objects,
00254         std::vector<std::string>& valid_objects,
00255         std::vector<re_msgs::DetectedObject> &detections,
00256         std::vector<re_msgs::DetectedObject *> &pointers) const
00257 {
00258         // Adds to detections a pointer to an entry in pointers
00259   detections.clear();
00260   valid_objects.clear();
00261 
00262   detections.resize(objects.size());
00263   valid_objects.reserve(objects.size());
00264   pointers.reserve(objects.size());
00265 
00266   for(unsigned int idx = 0; idx < objects.size(); ++idx)
00267   {
00268     // check if the object is valid
00269     tModelMap::const_iterator pit;
00270     for(pit = m_models.begin(); pit != m_models.end(); ++pit)
00271     {
00272       if(objects[idx] == pit->first) break;
00273     }
00274     if(pit != m_models.end())
00275     {
00276       valid_objects.push_back(objects[idx]);
00277       pointers.push_back( &detections[idx] );
00278     }
00279     else
00280     {
00281       // unknown object
00282       ROS_WARN("Object \"%s\" unknown", objects[idx].c_str());
00283       detections[idx].points2d.clear();
00284       detections[idx].points3d.clear();
00285     }
00286   }
00287 }
00288 
00289 // ---------------------------------------------------------------------------
00290 
00291 void ObjectDetectorProvider::processRequest(
00292         const re_vision::SearchFor::Request  &req,
00293         const cv::Mat &image,
00294         re_vision::SearchFor::Response &res)
00295 {
00296   ROS_DEBUG("Processing request...");
00297 
00298   cv::Mat _image = image.clone(); // ###
00299 
00300   ros::WallTime t_begin = ros::WallTime::now();
00301 
00302   vector<string> valid_objects;
00303   vector<re_msgs::DetectedObject *> pointers;
00304   getValidObjects(req.Objects, valid_objects, res.Detections, pointers);
00305 
00306   detectObjects(valid_objects, image, req.MaxPointsPerObject, pointers);
00307   rectifyDetections(res.Detections, image.cols, image.rows,
00308     req.MaxPointsPerObject);
00309 
00310 #if 0
00311   if(!res.Detections.empty() && !res.Detections[0].points2d.empty())
00312   {
00313     vector<cv::Point3f> points3d;
00314     for(unsigned int i = 0; i < res.Detections[0].points3d.size(); ++i)
00315     {
00316       points3d.push_back(cv::Point3f(
00317         -res.Detections[0].points3d[i].y,
00318         -res.Detections[0].points3d[i].z,
00319         res.Detections[0].points3d[i].x));
00320     }
00321 
00322     cv::Mat cP(points3d);
00323     cv::Mat R = cv::Mat::eye(3,3,CV_64F);
00324     cv::Mat t = cv::Mat::zeros(3,1,CV_64F);
00325 
00326     vector<cv::Point2f> cam_pixels;
00327 
00328     cv::projectPoints(cP, R, t, m_camera.GetIntrinsicParameters(),
00329       cv::Mat::zeros(4,1,CV_32F), cam_pixels);
00330 
00331     CvScalar color = cvScalar(255, 255, 255);
00332     for(unsigned int i = 0; i < cam_pixels.size(); ++i)
00333     {
00334       cv::circle(_image, cvPoint(cam_pixels[i].x, cam_pixels[i].y),
00335         2, color, 1);
00336     }
00337 
00338     cv::imwrite("_debug.png", _image);
00339 
00340   }
00341 #endif
00342 
00343   ros::WallTime t_end = ros::WallTime::now();
00344 
00345   {
00346     int counter = 0;
00347     vector<re_msgs::DetectedObject>::const_iterator dit;
00348     for(dit = res.Detections.begin(); dit != res.Detections.end(); ++dit)
00349     {
00350       if(!dit->points3d.empty()) counter++;
00351     }
00352     ROS_INFO("%d objects detected", counter);
00353   }
00354 
00355   ros::WallDuration d = t_end - t_begin;
00356   ROS_DEBUG("Processing ok. Elapsed time: %f", d.toSec());
00357 }
00358 
00359 // ---------------------------------------------------------------------------
00360 
00361 inline void  ObjectDetectorProvider::emptyResponse
00362   (const re_vision::SearchFor::Request &req,
00363   re_vision::SearchFor::Response &res) const
00364 {
00365   res.Detections.clear();
00366         res.Detections.resize(req.Objects.size());
00367 
00368         ROS_INFO("Request got, but there is not camera information yet");
00369 }
00370 
00371 // ---------------------------------------------------------------------------
00372 
00373 cv::Mat ObjectDetectorProvider::getImage(const re_vision::SearchFor::Request &req)
00374 {
00375   boost::shared_ptr<const sensor_msgs::Image> ros_img_ptr
00376     (new sensor_msgs::Image(req.Image));
00377 
00378   IplImage *im;
00379   if(m_camera.usesBayer())
00380   {
00381     // m_camera converts the image
00382     im = m_bridge.imgMsgToCv(ros_img_ptr, "passthrough");
00383   }
00384   else
00385   {
00386     // ros converts the image
00387     im = m_bridge.imgMsgToCv(ros_img_ptr, "mono8");
00388   }
00389 
00390   cv::Mat ret = cv::Mat (im).clone ();
00391 
00392   m_camera.ConvertImage(ret);
00393 
00394   return ret;
00395 }
00396 
00397 // ---------------------------------------------------------------------------
00398 
00399 void ObjectDetectorProvider::learnNewModel(const std::string &path)
00400 {
00401   ObjectModel *model = NULL;
00402 
00403   try
00404   {
00405     model = new ObjectModel(path, true);
00406 
00407     pair<tModelMap::iterator, bool> ret =
00408       m_models.insert(make_pair( model->Name, model ));
00409 
00410     if(!ret.second)
00411     {
00412       ROS_INFO("The object %s was already known, updating model...",
00413         model->Name.c_str());
00414 
00415       delete ret.first->second;
00416       ret.first->second = model;
00417     }
00418 
00419   } catch(std::string ex)
00420   {
00421     delete model;
00422     ROS_ERROR("Error loading model from directory %s: %s",
00423       path.c_str(), ex.c_str());
00424   }
00425 }
00426 
00427 // ---------------------------------------------------------------------------
00428 
00429 void ObjectDetectorProvider::removeModel(const std::string &name)
00430 {
00431   tModelMap::iterator mit = m_models.find(name);
00432 
00433   if(mit != m_models.end())
00434   {
00435     delete mit->second;
00436     m_models.erase(mit);
00437   }
00438 }
00439 
00440 // ---------------------------------------------------------------------------
00441 
00442 void ObjectDetectorProvider::detectObjects(
00443   const std::vector<std::string> &objects,
00444   const cv::Mat &image, int max_points_per_object,
00445   std::vector<re_msgs::DetectedObject*> &ret)
00446 {
00447   // initiate Data for recognition
00448   // this does not copy the image or the camera
00449   ObjectDetectorMethod::DetectionData data(image, m_camera);
00450 
00451   tModelMap::const_iterator mit;
00452   tAlgorithmMap::const_iterator ait;
00453 
00454   std::vector<std::string>::const_iterator oit;
00455   for(oit = objects.begin(); oit != objects.end(); ++oit)
00456   {
00457     mit = m_models.find(*oit);
00458 
00459     if(mit != m_models.end())
00460     {
00461       ObjectModel &model = *(mit->second);
00462 
00463       ait = m_algorithms.find(model.Type);
00464       if(ait != m_algorithms.end())
00465       {
00466         ObjectDetectorMethod *method = ait->second;
00467         re_msgs::DetectedObject &detection = *ret[oit - objects.begin()];
00468 
00469         method->detect(data, model, detection);
00470 
00471         // remove points if there are too many
00472         // (this is now done after rectification)
00473         //if(max_points_per_object >= 0)
00474         //  removeSomePoints(detection, max_points_per_object);
00475 
00476       }
00477       else
00478       {
00479         ROS_ERROR("Object \"%s\" is of type \"%s\", but there is no algorithm "
00480           "defined for these objects", oit->c_str(), model.Type.c_str());
00481       }
00482     }
00483     else
00484     {
00485       // this should not happen since objects already contains valid names
00486       ROS_WARN("Object \"%s\" unknown", oit->c_str());
00487     }
00488   }
00489 
00490 }
00491 
00492 // ---------------------------------------------------------------------------
00493 
00494 void ObjectDetectorProvider::rectifyDetections(
00495   vector<re_msgs::DetectedObject> &detections, int W, int H,
00496   int max_points_per_object) const
00497 {
00498   vector<re_msgs::Pixel>::iterator pit;
00499   vector<re_msgs::DetectedObject>::iterator it;
00500   for(it = detections.begin(); it != detections.end(); ++it)
00501   {
00502     vector<unsigned int> i_remove; // remove those that end up outside
00503 
00504     for(pit = it->points2d.begin(); pit != it->points2d.end(); ++pit){
00505             m_camera.DistortPoint(pit->x, pit->y);
00506 
00507             if(pit->x < 0 || pit->x >= W || pit->y < 0 || pit->y >= H)
00508             {
00509               i_remove.push_back(pit - it->points2d.begin());
00510             }
00511     }
00512 
00513     if(!i_remove.empty())
00514     {
00515       DUtils::STL::removeIndices(it->points2d, i_remove, false);
00516       DUtils::STL::removeIndices(it->points3d, i_remove, false);
00517       DUtils::STL::removeIndices(it->points3d_model, i_remove, false);
00518       DUtils::STL::removeIndices(it->octave, i_remove, false);
00519     }
00520 
00521     if(max_points_per_object >= 0 &&
00522       (int)it->points2d.size() > max_points_per_object)
00523     {
00524       removeSomePoints(*it, max_points_per_object);
00525     }
00526   }
00527 }
00528 
00529 // ---------------------------------------------------------------------------
00530 
00531 void ObjectDetectorProvider::showRequestInformation(
00532         const re_vision::SearchFor::Request &req,
00533         const cv::Mat &image) const
00534 {
00535   static int idx = 0;
00536   stringstream ss;
00537 
00538   ROS_INFO("Service /re_vision/search_for invoked %d", idx++);
00539 
00540   ss << "Received a " << image.cols << "x" << image.rows
00541     << " image and " << req.Objects.size() << " objects: ";
00542 
00543   vector<string>::const_iterator it;
00544   for(it = req.Objects.begin(); it != req.Objects.end(); ++it)
00545     ss << *it << " ";
00546 
00547   ROS_INFO("%s", ss.str().c_str());
00548 }
00549 
00550 // ---------------------------------------------------------------------------
00551 
00552 /*
00553 typedef vector<unsigned int> *tCell; // < inlier index >
00554 
00555 static bool CellsInDescendingOrder(
00556         const tCell &a,
00557         const tCell &b)
00558 {
00559         return a->size() > b->size();
00560 }
00561 */
00562 
00563 // -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
00564 
00565 void ObjectDetectorProvider::removeSomePoints(
00566   re_msgs::DetectedObject& detection, int max_points) const
00567 {
00568   if((int)detection.points2d.size() <= max_points) return;
00569 
00570   if(max_points <= 1)
00571   {
00572     if(max_points < 0) max_points = 0;
00573     // trivial case
00574     detection.points2d.resize(max_points);
00575     detection.points3d.resize(max_points);
00576     detection.points3d_model.resize(max_points);
00577     detection.octave.resize(max_points);
00578     return;
00579   }
00580 
00581   // random algorithm
00582   vector<unsigned int> i_remove;
00583   i_remove.reserve(detection.points2d.size());
00584 
00585   for(unsigned int i = 0; i < detection.points2d.size(); ++i)
00586   {
00587     i_remove.push_back(i);
00588   }
00589 
00590    DUtils::Random::SeedRandOnce();
00591 
00592 
00593   int N = max_points;
00594   while(N-- > 0)
00595   {
00596     int idx = DUtils::Random::RandomInt(0, i_remove.size()-1);
00597 
00598     i_remove[idx] = i_remove.back();
00599     i_remove.pop_back();
00600   }
00601 
00602   // do the removal
00603   DUtils::STL::removeIndices(detection.points2d, i_remove, false);
00604   DUtils::STL::removeIndices(detection.points3d, i_remove, false);
00605   DUtils::STL::removeIndices(detection.points3d_model, i_remove, false);
00606   DUtils::STL::removeIndices(detection.octave, i_remove, false);
00607   /*
00608   // convex hull algorithm
00609 
00610   // get the points of the convex hull
00611   vector<cv::Point2f> p2d_v;
00612   p2d_v.reserve(detection.points2d.size());
00613   for(unsigned int i = 0; i < detection.points2d.size(); ++i)
00614   {
00615     const re_msgs::Pixel &p = detection.points2d[i];
00616     p2d_v.push_back(cv::Point2f(p.x, p.y));
00617   }
00618 
00619   cv::Mat p2d(p2d_v, false);
00620   vector<int> i_hull;
00621   cv::convexHull(p2d, i_hull);
00622 
00623   vector<unsigned int> i_remove;
00624   i_remove.reserve(detection.points2d.size());
00625 
00626   sort(i_hull.begin(), i_hull.end());
00627 
00628   // create a vector will all the indices to remove, but those from the
00629   // convex hull
00630   if(!i_hull.empty())
00631   {
00632     for(int idx = 0; idx < i_hull[0]; ++idx)
00633     {
00634       i_remove.push_back(idx);
00635     }
00636     for(unsigned int i = 0; i < i_hull.size() - 1; ++i)
00637     {
00638       // add from i_hull[i] + 1 to i_hull[i+1]-1
00639       for(int idx = i_hull[i]+1; idx < i_hull[i+1]; ++idx)
00640       {
00641         i_remove.push_back(idx);
00642       }
00643     }
00644     // add from i_hull[last]+1 to N
00645     for(int idx = i_hull.back()+1; idx < (int)detection.points2d.size(); ++idx)
00646     {
00647       i_remove.push_back(idx);
00648     }
00649   }
00650   else
00651   {
00652     for(unsigned int idx = 0; idx < detection.points2d.size(); ++idx)
00653     {
00654       i_remove.push_back(idx);
00655     }
00656   }
00657 
00658   if(!i_hull.empty())
00659   {
00660     if((int)i_hull.size() < max_points)
00661     {
00662       // pick random points to save
00663       DUtils::Random::SeedRandOnce();
00664       int N = max_points - i_hull.size();
00665       while(N-- > 0)
00666       {
00667         int idx = DUtils::Random::RandomInt(0, i_remove.size());
00668 
00669         // save that index by removing the idx-th entry from i_remove
00670         i_remove[idx] = i_remove.back();
00671         i_remove.pop_back();
00672       }
00673     } // i_hull.size() < max_points
00674     else if((int)i_hull.size() > max_points)
00675     {
00676       // remove some points from the hull
00677 
00678       // remove those whose edges are shorter
00679       vector<float> len;
00680       len.reserve(i_hull.size());
00681 
00682       int N = i_hull.size() - max_points;
00683       while(N-- > 0)
00684       {
00685         len.resize(0);
00686         len.resize(i_hull.size(), 0);
00687 
00688         int idx_prev = i_hull.back();
00689         int idx_cur = i_hull[0];
00690         int idx_post = i_hull[1];
00691 
00692         for(unsigned int i = 0; i < i_hull.size(); ++i)
00693         {
00694           // len of edges
00695           const re_msgs::Pixel& prev = detection.points2d[idx_prev];
00696           const re_msgs::Pixel& cur = detection.points2d[idx_cur];
00697           const re_msgs::Pixel& post = detection.points2d[idx_post];
00698 
00699           len[i] = (cur.x - prev.x)*(cur.x - prev.x) +
00700             (cur.y - prev.y)*(cur.y - prev.y) +
00701             (cur.x - post.x)*(cur.x - post.x) +
00702             (cur.y - post.y)*(cur.y - post.y);
00703 
00704           //
00705           //const cv::Point2f &prev = p2d_v[idx_prev];
00706           //const cv::Point2f &cur = p2d_v[idx_cur];
00707           //const cv::Point2f &post = p2d_v[idx_post];
00708           //
00709           //const float Ax = cur.x - prev.x;
00710           //const float Ay = cur.y - prev.y;
00711           //const float Bx = post.x - prev.x;
00712           //const float By = post.y - prev.y;
00713           //
00716           //len[i] = fabs( Ax * By - Ay * Bx ) / 2
00717           //  + sqrt(Ax*Ax - Ay*Ay) + sqrt(Bx*Bx - By*By);
00719           //
00720 
00721           idx_prev = idx_cur;
00722           idx_cur = idx_post;
00723           if(i == i_hull.size() - 1)
00724             idx_post = i_hull[0];
00725           else
00726             idx_post = i_hull[i+1];
00727         }
00728 
00729         // get the point with shortest edges
00730         vector<unsigned int> remove_now;
00731         remove_now.push_back(
00732           min_element(len.begin(), len.end()) - len.begin());
00733 
00734         // flag to remove it later
00735         i_remove.push_back( i_hull[remove_now.back()] );
00736 
00737         // and remove it now from the convex hull
00738         DUtils::STL::removeIndices(i_hull, remove_now, true);
00739       }
00740 
00741     } // i_hull.size() > max_points
00742   } // i_hull.empty()
00743 
00744   // do the removal
00745   DUtils::STL::removeIndices(detection.points2d, i_remove, false);
00746   DUtils::STL::removeIndices(detection.points3d, i_remove, false);
00747   DUtils::STL::removeIndices(detection.points3d_model, i_remove, false);
00748 
00749   */
00750 
00751   /* // grid algorithm
00752 
00753   // the remaining points should be as much spread as possible
00754   float minx, miny, maxx, maxy; // bounding box of points in the image
00755   minx = miny = 1e5;
00756   maxx = maxy = 0;
00757 
00758   vector<re_msgs::Pixel>::const_iterator pit;
00759   for(pit = detection.points2d.begin(); pit != detection.points2d.end(); ++pit)
00760   {
00761     if(pit->x < minx) minx = pit->x;
00762     if(pit->x > maxx) maxx = pit->x;
00763     if(pit->y < miny) miny = pit->y;
00764     if(pit->y > maxy) maxy = pit->y;
00765   }
00766 
00767   const float width = maxx - minx + 1;
00768   const float height = maxy - miny + 1;
00769 
00770         const float ratioWH = width / height;
00771 
00772         // inflate the number of desired points to avoid rejecting many points
00773         // when only a few of them are desired
00774         const int DesiredPoints = max_points * 3;
00775 
00776         // size of grid in cells
00777         int GridW = (int)cvCeil(cvSqrt(DesiredPoints * ratioWH));
00778         int GridH = (int)cvCeil((float)DesiredPoints / GridW);
00779         const int NCells = GridW * GridH;
00780 
00781         // size of cell in pixels
00782         const float CellW = width / GridW;
00783         const float CellH = height / GridH;
00784 
00785         // cells stored by rows
00786         vector<tCell> cells(NCells); // each tCell contains inlier indices
00787         for(int i = 0; i < NCells; ++i){
00788                 cells[i] = new vector<unsigned int>;
00789         }
00790 
00791         // fill the grid
00792   for(unsigned int i = 0; i < detection.points2d.size(); ++i)
00793   {
00794     int gridx = int((detection.points2d[i].x - minx) / CellW);
00795     int gridy = int((detection.points2d[i].y - miny) / CellH);
00796     int i_cell = gridy * GridW + gridx;
00797 
00798     cells[i_cell]->push_back(i); // inlier index
00799   }
00800 
00801   // sort the cells in descending order of size
00802   sort(cells.begin(), cells.end(), CellsInDescendingOrder);
00803 
00804   // remove points until getting max_points points
00805   int last_cell = 0;
00806   int existing_points = detection.points2d.size();
00807   bool goon = true;
00808 
00809   vector<unsigned int> i_remove; // indices of points2d, points3d, etc to remove
00810 
00811   while(goon)
00812   {
00813     unsigned int this_level_points = cells[last_cell]->size();
00814 
00815     while(last_cell < NCells && cells[last_cell]->size() == this_level_points)
00816       last_cell++;
00817     last_cell--;
00818 
00819     // check how many points we should remove
00820     int this_level_cells = last_cell + 1;
00821     int remove_total = existing_points - max_points;
00822     int remove_from_level;
00823 
00824     if(last_cell < NCells-1)
00825     {
00826       int should_remove = this_level_points - cells[last_cell+1]->size();
00827       should_remove *= this_level_cells;
00828 
00829       if(should_remove < remove_total)
00830         remove_from_level = should_remove;
00831       else
00832         remove_from_level = remove_total;
00833 
00834     }else
00835       remove_from_level = remove_total;
00836 
00837     int remove_from_cell =
00838       (int)cvCeil((double)remove_from_level / (double)this_level_cells);
00839 
00840     for(int i_cell = 0; i_cell <= last_cell && remove_total > 0; ++i_cell)
00841     {
00842       int remove_now = (remove_from_cell < remove_total ?
00843         remove_from_cell : remove_total);
00844 
00845       if(remove_now > 0)
00846       {
00847         // get the last indices of *cells[i_cell]
00848         vector<unsigned int> &cell = *cells[i_cell];
00849 
00850         if((int)cell.size() <= remove_now)
00851         {
00852           i_remove.insert(i_remove.end(), cell.begin(), cell.end());
00853           cell.clear();
00854         }
00855         else
00856         {
00857           i_remove.insert(i_remove.end(),
00858             cell.begin() + (cell.size() - remove_now), cell.end());
00859           cell.resize(cell.size() - remove_now);
00860         }
00861 
00862         existing_points -= remove_now;
00863         remove_total -= remove_now;
00864       }
00865     }
00866 
00867     goon = existing_points > 0 && remove_total > 0;
00868   }
00869 
00870   // release aux data
00871   for(int i = 0; i < NCells; ++i) delete cells[i];
00872 
00873   // do the actual removal
00874   DUtils::STL::removeIndices(detection.points2d, i_remove, false);
00875   DUtils::STL::removeIndices(detection.points3d, i_remove, false);
00876   DUtils::STL::removeIndices(detection.points3d_model, i_remove, false);
00877   */
00878 }
00879 
00880 // ---------------------------------------------------------------------------
00881 


re_vision
Author(s): Dorian Galvez-Lopez
autogenerated on Sun Jan 5 2014 11:32:01