false_positives_filter.cpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2010, Willow Garage, Inc.
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/or other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of Willow Garage, Inc. nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
00033  *
00034  */
00035 
00036 /* \author Bastian Steder */
00037 
00038 
00039 #include <narf_recognition/false_positives_filter.h>
00040 
00041 using Eigen::Affine3f;
00042 using Eigen::Vector3f;
00043 using std::cout;
00044 using std::cerr;
00045 using std::min;
00046 using std::max;
00047 
00048 namespace pcl {
00049 
00050 FalsePositivesFilter::FalsePositivesFilter() : view_simulation_images_(NULL)
00051 {
00052 }
00053 
00054 FalsePositivesFilter::~FalsePositivesFilter()
00055 {
00056 }
00057 
00058 void
00059 FalsePositivesFilter::getRangeImagesForComparison(const RangeImage& scene, const ObjectModel& model,
00060                                                        const PoseEstimate& pose_estimate,
00061                                                        RangeImage& object_image, RangeImage& scene_sub_image) const
00062 {
00063   int wanted_image_size = 50;  // Ideally so many pixels
00064   float max_angle_size = model.getMaxAngleSize(pose_estimate.transformation);
00065   float wanted_angular_resolution = max_angle_size/float(wanted_image_size);
00066   int combine_pixels = 1;  // How many pixels of the original scene image should be merged to reduce resolution
00067   if (scene.getAngularResolution() < 0.5f*wanted_angular_resolution)
00068     combine_pixels = lrint(floor(wanted_angular_resolution/scene.getAngularResolution()));
00069   float angular_resolution = scene.getAngularResolution()*combine_pixels;
00070   //cout << PVARAC(max_angle_size)<<PVARAC(wanted_angular_resolution)<<PVARC(combine_pixels)<<PVARN(angular_resolution);
00071   
00072   Affine3f model_viewer_pose = pose_estimate.transformation.inverse()*scene.getTransformationToWorldSystem();
00073   model.createView(model_viewer_pose, angular_resolution, object_image);
00074   scene.getSubImage(object_image.getImageOffsetX(), object_image.getImageOffsetY(), object_image.width,
00075                     object_image.height, combine_pixels, scene_sub_image);
00076   
00077   object_image.change3dPointsToLocalCoordinateFrame();
00078   scene_sub_image.change3dPointsToLocalCoordinateFrame();
00079 }
00080 
00081 float
00082 FalsePositivesFilter::getViewSimulationNormalsScore(const RangeImage& object_image, const RangeImage& scene_sub_image,
00083                                                     RangeImage* score_image) const
00084 {
00085   int search_radius = 2;
00086   int no_of_nearest_neighbors = pow(search_radius+1, 2);
00087 
00088   float score=0.0f, weight=0.0f;
00089   int width=object_image.width, height=object_image.height;
00090   
00091   if (score_image != NULL)
00092     *score_image = object_image;
00093   
00094   for (int x=0; x<width; ++x)
00095   {
00096     for (int y=0; y<height; ++y)
00097     {
00098       const PointWithRange& object_pixel = object_image.getPoint(x, y);
00099       if (!pcl_isfinite(object_pixel.range))
00100         continue;
00101       const PointWithRange& model_point = object_image.getPoint(x,y);
00102       Vector3f normal1, normal2;
00103       if (!object_image.getNormalForClosestNeighbors(x, y, search_radius, model_point, no_of_nearest_neighbors, normal1))
00104         continue;
00105       scene_sub_image.getNormalForClosestNeighbors(x, y, search_radius, model_point, no_of_nearest_neighbors, normal2);
00106       
00107       float pixel_score = pow(std::max(normal1.dot(normal2), 0.0f), 2);
00108       
00109       score += pixel_score;
00110       weight += 1.0f;
00111       if (score_image != NULL)
00112       {
00113         score_image->getPoint(x,y).range = pixel_score;
00114       }
00115     }
00116   }
00117   score /= weight;
00118   //cout << PVARN(score);
00119   
00120   return score;
00121 }
00122 
00123 float
00124 FalsePositivesFilter::getViewSimulationScore(const RangeImage& object_image, const RangeImage& scene_sub_image,
00125                                              float max_dist_error, float& border_score, RangeImage* score_image) const
00126 {
00127   float weight_for_see_through_points = parameters_.weight_for_see_through_points;
00128   
00129   //cout << PVARN(object_image)<<PVARN(scene_sub_image)<<PVARN(max_dist_error);
00130   int search_radius = parameters_.pixel_search_radius_for_view_simulation_score;
00131   int search_radius_for_normals = std::max(search_radius, 2);
00132   int no_of_nearest_neighbors = pow(search_radius_for_normals+1, 2);
00133   float max_pixel_distance_reciprocal = 1.0f/(sqrtf(2.0f)*float(search_radius));
00134   float max_dist_error_reciprocal=1.0f/max_dist_error;
00135   
00136   float score=0.0f, weight=0.0f, border_weight=0.0f;
00137   border_score = 0.0f;
00138   int width=object_image.width, height=object_image.height;
00139   
00140   if (score_image != NULL)
00141     *score_image = object_image;
00142   
00143   for (int x=0; x<width; ++x)
00144   {
00145     for (int y=0; y<height; ++y)
00146     {
00147       const PointWithRange& object_pixel = object_image.getPoint(x, y);
00148       if (!pcl_isfinite(object_pixel.range))
00149         continue;
00150       
00151       float pixel_score = 0.0f;
00152       
00153       bool is_border_point = false;
00154       if (parameters_.check_borders_for_view_simulation)
00155         for (int x2=x-1; x2<=x+1; ++x2)
00156           for (int y2=y-1; y2<=y+1; ++y2)
00157             if (object_image.isMaxRange(x2, y2))
00158               is_border_point = true;
00159 
00160       float best_range_dist = -INFINITY;
00161       const PointWithRange* maximum_range_point=NULL, * best_scene_point = NULL;
00162       for (int x2=max(0, x-search_radius); x2<=min(x+search_radius, width-1); ++x2)
00163       {
00164         for (int y2=max(0, y-search_radius); y2<=min(y+search_radius, height-1); ++y2)
00165         {
00166           const PointWithRange& scene_neighbor_pixel= scene_sub_image.getPoint(x2, y2);
00167           if (maximum_range_point==NULL || scene_neighbor_pixel.range>maximum_range_point->range)
00168             maximum_range_point = &scene_neighbor_pixel;
00169           float range_dist = object_pixel.range - scene_neighbor_pixel.range;
00170           best_range_dist = max(best_range_dist, range_dist);
00171           if (fabsf(range_dist) >= max_dist_error)
00172             continue;
00173           float pixel_distance_factor = 1.0f - 0.5f*hypot(x2-x, y2-y)*max_pixel_distance_reciprocal;
00174           //float distance = euclideanDistance(object_pixel, scene_neighbor_pixel);
00175           //if (distance < max_dist_error)
00176           //float current_pixel_score = pixel_distance_factor*(1.0f - distance*max_dist_error_reciprocal);
00177           float current_pixel_score = pixel_distance_factor*(1.0f - fabsf(range_dist)*max_dist_error_reciprocal);
00178           //current_pixel_score = 1.0f - powf(1.0f-current_pixel_score, 2);  // Do some scaling
00179           if (current_pixel_score > pixel_score)
00180           {
00181             pixel_score = current_pixel_score;
00182             best_scene_point = &scene_neighbor_pixel;
00183           }
00184         }
00185       }
00186       bool is_see_through = best_range_dist < -max_dist_error;
00187       
00188       float border_pixel_score = 0.0f;
00189       if (!is_border_point)
00190       {
00191         if (parameters_.check_normals_for_view_simulation && pixel_score > 0.0f)
00192         {
00193           Vector3f normal1, normal2;
00194           if (!object_image.getNormalForClosestNeighbors(x, y, search_radius_for_normals,
00195                                                          object_pixel, no_of_nearest_neighbors, normal1))
00196             continue;
00197           scene_sub_image.getNormalForClosestNeighbors(x, y, search_radius_for_normals, object_pixel,
00198                                                        no_of_nearest_neighbors, normal2);
00199           float normal_score = pow(std::max(normal1.dot(normal2), 0.0f), 1);
00200           //cout << "Score: "<<pixel_score<<", normal score: "<<normal_score<<"\n";
00201           
00202           pixel_score *= normal_score;
00203           
00204           //if (score_image != NULL)
00205           //{
00206             //score_image->getPoint(x,y).range = pixel_score;
00207           //}
00208         }
00209         
00210         score += pixel_score;
00211         weight += (is_see_through ? weight_for_see_through_points : 1.0f);
00212       }
00213       else
00214       {
00215         if (best_scene_point!=NULL && scene_sub_image.getImpactAngle(*best_scene_point, *maximum_range_point) <
00216                                                                                                deg2rad(15.0f))
00217         {
00218           border_pixel_score = pixel_score;
00219           border_score += border_pixel_score;
00220         }
00221         border_weight += 1.0f;
00222       }
00223       
00224       if (score_image != NULL)
00225       {
00226         score_image->getPoint(x,y).range = (is_see_through ? NAN :
00227                                              (is_border_point&&border_pixel_score==0.0f ? -INFINITY : pixel_score));
00228       }
00229     }
00230   }
00231   score /= weight;
00232   border_score /= border_weight;
00233   //cout << PVARC(score) << PVARN(border_score);
00234   
00235   return score;
00236 }
00237 
00238 float
00239 FalsePositivesFilter::getBorderValidationPointScore(const std::vector<Eigen::Vector3f>& border_points,
00240                                                     const Eigen::Affine3f& pose, const RangeImage& scene,
00241                                                     float max_dist_error, float min_score) const
00242 {
00243   int search_radius = parameters_.pixel_search_radius_for_validation_points_score;
00244   int min_no_of_tested_points = parameters_.min_no_of_tested_validation_points;
00245   float min_validation_point_score_to_go_on = parameters_.min_validation_point_score_to_go_on_factor*min_score;
00246   float max_pixel_distance_reciprocal = 1.0f/(sqrtf(2.0f)*float(search_radius));
00247   float score = 0.0f, weight=0.0f;
00248   float max_dist_error_squared = max_dist_error*max_dist_error;
00249   float max_dist_error_reciprocal=1.0f/max_dist_error;
00250   
00251   for (unsigned int points_idx=0; points_idx<border_points.size(); ++points_idx)
00252   {
00253     const Eigen::Vector3f& validation_point = border_points[points_idx];
00254     PointWithRange vp;
00255     vp.getVector3fMap() = pose * validation_point;
00256     
00257     int x, y;
00258     scene.getImagePoint(vp.getVector3fMap(), x, y);
00259     
00260     const PointWithRange* best_found_point=NULL, * maximum_range_point=NULL;
00261     float pixel_score = 0.0f;
00262     for (int x2=x-search_radius; x2<=x+search_radius; ++x2)
00263     {
00264       for (int y2=y-search_radius; y2<=y+search_radius; ++y2)
00265       {
00266         if (!scene.isInImage(x2, y2))
00267           continue;
00268         const PointWithRange& scene_point = scene.getPoint(x2, y2);
00269         if (std::isinf(scene_point.range))
00270         {
00271           if (scene_point.range < 0.0f)
00272             continue;
00273           maximum_range_point = &scene_point;
00274         }
00275         
00276         if (maximum_range_point==NULL || maximum_range_point->range<scene_point.range)
00277           maximum_range_point = &scene_point;
00278         
00279         float distance_squared = squaredEuclideanDistance(scene_point, vp);
00280         if (distance_squared > max_dist_error_squared)
00281           continue;
00282         float pixel_distance = hypot(x2-x, y2-y);
00283         float pixel_distance_factor = 1.0f - 0.25f*pixel_distance*max_pixel_distance_reciprocal;
00284         //cout << PVARC(pixel_distance)<<PVARN(pixel_distance_factor);
00285         float distance = sqrtf(distance_squared);
00286         float current_pixel_score = 1.0f - distance*max_dist_error_reciprocal;
00287         current_pixel_score *= pixel_distance_factor;
00288         //current_pixel_score = powf(current_pixel_score, 0.3f);  // Do some scaling
00289         current_pixel_score = 1.0f - powf(1.0f - current_pixel_score, 2);  // Do some scaling
00290         //cout << PVARC(distance)<<PVARN(current_pixel_score);
00291         
00292         if (current_pixel_score > pixel_score)
00293         {
00294           pixel_score = current_pixel_score;
00295           best_found_point = &scene_point;
00296         }
00297       }
00298     }
00299     if (pixel_score > 0.0f)
00300     {
00301       float impact_angle = scene.getImpactAngle(*best_found_point, *maximum_range_point);
00302       //cout << PVARAN(impact_angle);
00303 //      if (impact_angle > deg2rad(15.0f))
00304       if (impact_angle > deg2rad(15.0f))
00305         pixel_score = 0.0f;
00306     }
00307     
00308     float current_weight = 1.0f;
00309     weight += current_weight;
00310     score += current_weight * (pixel_score-score)/weight;
00311     //cout << points_idx<<": "<<PVARN(score);
00312     
00313     if ((int)points_idx>=min_no_of_tested_points && score<min_validation_point_score_to_go_on)
00314       break;
00315   }
00316   
00317   
00318   return score;
00319 }
00320 float
00321 FalsePositivesFilter::getSurfaceValidationPointScore(const std::vector<Eigen::Vector3f>& surface_points,
00322                                                      const Eigen::Affine3f& pose, const RangeImage& scene,
00323                                                      float max_dist_error, float min_score) const
00324 {
00325   int search_radius = parameters_.pixel_search_radius_for_validation_points_score;
00326   // We give a higher weight to points that have a higher range in the actual scan than predicted,
00327   // since this means we would have seen through our object
00328   float weight_for_see_through_points = parameters_.weight_for_see_through_points;
00329   int min_no_of_tested_points = parameters_.min_no_of_tested_validation_points;
00330   float min_validation_point_score_to_go_on = parameters_.min_validation_point_score_to_go_on_factor*min_score;
00331   float max_pixel_distance_reciprocal = 1.0f/(sqrtf(2.0f)*float(search_radius));
00332   float score = 0.0f, weight=0.0f;
00333   float max_dist_error_squared = max_dist_error*max_dist_error;
00334   float max_dist_error_reciprocal=1.0f/max_dist_error;
00335   Vector3f sensor_pos = scene.getSensorPos();
00336   
00337   for (unsigned int points_idx=0; points_idx<surface_points.size(); ++points_idx)
00338   {
00339     const Eigen::Vector3f& validation_point = surface_points[points_idx];
00340     Eigen::Vector3f transformed_point = pose * validation_point;
00341     PointWithRange vp;
00342     vp.x=transformed_point[0]; vp.y=transformed_point[1]; vp.z=transformed_point[2];
00343     vp.range = (sensor_pos-transformed_point).norm();
00344     float max_range_in_scene = vp.range+max_dist_error;
00345     
00346     int x, y;
00347     scene.getImagePoint(transformed_point, x, y);
00348     
00349     float pixel_score = 0.0f;
00350     bool all_checked_pixel_too_far_away = true;
00351     for (int x2=x-search_radius; x2<=x+search_radius; ++x2)
00352     {
00353       for (int y2=y-search_radius; y2<=y+search_radius; ++y2)
00354       {
00355         if (!scene.isInImage(x2, y2))
00356         {
00357           all_checked_pixel_too_far_away = false;
00358           continue;
00359         }
00360         const PointWithRange& scene_point = scene.getPoint(x2, y2);
00361         if (!pcl_isfinite(scene_point.range))
00362         {
00363           if (scene_point.range < 0.0f)
00364             all_checked_pixel_too_far_away = false;
00365           continue;
00366         }
00367         if (scene_point.range < max_range_in_scene)
00368           all_checked_pixel_too_far_away = false;
00369         
00370         float distance_squared = squaredEuclideanDistance(scene_point, vp);
00371         if (distance_squared > max_dist_error_squared)
00372           continue;
00373         
00374         float pixel_distance = hypot(x2-x, y2-y);
00375         float pixel_distance_factor = 1.0f - 0.25f*pixel_distance*max_pixel_distance_reciprocal;
00376         //cout << PVARC(pixel_distance)<<PVARN(pixel_distance_factor);
00377         float distance = sqrtf(distance_squared);
00378         float current_pixel_score = 1.0f - distance*max_dist_error_reciprocal;
00379         current_pixel_score *= pixel_distance_factor;
00380         current_pixel_score = 1.0f - powf(1.0f-current_pixel_score, 2);  // Do some scaling
00381         //cout << PVARC(distance)<<PVARN(current_pixel_score);
00382         
00383         pixel_score = max(pixel_score, current_pixel_score);
00384       }
00385     }
00386     
00387     float current_weight = (all_checked_pixel_too_far_away ? weight_for_see_through_points : 1.0f);
00388     weight += current_weight;
00389     score += current_weight * (pixel_score-score)/weight;
00390     //cout << points_idx<<": "<<PVARN(score);
00391     
00392     if ((int)points_idx>=min_no_of_tested_points && score<min_validation_point_score_to_go_on)
00393       break;
00394   }
00395   
00396   return score;
00397 }
00398 
00399 void
00400 FalsePositivesFilter::validationPoints(const RangeImage& scene, const ObjectModel& model, PoseEstimates& pose_estimates,
00401                                        float min_score, float max_dist_error) const
00402 {
00403   //MEASURE_FUNCTION_TIME;
00404   //cout << __PRETTY_FUNCTION__<<" called with "<<PVARC(min_score)<<PVARN(max_dist_error);
00405   
00406   if (max_dist_error < 0.0f)
00407     max_dist_error = 0.2*model.getRadius();
00408   //PoseEstimates updated_pose_estimates;
00409   
00410   #pragma omp parallel for default(shared) num_threads(parameters_.max_no_of_threads) schedule(dynamic, 10)
00411   for (unsigned int pose_estimate_idx=0; pose_estimate_idx<pose_estimates.size(); ++pose_estimate_idx)
00412   {
00413     PoseEstimate& pose_estimate = pose_estimates[pose_estimate_idx];
00414     Affine3f model_viewer_pose = pose_estimate.transformation.inverse()*scene.getTransformationToWorldSystem();
00415     int view_idx = model.getClosestValidationPointViewIdx(model_viewer_pose);
00416     const ObjectModel::ValidationPoints& validation_points = model.getValidationPoints()[view_idx];
00417     
00418     float surface_score = getSurfaceValidationPointScore(validation_points.surface, pose_estimate.transformation,
00419                                                          scene, max_dist_error, min_score);
00420     if (surface_score < min_score) {
00421       pose_estimate.score = surface_score;
00422       //cout << "Rejecting a result with surface score "<<surface_score<<"(min score is "<<min_score<<").\n";
00423       continue;
00424     }
00425     float score = surface_score;
00426     
00427     if (!validation_points.border.empty() && parameters_.check_borders_for_validation_points)
00428     {
00429       float border_score = getBorderValidationPointScore(validation_points.border, pose_estimate.transformation,
00430                                                          scene, max_dist_error, min_score);
00431       //if (border_score < min_score)
00432       //{
00434         //continue;
00435       //}
00436       
00437       //cout << "Accepting a result with border score "<<border_score<<"(min score is "<<min_score<<").\n";
00438       //score = 0.5f*(surface_score+border_score);
00439       score = std::min(surface_score, border_score);
00440     }
00441     
00442     //if (score < min_score)
00443     //{
00445       //continue;
00446     //}
00447     
00448     //cout << "Result has score "<<score<<".\n";
00449     
00450     //cout << "Used view: "<<view_idx<<"\n";
00451     //#pragma omp critical
00452     //{
00453       //updated_pose_estimates.push_back(pose_estimate);
00454       //updated_pose_estimates.back().score = score;
00455     //}
00456     pose_estimate.score = score;
00457   }
00458   
00459   //cout << updated_pose_estimates.size()<<"/"<<pose_estimates.size()<<" object poses of model \""<<model.getName()
00460   //     << "\" left after validation point filtering.";
00461   //int maxNoOfPrintedScores = 10;
00462   //cout << (pose_estimates.empty() ? "" : " Scores are ");
00463   //for (unsigned int i=0; i<std::min(maxNoOfPrintedScores, int(pose_estimates.size())); ++i)
00464     //cout << (i>0?", ":"") << pose_estimates[i].score; cout<<".";
00465   //cout << "\n";
00466   
00467   //pose_estimates = updated_pose_estimates;
00468 }
00469 
00470 void
00471 FalsePositivesFilter::keepBest(PoseEstimates& pose_estimates, int max_no_of_results) const
00472 {
00473   //MEASURE_FUNCTION_TIME;
00474   
00475   std::sort(pose_estimates.begin(), pose_estimates.end(), PoseEstimate::IsBetter());
00476   pose_estimates.resize(max_no_of_results);
00477   //while ((int)pose_estimates.size() > max_no_of_results)
00478     //pose_estimates.pop_back();
00479   
00480   //cout << "Kept only "<<pose_estimates.size()<<" best matches.";
00481   //cout << (pose_estimates.empty() ? "" : " Scores are ");
00482   //for (unsigned int i=0; i<pose_estimates.size(); ++i) cout << (i>0?", ":"") << pose_estimates[i].score; cout<<".";
00483   //cout << "\n";
00484   
00485 }
00486 
00487 void
00488 FalsePositivesFilter::viewSimulation(const RangeImage& scene, const ObjectModel& model, PoseEstimates& pose_estimates,
00489                                      float min_score, float max_dist_error, std::vector<RangeImage>* results) const
00490 {
00491   //MEASURE_FUNCTION_TIME;
00492 
00493   if (max_dist_error < 0.0f)
00494     max_dist_error = 0.2*model.getRadius();
00495   //PoseEstimates updated_pose_estimates;
00496   //cout << PVARN(parameters_.max_no_of_threads);
00497   
00498   #pragma omp parallel for num_threads(parameters_.max_no_of_threads) default(shared) schedule(dynamic, 1)
00499   for (int pose_estimate_idx=0; pose_estimate_idx<pose_estimates.size(); ++pose_estimate_idx)
00500   {
00501     PoseEstimate& pose_estimate = pose_estimates[pose_estimate_idx];
00502     pose_estimate.score = 0.0f;
00503     
00504     RangeImage object_image, scene_sub_image, score_image, score_image2;
00505     getRangeImagesForComparison(scene, model, pose_estimate, object_image, scene_sub_image);
00506     float score_borders;
00507     float score = getViewSimulationScore(object_image, scene_sub_image, max_dist_error, score_borders,
00508                                          (results!=NULL ? &score_image : NULL));
00509     //cout << "Result has score "<<score<<".\n";
00510     
00511     //if (score < min_score)
00512     //{
00514       //continue;
00515     //}
00516     //float score_weight = 1.0f;
00517     
00518     if (parameters_.check_borders_for_view_simulation)
00519     {
00520       score = std::min(score, score_borders);
00521       //if (score_borders < min_score)
00522       //{
00524         //continue;
00525       //}
00526       //score += score_borders;
00527       //score_weight += 1.0f;
00528     }
00529     
00530     //if (parameters_.check_normals_for_view_simulation)
00531     //{
00532       //float score_normals = getViewSimulationNormalsScore(object_image, scene_sub_image,
00533                                                           //(results!=NULL ? &score_image2 : NULL));
00534       //if (score_normals < min_score)
00535       //{
00537         //continue;
00538       //}
00539       //score += score_normals;
00540       //score_weight += 1.0f;
00541     //}
00542     
00543     //score /= score_weight;
00544     pose_estimate.score = score;
00545     
00546     if (score>min_score && results!=NULL)
00547     {
00548       #pragma omp critical
00549       {
00550         results->push_back(object_image);
00551         results->push_back(scene_sub_image);
00552         results->push_back(score_image);
00553         results->push_back(score_image2);
00554       }
00555     }
00556   }
00557   
00558   //int maxNoOfPrintedScores = 10;
00559   //cout << (pose_estimates.empty() ? "" : " Scores are ");
00560   //for (unsigned int i=0; i<std::min(maxNoOfPrintedScores, int(pose_estimates.size())); ++i)
00561     //cout << (i>0?", ":"") << pose_estimates[i].score; cout<<".";
00562   //cout << "\n";
00563 
00564   //cout << updated_pose_estimates.size()<<"/"<<pose_estimates.size()<<" object poses of model \""<<model.getName()
00565        //<< "\" left after view simulation filtering.";
00566   //int maxNoOfPrintedScores = 10;
00567   //cout << (pose_estimates.empty() ? "" : " Scores are ");
00568   //for (unsigned int i=0; i<std::min(maxNoOfPrintedScores, int(pose_estimates.size())); ++i)
00569     //cout << (i>0?", ":"") << pose_estimates[i].score; cout<<".";
00570   //cout << "\n";
00571   
00572   //pose_estimates = updated_pose_estimates;
00573 }
00574 
00575 void
00576 FalsePositivesFilter::maximumRange(const RangeImage& scene, const ObjectModel& model,
00577                                    PoseEstimates& pose_estimates, float maximum_range) const
00578 {
00579   //MEASURE_FUNCTION_TIME;
00580   float maximum_range_squared = maximum_range*maximum_range;
00581   PoseEstimates updated_pose_estimates;
00582   Vector3f sensor_pos = scene.getSensorPos();
00583   for (unsigned int i=0; i<pose_estimates.size(); ++i)
00584   {
00585     const PoseEstimate& pose_estimate = pose_estimates[i];
00586     Vector3f model_center_in_world = pose_estimate.transformation * model.getCenter();
00587     if ((model_center_in_world-sensor_pos).squaredNorm() > maximum_range_squared)
00588       continue;
00589     updated_pose_estimates.push_back(pose_estimate);
00590   }
00591   
00592   cout << updated_pose_estimates.size()<<"/"<<pose_estimates.size()<<" object poses of model \""<<model.getName()
00593        << "\" left after filtering maximum ranges.\n";
00594   pose_estimates = updated_pose_estimates;
00595 }
00596 
00597 void
00598 FalsePositivesFilter::similarPoses(const ObjectModel& model, PoseEstimates& pose_estimates) const
00599 {
00600   //MEASURE_FUNCTION_TIME;
00601   float min_distance = 0.3*model.getRadius(),
00602         min_distance_squared = min_distance*min_distance;
00603   //cout << PVARN(min_distance);
00604   PoseEstimates updated_pose_estimates;
00605   for (unsigned int i=0; i<pose_estimates.size(); ++i)
00606   {
00607     const PoseEstimate& pose_estimate1 = pose_estimates[i];
00608     Vector3f center1 = pose_estimate1.transformation * model.getCenter();
00609     bool keep = true;
00610     for (unsigned int j=0; j<pose_estimates.size(); ++j)
00611     {
00612       if (i==j)
00613         continue;
00614       const PoseEstimate& pose_estimate2 = pose_estimates[j];
00615       if (pose_estimate2.score < pose_estimate1.score || (pose_estimate2.score == pose_estimate1.score && i<j))
00616         continue;
00617       Vector3f center2 = pose_estimate2.transformation * model.getCenter();
00618       float squared_distance = (center2-center1).squaredNorm();
00619       if (squared_distance >= min_distance_squared)
00620         continue;
00621       //cout << "Not keeping "<<i<<"("<<pose_estimate1.score<<"), since its distance to "<<j
00622       //     << "("<<pose_estimate2.score<<") is "<<sqrtf(squared_distance)<<".\n";
00623       //if (squared_distance==0.0f)
00624         //cout << "Identical results!\n";
00625       keep = false;
00626       break;
00627     }
00628     if (keep)
00629     {
00630       //cout << "Keeping "<<i<<"("<<pose_estimate1.score<<").\n";
00631       updated_pose_estimates.push_back(pose_estimate1);
00632     }
00633   }
00634   
00635   cout << updated_pose_estimates.size()<<"/"<<pose_estimates.size()<<" object poses of model \""<<model.getName()
00636        << "\" left after filtering of similar poses.";
00637   //cout << (pose_estimates.empty() ? "" : " Scores are ");
00638   //for (unsigned int i=0; i<updated_pose_estimates.size(); ++i)
00639   //  cout << (i>0?", ":"") << updated_pose_estimates[i].score;
00640   //cout<<".";
00641   cout << "\n";
00642   
00643   pose_estimates = updated_pose_estimates;
00644 }
00645 
00646 void
00647 FalsePositivesFilter::sortAndApplyMinScore(PoseEstimates& pose_estimates, float min_score) const
00648 {
00649   std::sort(pose_estimates.begin(), pose_estimates.end(), pcl::PosesFromMatches::PoseEstimate::IsBetter());
00650   for (unsigned int pose_estimate_idx=0; pose_estimate_idx<pose_estimates.size(); ++pose_estimate_idx)
00651     if (pose_estimates[pose_estimate_idx].score < min_score)
00652       pose_estimates.resize(pose_estimate_idx);
00653 }
00654 
00655 void
00656 FalsePositivesFilter::doIcp(const RangeImage& scene, const ObjectModel& model,
00657                             PoseEstimates& pose_estimates, bool fast_icp) const
00658 {
00659   #pragma omp parallel for default(shared) num_threads(parameters_.max_no_of_threads) schedule(dynamic, 10)
00660   for (unsigned int pose_estimate_idx=0; pose_estimate_idx<pose_estimates.size(); ++pose_estimate_idx)
00661   {
00662     PosesFromMatches::PoseEstimate& pose_estimate = pose_estimates[pose_estimate_idx];
00663     if (fast_icp)
00664     {
00665       pose_estimate.transformation = model.doFastICP(pose_estimate.transformation, scene,
00666                                                      parameters_.icp_pixel_search_radius,
00667                                                      parameters_.fast_icp_no_of_surface_points_to_use,
00668                                                      parameters_.fast_icp_no_of_border_points_to_use,
00669                                                      parameters_.icp_num_iterations,
00670                                                      parameters_.icp_max_distance_start,
00671                                                      parameters_.icp_max_distance_end);
00672     }
00673     else
00674     {
00675       pose_estimate.transformation = model.doSlowICP(pose_estimate.transformation, scene,
00676                                                      parameters_.icp_pixel_search_radius,
00677                                                      parameters_.icp_num_iterations,
00678                                                      parameters_.icp_max_distance_start,
00679                                                      parameters_.icp_max_distance_end);
00680     }
00681   }
00682 }
00683 
00684 void
00685 FalsePositivesFilter::filterResults(const RangeImage& scene, const ObjectModel& model,
00686                                     PoseEstimates& pose_estimates) const
00687 {
00688   cout << "Initial no of pose estimates: "<<pose_estimates.size()<<"\n";
00689   int maxNoOfPrintedScores = 10;
00690   
00691   if (parameters_.maximum_range_for_found_objects > 0.0f)
00692     maximumRange(scene, model, pose_estimates, parameters_.maximum_range_for_found_objects);
00693   
00696 
00697   if (parameters_.do_icp)
00698   {
00699     if (parameters_.do_validation_point_filtering)
00700     {
00701       double validation_point_score1_time = -getTime();
00702       float max_validation_point_error_before_icp = parameters_.max_validation_point_error_before_icp_factor *
00703                                                     parameters_.max_validation_point_error,
00704             min_validation_point_score_before_icp = parameters_.min_validation_point_score_before_icp_factor *
00705                                                     parameters_.min_validation_point_score;
00706       validationPoints(scene, model, pose_estimates,
00707                        min_validation_point_score_before_icp,
00708                        max_validation_point_error_before_icp);
00709       sortAndApplyMinScore(pose_estimates, min_validation_point_score_before_icp);
00710       if (parameters_.do_pose_similarity_filtering)
00711         similarPoses(model, pose_estimates);
00712       //poseEstimates.resize(std::min(int(poseEstimates.size()), parameters.maxNoOfRemainingPoseEstimatesForICP));
00713       //time_pose_scoring += get_time();
00714       validation_point_score1_time += getTime();
00715       cout << PVARN(validation_point_score1_time);
00716       cout << "No of pose estimates after first validation point scoring: "<<pose_estimates.size()<<"\n";
00717       
00718       cout << (pose_estimates.empty() ? "" : " Scores are ");
00719       for (unsigned int i=0; i<std::min(maxNoOfPrintedScores, int(pose_estimates.size())); ++i)
00720         cout << (i>0?", ":"") << pose_estimates[i].score; cout<<".";
00721       cout << "\n";
00722     }
00723     
00724     double icp_time = -getTime();
00725     doIcp(scene, model, pose_estimates, true);
00726     icp_time += getTime();
00727     cout << PVARN(icp_time);
00728   }
00729   
00730   if (parameters_.do_validation_point_filtering)
00731   {
00732     double validation_point_score2_time = -getTime();
00733     float max_validation_point_error = parameters_.max_validation_point_error,
00734           min_validation_point_score = parameters_.min_validation_point_score;
00735     validationPoints(scene, model, pose_estimates, min_validation_point_score, max_validation_point_error);
00736     sortAndApplyMinScore(pose_estimates, min_validation_point_score);
00737     if (parameters_.do_pose_similarity_filtering)
00738       similarPoses(model, pose_estimates);
00739     validation_point_score2_time += getTime();
00740     cout << PVARN(validation_point_score2_time);
00741     cout << "No of pose estimates after second validation point scoring: "<<pose_estimates.size()<<"\n";
00742     
00743     cout << (pose_estimates.empty() ? "" : " Scores are ");
00744     for (unsigned int i=0; i<std::min(maxNoOfPrintedScores, int(pose_estimates.size())); ++i)
00745       cout << (i>0?", ":"") << pose_estimates[i].score; cout<<".";
00746     cout << "\n";
00747   }
00748 
00749   if (parameters_.do_view_simulation_filtering)
00750   {
00751     double view_simulation_time = -getTime();
00752     float max_view_simulation_point_error = parameters_.max_validation_point_error,
00753           min_view_simulation_score = parameters_.min_view_simulation_score;
00754     viewSimulation(scene, model, pose_estimates, min_view_simulation_score,
00755                    max_view_simulation_point_error, view_simulation_images_);
00756     sortAndApplyMinScore(pose_estimates, parameters_.min_view_simulation_score);
00757     view_simulation_time += getTime();
00758     cout << PVARN(view_simulation_time);
00759     cout << "No of pose estimates after view simulation scoring: "<<pose_estimates.size()<<"\n";
00760     
00761     cout << (pose_estimates.empty() ? "" : " Scores are ");
00762     for (unsigned int i=0; i<std::min(maxNoOfPrintedScores, int(pose_estimates.size())); ++i)
00763       cout << (i>0?", ":"") << pose_estimates[i].score; cout<<".";
00764     cout << "\n";
00765   }
00766   
00767   //double icp2_time = -getTime();
00768   //doIcp(scene, model, pose_estimates, false);
00769   //icp2_time += getTime();
00770   //cout << PVARN(icp2_time);
00771   
00772   //if (parameters_.do_view_simulation_filtering)
00773   //{
00774     //double view_simulation2_time = -getTime();
00775     //float max_view_simulation_point_error = parameters_.max_validation_point_error,
00776           //min_view_simulation_score = parameters_.min_view_simulation_score;
00777     //viewSimulation(scene, model, pose_estimates, min_view_simulation_score,
00778                    //0.5f*max_view_simulation_point_error, view_simulation_images_);
00779     //sortAndApplyMinScore(pose_estimates, parameters_.min_view_simulation_score);
00781     //view_simulation2_time += getTime();
00782     //cout << PVARN(view_simulation2_time);
00783     //cout << "No of pose estimates after second view simulation scoring: "<<pose_estimates.size()<<"\n";
00784     
00785     //cout << (pose_estimates.empty() ? "" : " Scores are ");
00786     //for (unsigned int i=0; i<std::min(maxNoOfPrintedScores, int(pose_estimates.size())); ++i)
00787       //cout << (i>0?", ":"") << pose_estimates[i].score; cout<<".";
00788     //cout << "\n";
00789   //}
00790     
00791   //if (print_timings)
00792   //{
00793     //std::multimap<double, string> timings;
00794     //double time_sum=0.0, time_sum_constant=0.0;
00795     //#define ADD_TIMING(time_variable, dependent_on_database_size) \
00796     //{\
00797       //timings.insert(std::make_pair(time_variable, #time_variable)); \
00798       //time_sum += time_variable;\
00799       //if (!dependent_on_database_size) \
00800         //time_sum_constant += time_variable; \
00801     //}
00802     //ADD_TIMING(time_scene_range_image_creation, false);
00803     //ADD_TIMING(time_interest_point_extraction, false);
00804     //ADD_TIMING(time_feature_extraction, false);
00805     //ADD_TIMING(time_feature_matching, true);
00806     //ADD_TIMING(time_pose_estimation, true);
00807     //ADD_TIMING(time_false_positives_removal, true);
00808     //if (do_icp)
00809       //ADD_TIMING(time_icp, true);
00810     //if (do_view_simulation_filtering)
00811       //ADD_TIMING(time_view_simulation, true);
00812     //#undef ADD_TIMING
00813     //cout << "\nTIMINGS:\n========\n";
00814     //for (std::multimap<double, string>::const_reverse_iterator it=timings.rbegin(); it!=timings.rend(); ++it)
00815       //cout << it->second<<" = "<<it->first<<"s\n";
00816     //cout << "\nComplete process took "<<time_sum<<"s ("<<time_sum_constant<<"s for scan analysis, "
00817     //     << time_sum-time_sum_constant<<"s for object search).\n\n";
00818   //}
00819   
00820 }
00821 
00822 } // namespace end
00823 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Friends


chair_recognition
Author(s): Jan Metzger
autogenerated on Wed Dec 26 2012 15:54:47