range_image_border_extractor.cpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Point Cloud Library (PCL) - www.pointclouds.org
00005  *  Copyright (c) 2010-2012, Willow Garage, Inc.
00006  *  Copyright (c) 2012-, Open Perception, Inc.
00007  *
00008  *  All rights reserved.
00009  *
00010  *  Redistribution and use in source and binary forms, with or without
00011  *  modification, are permitted provided that the following conditions
00012  *  are met:
00013  *
00014  *   * Redistributions of source code must retain the above copyright
00015  *     notice, this list of conditions and the following disclaimer.
00016  *   * Redistributions in binary form must reproduce the above
00017  *     copyright notice, this list of conditions and the following
00018  *     disclaimer in the documentation and/or other materials provided
00019  *     with the distribution.
00020  *   * Neither the name of the copyright holder(s) nor the names of its
00021  *     contributors may be used to endorse or promote products derived
00022  *     from this software without specific prior written permission.
00023  *
00024  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00025  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00026  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00027  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00028  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00029  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00030  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00031  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00032  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00033  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00034  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00035  *  POSSIBILITY OF SUCH DAMAGE.
00036  */
00037 
00038 #include <iostream>
00039 using std::cout;
00040 using std::cerr;
00041 #include <map>
00042 #include <set>
00043 #include <cmath>
00044 #include <pcl/pcl_macros.h>
00045 #include <pcl/common/common_headers.h>
00046 #include <pcl/range_image/range_image.h>
00047 #include <pcl/point_cloud.h>
00048 #include <pcl/common/vector_average.h>
00049 #include <pcl/features/eigen.h>
00050 #include <pcl/features/range_image_border_extractor.h>
00051 
00052 namespace pcl 
00053 {
00054 
00056 RangeImageBorderExtractor::RangeImageBorderExtractor(const RangeImage* range_image) : BaseClass(),
00057   parameters_ (), range_image_(range_image), range_image_size_during_extraction_(0),
00058   border_scores_left_(NULL), border_scores_right_(NULL), border_scores_top_(NULL), border_scores_bottom_(NULL),
00059   surface_structure_(NULL), border_descriptions_(NULL), shadow_border_informations_(NULL), border_directions_(NULL),
00060   surface_change_scores_(NULL), surface_change_directions_(NULL)
00061 {
00062 }
00063 
00065 RangeImageBorderExtractor::~RangeImageBorderExtractor()
00066 {
00067   clearData ();
00068 }
00069 
00071 void 
00072 RangeImageBorderExtractor::setRangeImage (const RangeImage* range_image)
00073 {
00074   clearData ();
00075   range_image_ = range_image;
00076 }
00077 
00079 void 
00080 RangeImageBorderExtractor::clearData ()
00081 {
00082   delete[] border_scores_left_;    border_scores_left_   = NULL;
00083   delete[] border_scores_right_;   border_scores_right_  = NULL;
00084   delete[] border_scores_top_;     border_scores_top_    = NULL;
00085   delete[] border_scores_bottom_;  border_scores_bottom_ = NULL;
00086   //cout << PVARC(range_image_size_during_extraction_)<<PVARN((void*)this);
00087   for (int i=0; i<range_image_size_during_extraction_; ++i)
00088   {
00089     if (surface_structure_!=NULL)
00090       delete surface_structure_[i];
00091     if (shadow_border_informations_!=NULL)
00092       delete shadow_border_informations_[i];
00093     if (border_directions_!=NULL)
00094       delete border_directions_[i];
00095   }
00096   delete[] surface_structure_; surface_structure_ = NULL;
00097   delete border_descriptions_; border_descriptions_ = NULL;
00098   delete[] shadow_border_informations_; shadow_border_informations_ = NULL;
00099   delete[] border_directions_; border_directions_ = NULL;
00100   
00101   delete[] surface_change_scores_;  surface_change_scores_ = NULL;
00102   delete[] surface_change_directions_;  surface_change_directions_ = NULL;
00103 }
00104 
00106 void 
00107 RangeImageBorderExtractor::extractLocalSurfaceStructure ()
00108 {
00109   if (surface_structure_ != NULL)
00110     return;
00111   //cerr << __PRETTY_FUNCTION__<<" called (this="<<(void*)this<<").\n";
00112   //MEASURE_FUNCTION_TIME;
00113   
00114   int width  = range_image_->width,
00115       height = range_image_->height;
00116   range_image_size_during_extraction_ = width*height;
00117   int array_size = range_image_size_during_extraction_;
00118   surface_structure_ = new LocalSurface*[array_size];
00119   int step_size = (std::max)(1, parameters_.pixel_radius_plane_extraction/2);
00120   //cout << PVARN(step_size);
00121   int no_of_nearest_neighbors = static_cast<int> (pow (static_cast<double> (parameters_.pixel_radius_plane_extraction/step_size + 1), 2.0));
00122   
00123 # pragma omp parallel for num_threads(parameters_.max_no_of_threads) default(shared) schedule(dynamic, 10)
00124   for (int y=0; y<height; ++y)
00125   {
00126     for (int x=0; x<width; ++x)
00127     {
00128       int index = y*width + x;
00129       LocalSurface*& local_surface = surface_structure_[index];
00130       local_surface = NULL;
00131       if (!range_image_->isValid(index))
00132         continue;
00133       local_surface = new LocalSurface;
00134       Eigen::Vector3f point;
00135       range_image_->getPoint(x, y, point);
00136       //cout << PVARN(point);
00137       if (!range_image_->getSurfaceInformation(x, y, parameters_.pixel_radius_plane_extraction, point,
00138                                   no_of_nearest_neighbors, step_size, local_surface->max_neighbor_distance_squared,
00139                                   local_surface->normal_no_jumps, local_surface->neighborhood_mean_no_jumps,
00140                                   local_surface->eigen_values_no_jumps,  &local_surface->normal,
00141                                   &local_surface->neighborhood_mean, &local_surface->eigen_values))
00142       {
00143         delete local_surface;
00144         local_surface = NULL;
00145       }
00146       
00147       //cout << x<<","<<y<<": ("<<local_surface->normal_no_jumps[0]<<","<<local_surface->normal_no_jumps[1]<<","<<local_surface->normal_no_jumps[2]<<")\n";
00148     }
00149   }
00150 }
00151 
00153 void 
00154 RangeImageBorderExtractor::extractBorderScoreImages ()
00155 {
00156   if (border_scores_left_ != NULL)
00157     return;
00158   
00159   extractLocalSurfaceStructure();
00160   
00161   //MEASURE_FUNCTION_TIME;
00162   
00163   int width  = range_image_->width,
00164       height = range_image_->height,
00165       size   = width*height;
00166   border_scores_left_   = new float[size];
00167   border_scores_right_  = new float[size];
00168   border_scores_top_    = new float[size];
00169   border_scores_bottom_ = new float[size];
00170   
00171 # pragma omp parallel for num_threads(parameters_.max_no_of_threads) default(shared) schedule(dynamic, 10)
00172   for (int y=0; y<height; ++y) {
00173     for (int x=0; x<width; ++x) {
00174       int index = y*width + x;
00175       float& left=border_scores_left_[index]; float& right=border_scores_right_[index];
00176       float& top=border_scores_top_[index]; float& bottom=border_scores_bottom_[index]; 
00177       LocalSurface* local_surface_ptr = surface_structure_[index];
00178       if (local_surface_ptr==NULL)
00179       {
00180         left=right=top=bottom = 0.0f;
00181         continue;
00182       }
00183       
00184       left   = getNeighborDistanceChangeScore(*local_surface_ptr, x, y, -1,  0, parameters_.pixel_radius_borders);
00185       right  = getNeighborDistanceChangeScore(*local_surface_ptr, x, y,  1,  0, parameters_.pixel_radius_borders);
00186       top    = getNeighborDistanceChangeScore(*local_surface_ptr, x, y,  0, -1, parameters_.pixel_radius_borders);
00187       bottom = getNeighborDistanceChangeScore(*local_surface_ptr, x, y,  0,  1, parameters_.pixel_radius_borders);
00188     }
00189   }
00190 }
00191 
00193 float* 
00194 RangeImageBorderExtractor::updatedScoresAccordingToNeighborValues (const float* border_scores) const
00195 {
00196   float* new_scores = new float[range_image_->width*range_image_->height];
00197   float* new_scores_ptr = new_scores;
00198   for (int y=0; y < static_cast<int> (range_image_->height); ++y) 
00199     for (int x=0; x < static_cast<int> (range_image_->width); ++x) 
00200       *(new_scores_ptr++) = updatedScoreAccordingToNeighborValues(x, y, border_scores);
00201   return (new_scores);
00202 }
00203 
00205 void 
00206 RangeImageBorderExtractor::updateScoresAccordingToNeighborValues ()
00207 {
00208   extractBorderScoreImages();
00209   
00210   //MEASURE_FUNCTION_TIME;
00211   
00212   float* left_with_propagated_neighbors = updatedScoresAccordingToNeighborValues(border_scores_left_);
00213   delete[] border_scores_left_;
00214   border_scores_left_ = left_with_propagated_neighbors;
00215   float* right_with_propagated_neighbors = updatedScoresAccordingToNeighborValues(border_scores_right_);
00216   delete[] border_scores_right_;
00217   border_scores_right_ = right_with_propagated_neighbors;
00218   float* top_with_propagated_neighbors = updatedScoresAccordingToNeighborValues(border_scores_top_);
00219   delete[] border_scores_top_;
00220   border_scores_top_ = top_with_propagated_neighbors;
00221   float* bottom_with_propagated_neighbors = updatedScoresAccordingToNeighborValues(border_scores_bottom_);
00222   delete[] border_scores_bottom_;
00223   border_scores_bottom_ = bottom_with_propagated_neighbors;
00224 }
00225  
00227 void 
00228 RangeImageBorderExtractor::findAndEvaluateShadowBorders ()
00229 {
00230   if (shadow_border_informations_ != NULL)
00231     return;
00232   
00233   if (border_scores_left_==NULL)
00234   {
00235     std::cerr << __PRETTY_FUNCTION__<<": border score images not available!\n";
00236   }
00237   
00238   //MEASURE_FUNCTION_TIME;
00239   
00240   int width  = range_image_->width,
00241       height = range_image_->height;
00242   shadow_border_informations_ = new ShadowBorderIndices*[width*height];
00243   for (int y = 0; y < static_cast<int> (height); ++y) 
00244   {
00245     for (int x = 0; x < static_cast<int> (width); ++x) 
00246     {
00247       int index = y*width+x;
00248       ShadowBorderIndices*& shadow_border_indices = shadow_border_informations_[index];
00249       shadow_border_indices = NULL;
00250       int shadow_border_idx;
00251       
00252       if (changeScoreAccordingToShadowBorderValue(x, y, -1, 0, border_scores_left_, border_scores_right_, shadow_border_idx))
00253       {
00254         shadow_border_indices = (shadow_border_indices==NULL ? new ShadowBorderIndices : shadow_border_indices);
00255         shadow_border_indices->left = shadow_border_idx;
00256       }
00257       if (changeScoreAccordingToShadowBorderValue(x, y, 1, 0, border_scores_right_, border_scores_left_, shadow_border_idx))
00258       {
00259         shadow_border_indices = (shadow_border_indices==NULL ? new ShadowBorderIndices : shadow_border_indices);
00260         shadow_border_indices->right = shadow_border_idx;
00261       }
00262       if (changeScoreAccordingToShadowBorderValue(x, y, 0, -1, border_scores_top_, border_scores_bottom_, shadow_border_idx))
00263       {
00264         shadow_border_indices = (shadow_border_indices==NULL ? new ShadowBorderIndices : shadow_border_indices);
00265         shadow_border_indices->top = shadow_border_idx;
00266       }
00267       if (changeScoreAccordingToShadowBorderValue(x, y, 0, 1, border_scores_bottom_, border_scores_top_, shadow_border_idx))
00268       {
00269         shadow_border_indices = (shadow_border_indices==NULL ? new ShadowBorderIndices : shadow_border_indices);
00270         shadow_border_indices->bottom = shadow_border_idx;
00271       }
00272     }
00273   }
00274 }
00275 
00277 float* 
00278 RangeImageBorderExtractor::getAnglesImageForBorderDirections ()
00279 {
00280   calculateBorderDirections();
00281   
00282   int width  = range_image_->width,
00283       height = range_image_->height,
00284       array_size = width*height;
00285   float* angles_image = new float[array_size];
00286   
00287   for (int y=0; y<height; ++y)
00288   {
00289     for (int x=0; x<width; ++x)
00290     {
00291       int index = y*width + x;
00292       float& angle = angles_image[index];
00293       angle = -std::numeric_limits<float>::infinity ();
00294       const Eigen::Vector3f* border_direction_ptr = border_directions_[index];
00295       if (border_direction_ptr == NULL)
00296         continue;
00297       const Eigen::Vector3f& border_direction = *border_direction_ptr;
00298       const PointWithRange& point = range_image_->getPoint(index);
00299       
00300       float border_direction_in_image_x, border_direction_in_image_y;
00301       float tmp_factor = point.range*range_image_->getAngularResolution();
00302       range_image_->getImagePoint(point.x+tmp_factor*border_direction[0], point.y+tmp_factor*border_direction[1], point.z+tmp_factor*border_direction[2],
00303                                 border_direction_in_image_x, border_direction_in_image_y);
00304       border_direction_in_image_x -= static_cast<float> (x);  border_direction_in_image_y -= static_cast<float> (y);
00305       angle = atan2f (border_direction_in_image_y, border_direction_in_image_x);
00306     }
00307   }
00308   return angles_image;
00309 }
00310 
00312 float* 
00313 RangeImageBorderExtractor::getAnglesImageForSurfaceChangeDirections ()
00314 {
00315   //MEASURE_FUNCTION_TIME;
00316   
00317   calculateSurfaceChanges();
00318   
00319   int width  = range_image_->width,
00320       height = range_image_->height,
00321       array_size = width*height;
00322   float* angles_image = new float[array_size];
00323   
00324   for (int y=0; y<height; ++y)
00325   {
00326     for (int x=0; x<width; ++x)
00327     {
00328       int index = y*width + x;
00329       float& angle = angles_image[index];
00330       angle = -std::numeric_limits<float>::infinity ();
00331       float surface_change_score = surface_change_scores_[index];
00332       if (surface_change_score <= 0.1f)
00333         continue;
00334       const Eigen::Vector3f& direction = surface_change_directions_[index];
00335       const PointWithRange& point = range_image_->getPoint(index);
00336       
00337       float border_direction_in_image_x, border_direction_in_image_y;
00338       float tmp_factor = point.range*range_image_->getAngularResolution();
00339       range_image_->getImagePoint(point.x+tmp_factor*direction[0], point.y+tmp_factor*direction[1], point.z+tmp_factor*direction[2],
00340                                 border_direction_in_image_x, border_direction_in_image_y);
00341       border_direction_in_image_x -= static_cast<float> (x);  border_direction_in_image_y -= static_cast<float> (y);
00342       angle = atan2f (border_direction_in_image_y, border_direction_in_image_x);
00343       if (angle <= deg2rad (-90.0f))
00344         angle += static_cast<float> (M_PI);
00345       else if (angle > deg2rad (90.0f))
00346         angle -= static_cast<float> (M_PI);
00347     }
00348   }
00349   return (angles_image);
00350 }
00351 
00352 
00354 void 
00355 RangeImageBorderExtractor::classifyBorders ()
00356 {
00357   if (border_descriptions_ != NULL)
00358     return;
00359   
00360   // Get local plane approximations
00361   extractLocalSurfaceStructure();
00362   
00363   // Get scores for every point, describing how probable a border in that direction is
00364   extractBorderScoreImages();
00365   
00366   // Propagate values to neighboring pixels
00367   updateScoresAccordingToNeighborValues();
00368   
00369   // Change border score according to the existence of a shadow border
00370   findAndEvaluateShadowBorders();
00371   
00372   int width  = range_image_->width,
00373       height = range_image_->height,
00374       size   = width*height;
00375   
00376   BorderDescription initial_border_description;
00377   initial_border_description.traits = 0;
00378   border_descriptions_ = new PointCloudOut;
00379   border_descriptions_->width = width;
00380   border_descriptions_->height = height;
00381   border_descriptions_->is_dense = true;
00382   border_descriptions_->points.resize(size, initial_border_description);
00383   
00384   for (int y = 0; y < static_cast<int> (height); ++y) 
00385   {
00386     for (int x = 0; x < static_cast<int> (width); ++x) 
00387     {
00388       int index = y*width+x;
00389       BorderDescription& border_description = border_descriptions_->points[index];
00390       border_description.x = x;
00391       border_description.y = y;
00392       BorderTraits& border_traits = border_description.traits;
00393       
00394       ShadowBorderIndices* shadow_border_indices = shadow_border_informations_[index];
00395       if (shadow_border_indices == NULL)
00396         continue;
00397       
00398       int shadow_border_index = shadow_border_indices->left;
00399       if (shadow_border_index >= 0 && checkIfMaximum(x, y, -1, 0, border_scores_left_, shadow_border_index))
00400       {
00401         BorderTraits& shadow_traits = border_descriptions_->points[shadow_border_index].traits;
00402         border_traits[BORDER_TRAIT__OBSTACLE_BORDER] = border_traits[BORDER_TRAIT__OBSTACLE_BORDER_LEFT] = true;
00403         shadow_traits[BORDER_TRAIT__SHADOW_BORDER] = shadow_traits[BORDER_TRAIT__SHADOW_BORDER_RIGHT] = true;
00404         for (int index3=index-1; index3>shadow_border_index; --index3)
00405         {
00406           BorderTraits& veil_point = border_descriptions_->points[index3].traits;
00407           veil_point[BORDER_TRAIT__VEIL_POINT] = veil_point[BORDER_TRAIT__VEIL_POINT_RIGHT] = true;
00408         }
00409       }
00410       
00411       shadow_border_index = shadow_border_indices->right;
00412       if (shadow_border_index >= 0 && checkIfMaximum(x, y, 1, 0, border_scores_right_, shadow_border_index))
00413       {
00414         BorderTraits& shadow_traits = border_descriptions_->points[shadow_border_index].traits;
00415         border_traits[BORDER_TRAIT__OBSTACLE_BORDER] = border_traits[BORDER_TRAIT__OBSTACLE_BORDER_RIGHT] = true;
00416         shadow_traits[BORDER_TRAIT__SHADOW_BORDER] = shadow_traits[BORDER_TRAIT__SHADOW_BORDER_LEFT] = true;
00417         for (int index3=index+1; index3<shadow_border_index; ++index3)
00418         {
00419           BorderTraits& veil_point = border_descriptions_->points[index3].traits;
00420           veil_point[BORDER_TRAIT__VEIL_POINT] = veil_point[BORDER_TRAIT__VEIL_POINT_LEFT] = true;
00421         }
00422       }
00423       
00424       shadow_border_index = shadow_border_indices->top;
00425       if (shadow_border_index >= 0 && checkIfMaximum(x, y, 0, -1, border_scores_top_, shadow_border_index))
00426       {
00427         BorderTraits& shadow_traits = border_descriptions_->points[shadow_border_index].traits;
00428         border_traits[BORDER_TRAIT__OBSTACLE_BORDER] = border_traits[BORDER_TRAIT__OBSTACLE_BORDER_TOP] = true;
00429         shadow_traits[BORDER_TRAIT__SHADOW_BORDER] = shadow_traits[BORDER_TRAIT__SHADOW_BORDER_BOTTOM] = true;
00430         for (int index3=index-width; index3>shadow_border_index; index3-=width)
00431         {
00432           //cout << "Adding veil point at "<<(index3-index)%width<<","<<(index3-index)/width<<".\n";
00433           BorderTraits& veil_point = border_descriptions_->points[index3].traits;
00434           veil_point[BORDER_TRAIT__VEIL_POINT] = veil_point[BORDER_TRAIT__VEIL_POINT_BOTTOM] = true;
00435         }
00436       }
00437       
00438       shadow_border_index = shadow_border_indices->bottom;
00439       if (shadow_border_index >= 0 && checkIfMaximum(x, y, 0, 1, border_scores_bottom_, shadow_border_index))
00440       {
00441         BorderTraits& shadow_traits = border_descriptions_->points[shadow_border_index].traits;
00442         border_traits[BORDER_TRAIT__OBSTACLE_BORDER] = border_traits[BORDER_TRAIT__OBSTACLE_BORDER_BOTTOM] = true;
00443         shadow_traits[BORDER_TRAIT__SHADOW_BORDER] = shadow_traits[BORDER_TRAIT__SHADOW_BORDER_TOP] = true;
00444         for (int index3=index+width; index3<shadow_border_index; index3+=width)
00445         {
00446           //cout << "Adding veil point at "<<(index3-index)%width<<","<<(index3-index)/width<<".\n";
00447           BorderTraits& veil_point = border_descriptions_->points[index3].traits;
00448           veil_point[BORDER_TRAIT__VEIL_POINT] = veil_point[BORDER_TRAIT__VEIL_POINT_TOP] = true;
00449         }
00450       }
00451       
00452       //if (border_traits[BORDER_TRAIT__OBSTACLE_BORDER])
00453       //{
00454         //border_points.push_back(&border_description);
00455       //}
00456     }
00457   }
00458 }
00459 
00461 void 
00462 RangeImageBorderExtractor::calculateBorderDirections ()
00463 {
00464   if (border_directions_!=NULL)
00465     return;
00466   classifyBorders();
00467   
00468   //MEASURE_FUNCTION_TIME;
00469   
00470   int width  = range_image_->width,
00471       height = range_image_->height,
00472       size   = width*height;
00473   border_directions_ = new Eigen::Vector3f*[size];
00474   for (int y=0; y<height; ++y)
00475   {
00476     for (int x=0; x<width; ++x)
00477     {
00478       calculateBorderDirection(x, y);
00479     }
00480   }
00481   
00482   Eigen::Vector3f** average_border_directions = new Eigen::Vector3f*[size];
00483   int radius = parameters_.pixel_radius_border_direction;
00484   int minimum_weight = radius+1;
00485   float min_cos_angle=cosf(deg2rad(120.0f));
00486   for (int y=0; y<height; ++y)
00487   {
00488     for (int x=0; x<width; ++x)
00489     {
00490       int index = y*width + x;
00491       Eigen::Vector3f*& average_border_direction = average_border_directions[index];
00492       average_border_direction = NULL;
00493       const Eigen::Vector3f* border_direction = border_directions_[index];
00494       if (border_direction==NULL)
00495         continue;
00496       average_border_direction = new Eigen::Vector3f(*border_direction);
00497       float weight_sum = 1.0f;
00498       for (int y2=(std::max)(0, y-radius); y2<=(std::min)(y+radius, height-1); ++y2)
00499       {
00500         for (int x2=(std::max)(0, x-radius); x2<=(std::min)(x+radius, width-1); ++x2)
00501         {
00502           int index2 = y2*width + x2;
00503           const Eigen::Vector3f* neighbor_border_direction = border_directions_[index2];
00504           if (neighbor_border_direction==NULL || index2==index)
00505             continue;
00506           
00507           // Oposite directions?
00508           float cos_angle = neighbor_border_direction->dot(*border_direction);
00509           if (cos_angle<min_cos_angle)
00510           {
00511             //cout << "Reject. "<<PVARC(min_cos_angle)<<PVARC(cos_angle)<<PVARAN(acosf(cos_angle));
00512             continue;
00513           }
00514           //else
00515             //cout << "No reject\n";
00516           
00517           // Border in between?
00518           float border_between_points_score = getNeighborDistanceChangeScore(*surface_structure_[index], x, y, x2-x,  y2-y, 1);
00519           if (fabsf(border_between_points_score) >= 0.95f*parameters_.minimum_border_probability)
00520             continue;
00521           
00522           *average_border_direction += *neighbor_border_direction;
00523           weight_sum += 1.0f;
00524         }
00525       }
00526       if (pcl_lrint (weight_sum) < minimum_weight)
00527       {
00528         delete average_border_direction;
00529         average_border_direction=NULL;
00530       }
00531       else
00532         average_border_direction->normalize();
00533     }
00534   }
00535   
00536   for (int i=0; i<size; ++i)
00537     delete border_directions_[i];
00538   delete[] border_directions_;
00539   border_directions_ = average_border_directions;
00540 }
00541 
00543 void 
00544 RangeImageBorderExtractor::calculateSurfaceChanges ()
00545 {
00546   if (surface_change_scores_!=NULL)
00547     return;
00548   
00549   calculateBorderDirections();
00550   
00551   //MEASURE_FUNCTION_TIME;
00552   
00553   int width  = range_image_->width,
00554       height = range_image_->height,
00555       size   = width*height;
00556   surface_change_scores_ = new float[size];
00557   surface_change_directions_ = new Eigen::Vector3f[size];
00558 # pragma omp parallel for num_threads(parameters_.max_no_of_threads) default(shared) schedule(dynamic, 10)
00559   for (int y=0; y<height; ++y)
00560   {
00561     for (int x=0; x<width; ++x)
00562     {
00563       int index = y*width + x;
00564       float& surface_change_score = surface_change_scores_[index];
00565       surface_change_score = 0.0f;
00566       Eigen::Vector3f& surface_change_direction = surface_change_directions_[index];
00567       surface_change_direction.setZero();
00568       
00569       const BorderTraits& border_traits = border_descriptions_->points[index].traits;
00570       if (border_traits[BORDER_TRAIT__VEIL_POINT] || border_traits[BORDER_TRAIT__SHADOW_BORDER])
00571         continue;
00572       if (border_directions_[index]!=NULL)
00573       {
00574         surface_change_score = 1.0f;
00575         surface_change_direction = *border_directions_[index];
00576       }
00577       else
00578       {
00579         if (!calculateMainPrincipalCurvature(x, y, parameters_.pixel_radius_principal_curvature,
00580                                              surface_change_score, surface_change_direction))
00581         {
00582           surface_change_score = 0.0f;
00583           continue;
00584         }
00585       }
00586     }
00587   }
00588   //blurSurfaceChanges();
00589 }
00590 
00592 void 
00593 RangeImageBorderExtractor::blurSurfaceChanges ()
00594 {
00595   int blur_radius = 1;
00596   if (blur_radius==0)
00597     return;
00598   
00599   const RangeImage& range_image = *range_image_;
00600   
00601   Eigen::Vector3f* blurred_directions = new Eigen::Vector3f[range_image.width*range_image.height];
00602   float* blurred_scores = new float[range_image.width*range_image.height];
00603   for (int y=0; y<int(range_image.height); ++y)
00604   {
00605     for (int x=0; x<int(range_image.width); ++x)
00606     {
00607       int index = y*range_image.width + x;
00608       Eigen::Vector3f& new_point = blurred_directions[index];
00609       new_point.setZero();
00610       float& new_score = blurred_scores[index];
00611       new_score = 0.0f;
00612       if (!range_image.isValid(index))
00613         continue;
00614       const BorderTraits& border_traits = border_descriptions_->points[index].traits;
00615       if (border_traits[BORDER_TRAIT__VEIL_POINT] || border_traits[BORDER_TRAIT__SHADOW_BORDER])
00616         continue;
00617       const Eigen::Vector3f& point = surface_change_directions_[index];
00618       float counter = 0.0f;
00619       for (int y2=y-blur_radius; y2<y+blur_radius; ++y2)
00620       {
00621         for (int x2=x-blur_radius; x2<x+blur_radius; ++x2)
00622         {
00623           if (!range_image.isInImage(x2,y2))
00624             continue;
00625           int index2 = y2*range_image.width + x2;
00626           float score = surface_change_scores_[index2];
00627           //if (score == 0.0f)
00628             //continue;
00629             //
00630           if (score > 0.0f)
00631           {
00632             Eigen::Vector3f& neighbor = surface_change_directions_[index2];
00633             //if (fabs(neighbor.norm()-1) > 1e-4)
00634               //cerr<<PVARN(neighbor)<<PVARN(score);
00635             if (point.dot(neighbor)<0.0f)
00636               neighbor *= -1.0f;
00637             new_point += score*neighbor;
00638           }
00639           new_score += score;
00640           counter += 1.0f;
00641         }
00642       }
00643       new_point.normalize();
00644       if (counter > 0.0f)
00645         new_score /= counter;
00646     }
00647   }
00648   delete[] surface_change_directions_;
00649   surface_change_directions_ = blurred_directions;
00650   delete[] surface_change_scores_;
00651   surface_change_scores_ = blurred_scores;
00652 }
00653 
00655 void 
00656 RangeImageBorderExtractor::computeFeature (PointCloudOut& output)
00657 {
00658   output.points.clear();
00659   
00660   if (indices_)
00661   {
00662     std::cerr << __PRETTY_FUNCTION__
00663               << ": Sorry, usage of indices for the extraction is not supported for range image border extraction (yet).\n\n";
00664     output.width = output.height = 0;
00665     output.points.clear ();
00666     return;
00667   }
00668   
00669   if (range_image_==NULL)
00670   {
00671     std::cerr << __PRETTY_FUNCTION__
00672               << ": RangeImage is not set. Sorry, the border extraction works on range images, not on normal point clouds."
00673               << " Use setRangeImage(...).\n\n";
00674     output.width = output.height = 0;
00675     output.points.clear ();
00676     return;
00677   }
00678   output = getBorderDescriptions ();
00679 }
00680 
00682 void 
00683 RangeImageBorderExtractor::compute (PointCloudOut& output)
00684 {
00685   computeFeature (output);
00686 }
00687 
00688 }  // namespace end


pcl
Author(s): Open Perception
autogenerated on Wed Aug 26 2015 15:32:01