object_model.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/object_model.h>
00040 
00041 #include <pcl/common/transformation_from_correspondences.h>
00042 #include <pcl/common/transforms.h>
00043 #include <iostream>
00044 using std::cout;
00045 using std::cerr;
00046 using std::string;
00047 using std::min;
00048 using std::max;
00049 using std::vector;
00050 #include <cmath>
00051 
00052 #include <pcl/common/common_headers.h>
00053 
00054 #include <pcl/features/range_image_border_extractor.h>
00055 #include <pcl/keypoints/narf_keypoint.h>
00056 
00057 using Eigen::Vector3f;
00058 using Eigen::Affine3f;
00059 
00060 namespace pcl {
00061 
00062 ObjectModel::ObjectModel()
00063 {
00064   clear();
00065 }
00066 
00067 ObjectModel::~ObjectModel()
00068 {
00069   clear();
00070 }
00071 
00072 void ObjectModel::clear(bool keep_point_cloud)
00073 {
00074   id_ = 0;
00075   name_ = "";
00076   if (!keep_point_cloud)
00077     point_cloud_ = PointCloudType();
00078   clearViews();
00079   center_ = Vector3f(0.0f, 0.0f, 0.0f);
00080   radius_ = 0.0f;
00081   is_single_view_model_ = false;
00082 }
00083 
00084 void ObjectModel::clearViews()
00085 {
00086   views_.clear();
00087   views_for_validation_points_.clear();
00088   validation_points_.clear();
00089 }
00090 
00091 void ObjectModel::updateCenterAndRadius()
00092 {
00093   // Get bounding box
00094   Vector3f bb_min(INFINITY, INFINITY, INFINITY), bb_max(-INFINITY, -INFINITY, -INFINITY);
00095   for (unsigned int i=0; i<point_cloud_.points.size(); ++i)
00096   {
00097     const PointType& p = point_cloud_.points[i];
00098     bb_min[0]=min(bb_min[0], p.x);  bb_min[1]=min(bb_min[1], p.y);  bb_min[2]=min(bb_min[2], p.z);
00099     bb_max[0]=max(bb_max[0], p.x);  bb_max[1]=max(bb_max[1], p.y);  bb_max[2]=max(bb_max[2], p.z);
00100   }
00101   center_ = 0.5f * (bb_min+bb_max);
00102   
00103   radius_ = 0.0f;
00104   for (unsigned int i=0; i<point_cloud_.points.size(); ++i)
00105   {
00106     const PointType& p = point_cloud_.points[i];
00107     radius_ = max(radius_, (center_-Vector3f(p.x, p.y, p.z)).norm());
00108   }
00109   //cout << "Object center is ("<<center_[0]<<","<<center_[1]<<","<<center_[2]<<") with radius "<<radius_<<"m.\n";
00110 }
00111 
00112 void ObjectModel::sampleViews2D(int no_of_views, int first_layer, int last_layer,
00113                                 float angular_resolution, float distance,
00114                                 std::vector<RangeImage, Eigen::aligned_allocator<RangeImage> >* views)
00115 {
00116   //cout << __PRETTY_FUNCTION__<<" was called.\n";
00117   views = (views==NULL ? &views_ : views);
00118   if (radius_ == 0.0f)
00119   {
00120     cerr << __PRETTY_FUNCTION__<<": radius_ is 0.0 => calling updateCenterAndRadius()\n";
00121     updateCenterAndRadius();
00122   }
00123   
00124   for (int layer=first_layer; layer<=last_layer; ++layer) {
00125     for (int view_index=0; view_index<no_of_views; ++view_index)
00126     {
00127       float angle = deg2rad(360.f)*float(view_index)/float(no_of_views) - deg2rad(180.f);
00128       Vector3f direction(cosf(angle), -0.5f*float(layer), sinf(angle));
00129       addSimulatedView(direction, angular_resolution, distance, views);
00130     }
00131   }
00132 }
00133 
00134 void ObjectModel::sampleViews3D(float sample_angular_resolution, float angular_resolution, float distance,
00135                                 std::vector<RangeImage, Eigen::aligned_allocator<RangeImage> >* views)
00136 {
00137   views = (views==NULL ? &views_ : views);
00138   if (radius_ == 0.0f)
00139   {
00140     cerr << __PRETTY_FUNCTION__<<": radius_ is 0.0 => calling updateCenterAndRadius()\n";
00141     updateCenterAndRadius();
00142   }
00143   
00144   int no_of_steps_y = lrint(deg2rad(180.0f)/sample_angular_resolution)+1;
00145   //cout << PVARN(no_of_steps_y);
00146   float step_size_y = deg2rad(180.0f)/float(no_of_steps_y-1);
00147   for (int step_y=0; step_y<no_of_steps_y; ++step_y)
00148   {
00149     float angle_y = step_y*step_size_y - deg2rad(90.0f);
00150     int no_of_steps_x = max(1, (int)(lrint(cosf(angle_y)*deg2rad(360.0f) / sample_angular_resolution)));
00151     //cout<<PVARN(no_of_steps_x);
00152     float step_size_x = deg2rad(360.0f)/float(no_of_steps_x);
00153     
00154     for (int step_x=0; step_x<no_of_steps_x; ++step_x)
00155     {
00156       float angle_x = step_x*step_size_x - deg2rad(180.0f);
00157       //cout << PVARAC(angle_x)<<PVARAN(angle_y);
00158       Vector3f direction(sinf(angle_x) * cosf(angle_y), sinf(angle_y), cosf(angle_x)*cosf(angle_y));
00159       //cout << "Sample direction for angles ("<<rad2deg(angle_x)<<","<<rad2deg(angle_y)<<") is ("<<direction[0]<<","<<direction[1]<<","<<direction[2]<<")\n";
00160       addSimulatedView(direction, angular_resolution, distance, views);
00161     }
00162   }
00163 }
00164 
00165 void ObjectModel::addSimulatedView(const Vector3f& direction, float angular_resolution, float distance,
00166                                    std::vector<RangeImage, Eigen::aligned_allocator<RangeImage> >* views)
00167 {
00168   views = (views==NULL ? &views_ : views);
00169   if (distance <= 0.0f)
00170     distance = 5.0f*radius_;
00171   
00172   Vector3f viewpoint = center_ + (radius_+distance)*direction;
00173   float actual_distance = INFINITY;
00174   for (unsigned int i=0; i<point_cloud_.points.size(); ++i)
00175   {
00176     const PointType& p = point_cloud_.points[i];
00177     actual_distance = min(actual_distance, (viewpoint-Vector3f(p.x, p.y, p.z)).norm());
00178   }
00179   // Approximate method to get closer to the real distance
00180   viewpoint = viewpoint - (actual_distance-distance)*direction;
00181   //cout << "Viewpoint is ("<<viewpoint[0]<<","<<viewpoint[1]<<","<<viewpoint[2]<<").\n";
00182   Affine3f viewer_pose = getViewerPose(viewpoint);
00183   
00184   views->push_back(RangeImage());
00185   RangeImage& view = views->back();
00186   //cout << "Starting creating view for pose \n"<<viewer_pose<<" and point cloud of size "<<point_cloud_.points.size()<<"\n";
00187   createView(viewer_pose, angular_resolution, view);
00188 }
00189 
00190 float ObjectModel::getMaxAngleSize(const Eigen::Affine3f& viewer_pose) const
00191 {
00192   return RangeImage::getMaxAngleSize(viewer_pose, center_, radius_);
00193 }
00194 
00195 void ObjectModel::addView(const Eigen::Affine3f& viewer_pose, float angular_resolution)
00196 {
00197   //cout << PVARN(point_cloud_.points.size())<<PVARN(radius_);
00198   views_.push_back(RangeImage());
00199   createView(viewer_pose, angular_resolution, views_.back());
00200 }
00201 
00202 void ObjectModel::createView(const Affine3f& viewer_pose, float angular_resolution, RangeImage& view) const
00203 {
00204   float noise_level = 0.05f*radius_;
00205   view.createFromPointCloud(point_cloud_, angular_resolution, deg2rad(360.0f), deg2rad(180.0f), viewer_pose, RangeImage::CAMERA_FRAME, noise_level, 0.0, 1);
00206   //view.createFromPointCloudWithKnownSize(point_cloud_, angular_resolution, center_, radius_, viewer_pose, RangeImage::CAMERA_FRAME, 0.0, 0.0, 1); // damn, doesn't work for objects with large radius
00207   view.setUnseenToMaxRange();
00208 }
00209 
00210 Affine3f ObjectModel::getViewerPose(const Vector3f& viewpoint) const
00211 {
00212   Affine3f viewer_pose;
00213   Vector3f viewing_direction = (center_-viewpoint).normalized(),
00214            up_vector(0.0f, 1.0f, 0.0f);
00215   getTransformationFromTwoUnitVectorsAndOrigin(up_vector, viewing_direction, viewpoint, viewer_pose);
00216   viewer_pose = viewer_pose.inverse();
00217   return viewer_pose;
00218 }
00219 
00220 void ObjectModel::extractNARFsForCompleteSurface(unsigned int descriptor_size, float size_in_world, bool rotation_invariant, vector<vector<Narf*>*>& features) const
00221 {
00222   freeFeatureListMemory(features);
00223   
00224   std::vector<float> rotations, strengths;
00225   for (unsigned int view_index=0; view_index<views_.size(); ++view_index)
00226   {
00227     const RangeImage& view = views_[view_index];
00228     //cout << PVARN(view);
00229     features.push_back(new vector<Narf*>);
00230     vector<Narf*>& features_of_current_view = *features.back();
00231     
00232     for (unsigned int y=0; y<view.height; ++y)
00233     {
00234       for (unsigned int x=0; x<view.width; ++x)
00235       {
00236         Narf::extractFromRangeImageAndAddToList(view, x, y, descriptor_size, size_in_world, rotation_invariant, features_of_current_view);
00237       }
00238     }
00239     //cout << PVARN(features_of_current_view.size());
00240   }
00241 }
00242 
00243 void ObjectModel::extractInterestPoints(int view_ix, float support_size, NarfKeypoint& interest_point_detector, 
00244                                         PointCloud<InterestPoint>& interest_points) const
00245 {
00246   float original_support_size = interest_point_detector.getParameters().support_size;
00247   interest_point_detector.getParameters().support_size = support_size;
00248   interest_point_detector.setRangeImage(&views_[view_ix]);
00249   interest_points = interest_point_detector.getInterestPoints();
00250   //cout << "Resetting interest point detector.\n";
00251   interest_point_detector.setRangeImage(NULL); // Clear structure to prevent memory problems when view is not valid anymore
00252   interest_point_detector.getParameters().support_size = original_support_size;
00253 }
00254 
00255 void ObjectModel::extractNARFsForInterestPoints(unsigned int descriptor_size, float size_in_world,
00256                                                bool rotation_invariant, NarfKeypoint& interest_point_detector,
00257                                                vector<vector<Narf*>*>& features) const
00258 {
00259   freeFeatureListMemory(features);
00260   
00261   std::vector<float> rotations, strengths;
00262   for (unsigned int view_index=0; view_index<views_.size(); ++view_index)
00263   {
00264     const RangeImage& view = views_[view_index];
00265     
00266     PointCloud<InterestPoint> interest_points;
00267     extractInterestPoints(view_index, size_in_world, interest_point_detector, interest_points);
00268     
00269     //cout << PVARN(view);
00270     features.push_back(new vector<Narf*>);
00271     vector<Narf*>& features_of_current_view = *features.back();
00272     
00273     Narf::extractForInterestPoints(view, interest_points, descriptor_size, size_in_world, rotation_invariant, features_of_current_view);
00274     //cout << PVARN(features_of_current_view.size());
00275   }
00276 }
00277 
00278 
00279 void ObjectModel::getTransformedPointCloud(const Affine3f& transformation, ObjectModel::PointCloudType& output) const
00280 {
00281   pcl::transformPointCloud(point_cloud_, output, transformation);
00282 }
00283 
00284 void ObjectModel::updateValidationPoints(unsigned int no_of_surface_points, unsigned int no_of_border_points, float sample_resolution,
00285                                          NarfKeypoint* interest_point_detector, float support_size)
00286 {
00287   //cout << __PRETTY_FUNCTION__ << " called.\n";
00288   //MEASURE_FUNCTION_TIME;
00289   if (is_single_view_model_)
00290   {
00291     views_for_validation_points_ = views_;
00292   }
00293   else
00294   {
00295     views_for_validation_points_.clear();
00296     sampleViews3D(sample_resolution, deg2rad(0.4f), -1.0f, &views_for_validation_points_);
00297   }
00298   
00299   validation_points_.clear();
00300   validation_points_.resize(views_for_validation_points_.size());
00301   
00302   for (unsigned int view_idx=0; view_idx<views_for_validation_points_.size(); ++view_idx)
00303   {
00304     //std::cout << view_idx<<" ";
00305     const RangeImage& view = views_for_validation_points_[view_idx];
00306     ValidationPoints& validation_points_for_view = validation_points_[view_idx];
00307     
00308     int width=view.width, height=view.height;
00309     vector<Eigen::Vector3f> surface_points, border_points;
00310     for (int x=0; x<width; ++x)
00311     {
00312       for (int y=0; y<height; ++y)
00313       {
00314         int index = y*width+x;
00315         const PointWithRange& point = view.getPoint(index);
00316         if (!pcl_isfinite(point.range))
00317           continue;
00318         bool is_border_point=false;
00319         for (int y2=y-1; y2<=y+1; ++y2)
00320         {
00321           for (int x2=(y2==y ? x-1 : x); x2<=(y2==y ? x+1 : x); x2+=2)
00322           {
00323             if (!view.isInImage(x2,y2))
00324               continue;
00325             const PointWithRange& point2 = view.getPoint(x2, y2);
00326             if (std::isinf(point2.range) && point2.range>0.0f)
00327             {
00328               is_border_point = true;
00329               break;
00330             }
00331           }
00332         }
00333         Eigen::Vector3f point_eigen;
00334         view.getPoint(x, y, point_eigen);
00335         if (is_border_point)
00336           border_points.push_back(point_eigen);
00337         else if (interest_point_detector == NULL)
00338           surface_points.push_back(point_eigen);
00339       }
00340     }
00341     //std::cout << view_idx<<" ";
00342     
00343     if (interest_point_detector != NULL)
00344     {
00345       PointCloud<InterestPoint> interest_points;
00346       float original_distance_for_additional_points = interest_point_detector->getParameters().distance_for_additional_points;
00347       interest_point_detector->getParameters().distance_for_additional_points = 0.0f;
00348       extractInterestPoints(view_idx, support_size, *interest_point_detector, interest_points);
00349       for (unsigned int i=0; i<interest_points.points.size(); ++ i)
00350         surface_points.push_back(interest_points.points[i].getVector3fMap());
00351       interest_point_detector->getParameters().distance_for_additional_points = original_distance_for_additional_points;
00352     }
00353     
00354     //cout << PVARC(surface_points.size())<<PVARN(border_points.size());
00355     getUniformlyDistributedPoints(surface_points, no_of_surface_points, validation_points_for_view.surface);
00356     getUniformlyDistributedPoints(border_points, no_of_border_points, validation_points_for_view.border);
00357   }
00358 }
00359 
00360 
00361 void ObjectModel::getUniformlyDistributedPoints(const vector<Eigen::Vector3f>& points, int no_of_points, vector<Eigen::Vector3f>& result)
00362 {
00363   if (points.empty() || no_of_points==0)
00364     return;
00365 
00366   no_of_points = std::min(no_of_points, (int)points.size());
00367   
00368   std::multimap<float, Vector3f> distance_sorted_points1, distance_sorted_points2;
00369   std::multimap<float, Vector3f>* current_points=&distance_sorted_points1, * new_points=&distance_sorted_points2;
00370   result.push_back(points[0]);
00371   
00372   for (unsigned int i=1; i<points.size(); ++i)
00373     current_points->insert(std::make_pair(INFINITY, points[i]));
00374   
00375   while ((int)result.size() < no_of_points)
00376   {
00377     new_points->clear();
00378     for (std::multimap<float, Vector3f>::const_iterator it=current_points->begin(); it!=current_points->end(); ++it)
00379     {
00380       const Vector3f& point = it->second;
00381       float distance_to_last_point = (result.back()-point).squaredNorm();
00382       float distance = min(it->first, distance_to_last_point);
00383       if (distance > 0.0f)
00384         new_points->insert(std::make_pair(distance, point));
00385     }
00386     std::swap(current_points, new_points);
00387     //cout << PVARC(result.size())<<PVARN(current_points->size());
00388     result.push_back(current_points->rbegin()->second);
00389   }
00390 }
00391 
00392 Eigen::Affine3f ObjectModel::doFastICP(const Eigen::Affine3f& initial_guess, const RangeImage& range_image,
00393                                         int search_radius, int no_of_surface_points_to_use,
00394                                         int no_of_border_points_to_use, int num_iterations,
00395                                         float max_distance_start, float max_distance_end) const
00396 {
00397   if (max_distance_start <= 0.0f)
00398     max_distance_start = 0.05f*radius_;
00399   if (max_distance_end <= 0.0f)
00400     max_distance_end = 0.5*max_distance_start;
00401   Affine3f model_viewer_pose = initial_guess.inverse()*range_image.getTransformationToWorldSystem();
00402   int view_idx = getClosestValidationPointViewIdx(model_viewer_pose);
00403   const ValidationPoints& validation_points_for_view = validation_points_[view_idx];
00404   
00405   //std::vector<Eigen::Vector3f> points;
00406   //points.resize(no_of_surface_points_to_use+no_of_border_points_to_use);
00407   //for (int i=0; i<min(no_of_surface_points_to_use,(int)validation_points_for_view.surface.size()); ++i)
00408     //points.push_back(validation_points_for_view.surface[i]);
00409   //for (int i=0; i<min(no_of_border_points_to_use,(int)validation_points_for_view.border.size()); ++i)
00410     //points.push_back(validation_points_for_view.border[i]);
00411   
00412   //return range_image.doIcp(points, initial_guess, search_radius, max_distance_start, max_distance_end, num_iterations);
00413 
00414 
00415   float max_distance = max_distance_start, 
00416         max_distance_reduction = (max_distance_start-max_distance_end)/float(num_iterations);
00417   Affine3f ret = initial_guess;
00418   no_of_surface_points_to_use = min(no_of_surface_points_to_use, (int)validation_points_for_view.surface.size());
00419   no_of_border_points_to_use  = min(no_of_border_points_to_use, (int)validation_points_for_view.border.size());
00420   
00421   
00422   TransformationFromCorrespondences transformation_from_correspondeces;
00423   for (int iteration=1; iteration<=num_iterations; ++iteration)
00424   {
00425     float max_distance_squared = max_distance*max_distance;
00426     transformation_from_correspondeces.reset();
00427     for (int point_idx=0; point_idx<no_of_surface_points_to_use+no_of_border_points_to_use; ++point_idx)
00428     {
00429       const Vector3f* point;
00430       if (point_idx<no_of_surface_points_to_use)
00431          point = &validation_points_for_view.surface[point_idx];
00432       else
00433          point = &validation_points_for_view.border[point_idx-no_of_surface_points_to_use];
00434       Vector3f transformed_point = ret * *point;
00435       int x,y;
00436       range_image.getImagePoint(transformed_point, x, y);
00437       float closest_distance = max_distance_squared;
00438       Vector3f closest_point(0,0,0);
00439       bool found_neighbor = false;
00440       for (int y2=y-search_radius; y2<=y+search_radius; ++y2)
00441       {
00442         for (int x2=x-search_radius; x2<=x+search_radius; ++x2)
00443         {
00444           const PointWithRange& neighbor = range_image.getPoint(x2, y2);
00445           if (!pcl_isfinite(neighbor.range))
00446             continue;
00447           float distance = (transformed_point-neighbor.getVector3fMap()).squaredNorm();
00448           if (distance < closest_distance)
00449           {
00450             closest_distance = distance;
00451             closest_point = neighbor.getVector3fMap();
00452             found_neighbor = true;
00453           }
00454         }
00455       }
00456       if (found_neighbor)
00457       {
00458         //cout << PVARN(closest_distance);
00459         transformation_from_correspondeces.add(*point, closest_point);
00460       }
00461     }
00462     //cout << PVARN(transformation_from_correspondeces.getNoOfSamples());
00463     //cout << PVARN(iteration);
00464     if (transformation_from_correspondeces.getNoOfSamples() < 3)
00465       return ret;
00466     // TODO: check
00467     ret = transformation_from_correspondeces.getTransformation();
00468     //cout << ret.matrix()<<"\n";
00469     
00470     max_distance -= max_distance_reduction;
00471   }
00472   //cout << PVARN(initial_guess.matrix())<<PVARN(ret.matrix());
00473   
00474   return ret;
00475 }
00476 
00477 Eigen::Affine3f ObjectModel::doSlowICP(const Eigen::Affine3f& initial_guess, const RangeImage& range_image,
00478                                        int search_radius, int num_iterations, float max_distance_start,
00479                                        float max_distance_end) const
00480 {
00481   if (max_distance_start <= 0.0f)
00482     max_distance_start = 0.05f*radius_;
00483   if (max_distance_end <= 0.0f)
00484     max_distance_end = 0.5*max_distance_start;
00485   Affine3f viewer_pose = initial_guess.inverse()*range_image.getTransformationToWorldSystem();
00486   float angular_resolution = range_image.getAngularResolution();
00487   //float angular_resolution = 2.0f * range_image.getAngularResolution();
00488   RangeImage simulated_view;
00489   float noise_level = 0.1*radius_;
00490   simulated_view.createFromPointCloud(point_cloud_, angular_resolution, deg2rad(360.0f), deg2rad(180.0f), viewer_pose,
00491                                       RangeImage::CAMERA_FRAME, noise_level);
00492   RangeImage::VectorOfEigenVector3f points;
00493   for (unsigned int i=0; i<simulated_view.points.size(); ++i)
00494   //for (unsigned int i=0; i<point_cloud_.points.size(); ++i)
00495     if (simulated_view.isValid(i))
00496       points.push_back(simulated_view.getPoint(i).getVector3fMap());
00497   
00498   return range_image.doIcp(points, initial_guess, search_radius, max_distance_start, max_distance_end, num_iterations);
00499 }
00500 
00501 void ObjectModel::addNoise(float max_noise)
00502 {
00503   double normalization_factor = double(2.0*max_noise) / double(RAND_MAX),
00504          offset = -max_noise;
00505   clear(true);  // Clear all but point_cloud_;
00506   
00507   for (unsigned int point_idx=0; point_idx<point_cloud_.points.size(); ++point_idx)
00508   {
00509     PointType& point = point_cloud_.points[point_idx];
00510     point.x += normalization_factor*double(rand()) + offset;
00511     point.y += normalization_factor*double(rand()) + offset;
00512     point.z += normalization_factor*double(rand()) + offset;
00513   }
00514 }
00515 
00516 float ObjectModel::getMaximumPlaneSize (float initial_max_plane_error) const
00517 {
00518   float max_plane_size = 0.0f;
00519   std::vector<RangeImage::ExtractedPlane> planes;
00520   for (int view_idx=0; view_idx<int(views_.size()); ++view_idx)
00521   {
00522     const RangeImage& view = views_[view_idx];
00523     planes.clear ();
00524     view.extractPlanes (initial_max_plane_error, planes);
00525     for (int plane_idx=0; plane_idx<int(planes.size()); ++plane_idx)
00526       max_plane_size = std::max(max_plane_size, planes[plane_idx].maximum_extensions[2]);
00527   }
00528   return max_plane_size;
00529 }
00530 
00531 } // namespace end
00532 
 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