hough_3d.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  *  
00007  *  All rights reserved.
00008  *
00009  *  Redistribution and use in source and binary forms, with or without
00010  *  modification, are permitted provided that the following conditions
00011  *  are met:
00012  *
00013  *   * Redistributions of source code must retain the above copyright
00014  *     notice, this list of conditions and the following disclaimer.
00015  *   * Redistributions in binary form must reproduce the above
00016  *     copyright notice, this list of conditions and the following
00017  *     disclaimer in the documentation and/or other materials provided
00018  *     with the distribution.
00019  *   * Neither the name of Willow Garage, Inc. nor the names of its
00020  *     contributors may be used to endorse or promote products derived
00021  *     from this software without specific prior written permission.
00022  *
00023  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00024  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00025  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00026  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00027  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00028  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00029  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00030  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00031  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00032  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00033  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00034  *  POSSIBILITY OF SUCH DAMAGE.
00035  *
00036  * $Id$
00037  *
00038  */
00039 
00040 #include "pcl/point_types.h"
00041 #include "pcl/impl/instantiate.hpp"
00042 #include "pcl/recognition/cg/hough_3d.h"
00043 #include "pcl/recognition/impl/cg/hough_3d.hpp"
00044 
00045 PCL_INSTANTIATE_PRODUCT(Hough3DGrouping, ((pcl::PointXYZ)(pcl::PointXYZI)(pcl::PointXYZRGB)(pcl::PointXYZRGBA))
00046                                          ((pcl::PointXYZ)(pcl::PointXYZI)(pcl::PointXYZRGB)(pcl::PointXYZRGBA))
00047                                          ((pcl::ReferenceFrame))((pcl::ReferenceFrame)))
00048 
00049 
00050 pcl::recognition::HoughSpace3D::HoughSpace3D (const Eigen::Vector3d &min_coord, const Eigen::Vector3d &bin_size, const Eigen::Vector3d &max_coord)
00051 {
00052   min_coord_ = min_coord;
00053   bin_size_ = bin_size;
00054 
00055   for (int i = 0; i < 3; ++i)
00056   {
00057     bin_count_[i] = static_cast<int> (ceil ((max_coord[i] - min_coord_[i]) / bin_size_[i]));
00058   }
00059 
00060   partial_bin_products_[0] = 1;
00061   for (int i=1; i<=3; ++i)
00062     partial_bin_products_[i] = bin_count_[i-1]*partial_bin_products_[i-1];
00063 
00064   total_bins_count_ = partial_bin_products_[3];
00065 
00066   hough_space_.clear ();
00067   hough_space_.resize (total_bins_count_, 0.0);
00068 }
00069 
00071 void
00072 pcl::recognition::HoughSpace3D::reset ()
00073 {
00074   hough_space_.clear ();
00075   hough_space_.resize (total_bins_count_, 0.0);
00076 
00077   voter_ids_.clear ();
00078 }
00079 
00081 int
00082 pcl::recognition::HoughSpace3D::vote (const Eigen::Vector3d &single_vote_coord, double weight, int voter_id)
00083 {
00084   int index = 0;
00085 
00086   for (int i=0; i<3; ++i)
00087   {
00088     int currentBin = static_cast<int> (floor ((single_vote_coord[i] - min_coord_[i])/bin_size_[i]));
00089     if (currentBin < 0 || currentBin >= bin_count_[i])
00090     {
00091       //PCL_ERROR("Current Vote goes out of bounds in the Hough Table!\nDimension: %d, Value inserted: %f, Min value: %f, Max value: %f\n", i, 
00092       //  single_vote_coord[i], min_coord_[i], min_coord_[i] + bin_size_[i]*bin_count_[i]);
00093       return -1;
00094     }
00095 
00096     index += partial_bin_products_[i] * currentBin;
00097   }
00098 
00099   hough_space_[index] += weight;
00100   voter_ids_[index].push_back (voter_id);
00101 
00102   return (index);
00103 }
00104 
00106 int
00107 pcl::recognition::HoughSpace3D::voteInt (const Eigen::Vector3d &single_vote_coord, double weight, int voter_id)
00108 {
00109   int central_bin_index = 0;
00110 
00111   const int n_neigh = 27; // total number of neighbours = 3^nDim = 27
00112 
00113   Eigen::Vector3i central_bin_coord;
00114   Eigen::Vector3f bin_centroid;
00115   Eigen::Vector3f central_bin_weight;
00116   Eigen::Vector3i interp_bin;
00117   std::vector<float> interp_weight (n_neigh);
00118 
00119   for (int n = 0; n < n_neigh; ++n)
00120     interp_weight[n] = 1.0;
00121 
00122   for (int d = 0; d < 3; ++d)
00123   {
00124     // Compute coordinates of central bin
00125     central_bin_coord[d] = static_cast<int> (floor ((single_vote_coord[d] - min_coord_[d]) / bin_size_[d]));
00126     if (central_bin_coord[d] < 0 || central_bin_coord[d] >= bin_count_[d])
00127     {
00128       //PCL_ERROR("Current Vote goes out of bounds in the Hough Table!\nDimension: %d, Value inserted: %f, Min value: %f, Max value: %f\n", d,
00129       //  single_vote_coord[d], min_coord_[d], min_coord_[d] + bin_size_[d]*bin_count_[d]);
00130       return -1;
00131     }
00132 
00133     central_bin_index += partial_bin_products_[d] * central_bin_coord[d];
00134 
00135     // Compute coordinates of the centroid of the bin
00136     bin_centroid[d] = static_cast<float> ((2 * static_cast<double> (central_bin_coord[d]) * bin_size_[d] + bin_size_[d]) / 2.0 );
00137 
00138     // Compute interpolated weight for each coordinate of the central bin
00139     central_bin_weight[d] = static_cast<float> (1 - (fabs (single_vote_coord[d] - min_coord_[d] - bin_centroid[d]) / bin_size_[d] ) );
00140 
00141     // Compute the neighbor bins where the weight has to be interpolated
00142     if ((single_vote_coord[d] - min_coord_[d]) < bin_centroid[d])
00143     {
00144       interp_bin[d] = central_bin_coord[d] - 1;
00145     }
00146     else if ((single_vote_coord[d] - min_coord_[d]) > bin_centroid[d])
00147     {
00148       interp_bin[d] = central_bin_coord[d] + 1;
00149     }
00150     else
00151     {
00152       interp_bin[d] = central_bin_coord[d]; // the vote is precisely in the middle, so along this dimension the vote is given all to the central bin
00153     }
00154   }
00155 
00156   // For each neighbor of the central point
00157   //int counterRealVotes = 0;
00158   for (int n = 0; n < n_neigh; ++n)
00159   {
00160     int final_bin_index = 0;
00161     int exp = 1;
00162     int curr_neigh_index = 0;
00163     bool invalid = false;
00164 
00165     for (int d = 0; d < 3; ++d)
00166     {
00167       curr_neigh_index = central_bin_coord[d] + ( n % (exp*3) ) / exp - 1; // (n % 3^(d+1) / 3^d) - 1
00168       if (curr_neigh_index >= 0 && curr_neigh_index <= bin_count_[d]-1)
00169       {
00170         // Each coordinate of the neighbor has to be equal either to one of the central bin or to one of the interpolated bins
00171         if(curr_neigh_index == interp_bin[d])
00172         {
00173           interp_weight[n] *= 1-central_bin_weight[d];
00174         }
00175         else if(curr_neigh_index == central_bin_coord[d])
00176         {
00177           interp_weight[n] *= central_bin_weight[d];
00178         }
00179         else
00180         {
00181           invalid = true;
00182           break;
00183         }
00184 
00185         final_bin_index += curr_neigh_index * partial_bin_products_[d];
00186       }
00187       else
00188       {
00189         invalid = true;
00190         break;
00191       }
00192       exp *= 3;
00193     }
00194 
00195     if (!invalid)
00196     {
00197       hough_space_[final_bin_index] += weight * interp_weight[n];
00198       voter_ids_[final_bin_index].push_back (voter_id);
00199     }
00200   }
00201 
00202   return (central_bin_index);
00203 }
00204 
00206 double
00207 pcl::recognition::HoughSpace3D::findMaxima (double min_threshold, std::vector<double> &maxima_values, std::vector<std::vector<int> > &maxima_voter_ids)
00208 {
00209   // If min_threshold between -1 and 0 use it as a percentage of maximum vote
00210   if (min_threshold < 0)
00211   {
00212     double hough_maximum = std::numeric_limits<double>::min ();
00213     for (int i = 0; i < total_bins_count_; ++i)
00214     {
00215       if (hough_space_[i] > hough_maximum)
00216       {
00217         hough_maximum = hough_space_[i];
00218       }
00219     }
00220 
00221     min_threshold = min_threshold >= -1 ? -min_threshold * hough_maximum : hough_maximum;
00222   }
00223 
00224   maxima_voter_ids.clear ();
00225   maxima_values.clear ();
00226 
00227   double indexes[3];
00228 
00229   //int zeros = 0;
00230 
00231   for (int i=0; i < total_bins_count_; ++i)
00232   {
00233     //if (hough_space_[i] == 0)
00234     //{
00235     //  ++zeros;
00236     //}
00237     if (hough_space_[i] < min_threshold)
00238       continue;
00239 
00240     // Check with neighbors
00241     bool is_maximum = true;
00242     int moduled_index = i;
00243 
00244     for (int k = 2; k >= 0; --k){
00245 
00246       moduled_index = moduled_index % partial_bin_products_[k+1];
00247       indexes[k] = moduled_index / partial_bin_products_[k];
00248 
00249       if (indexes[k] > 0 && hough_space_[i] < hough_space_[i-partial_bin_products_[k]])
00250       {
00251         is_maximum = false;
00252         break;
00253       }
00254       if (indexes[k] < bin_count_[k]-1 && hough_space_[i] < hough_space_[i+partial_bin_products_[k]])
00255       {
00256         is_maximum = false;
00257         break;
00258       }
00259     }
00260 
00261     if (is_maximum)
00262     {
00263       maxima_values.push_back (hough_space_[i]);
00264       maxima_voter_ids.push_back ( voter_ids_[i] );
00265     }
00266   }
00267 
00268   return (min_threshold);
00269 }


pcl
Author(s): Open Perception
autogenerated on Wed Aug 26 2015 15:24:43