|
Point Cloud Library (PCL)
1.5.1
|
00001 /* 00002 * Software License Agreement (BSD License) 00003 * 00004 * Point Cloud Library (PCL) - www.pointclouds.org 00005 * Copyright (c) 2010-2011, 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: rift.hpp 4702 2012-02-23 09:39:33Z gedikli $ 00037 * 00038 */ 00039 00040 #ifndef PCL_FEATURES_IMPL_RIFT_H_ 00041 #define PCL_FEATURES_IMPL_RIFT_H_ 00042 00043 #include "pcl/features/rift.h" 00044 00046 template <typename PointInT, typename GradientT, typename PointOutT> void 00047 pcl::RIFTEstimation<PointInT, GradientT, PointOutT>::computeRIFT ( 00048 const PointCloudIn &cloud, const PointCloudGradient &gradient, 00049 int p_idx, float radius, const std::vector<int> &indices, 00050 const std::vector<float> &sqr_distances, Eigen::MatrixXf &rift_descriptor) 00051 { 00052 if (indices.empty ()) 00053 { 00054 PCL_ERROR ("[pcl::RIFTEstimation] Null indices points passed!\n"); 00055 return; 00056 } 00057 00058 // Determine the number of bins to use based on the size of rift_descriptor 00059 int nr_distance_bins = rift_descriptor.rows (); 00060 int nr_gradient_bins = rift_descriptor.cols (); 00061 00062 // Get the center point 00063 pcl::Vector3fMapConst p0 = cloud.points[p_idx].getVector3fMap (); 00064 00065 // Compute the RIFT descriptor 00066 rift_descriptor.setZero (); 00067 for (size_t idx = 0; idx < indices.size (); ++idx) 00068 { 00069 // Compute the gradient magnitude and orientation (relative to the center point) 00070 pcl::Vector3fMapConst point = cloud.points[indices[idx]].getVector3fMap (); 00071 Eigen::Map<const Eigen::Vector3f> gradient_vector (& (gradient.points[indices[idx]].gradient[0])); 00072 00073 float gradient_magnitude = gradient_vector.norm (); 00074 float gradient_angle_from_center = acos (gradient_vector.dot ((point - p0).normalized ()) / gradient_magnitude); 00075 if (!pcl_isfinite (gradient_angle_from_center)) 00076 { 00077 gradient_angle_from_center = 0.0; 00078 } 00079 00080 // Normalize distance and angle values to: 0.0 <= d,g < nr_distances_bins,nr_gradient_bins 00081 const float eps = std::numeric_limits<float>::epsilon (); 00082 float d = nr_distance_bins * sqrt (sqr_distances[idx]) / (radius + eps); 00083 float g = nr_gradient_bins * gradient_angle_from_center / (M_PI + eps); 00084 00085 // Compute the bin indices that need to be updated 00086 int d_idx_min = (std::max)((int) ceil (d - 1), 0); 00087 int d_idx_max = (std::min)((int) floor (d + 1), nr_distance_bins - 1); 00088 int g_idx_min = (int) ceil (g - 1); 00089 int g_idx_max = (int) floor (g + 1); 00090 00091 // Update the appropriate bins of the histogram 00092 for (int g_idx = g_idx_min; g_idx <= g_idx_max; ++g_idx) 00093 { 00094 // Because gradient orientation is cyclical, out-of-bounds values must wrap around 00095 int g_idx_wrapped = ((g_idx + nr_gradient_bins) % nr_gradient_bins); 00096 00097 for (int d_idx = d_idx_min; d_idx <= d_idx_max; ++d_idx) 00098 { 00099 // To avoid boundary effects, use linear interpolation when updating each bin 00100 float w = (1 - fabs (d - d_idx)) * (1 - fabs (g - g_idx)); 00101 00102 rift_descriptor (d_idx, g_idx_wrapped) += w * gradient_magnitude; 00103 } 00104 } 00105 } 00106 00107 // Normalize the RIFT descriptor to unit magnitude 00108 rift_descriptor.normalize (); 00109 } 00110 00111 00113 template <typename PointInT, typename GradientT, typename PointOutT> void 00114 pcl::RIFTEstimation<PointInT, GradientT, PointOutT>::computeFeature (PointCloudOut &output) 00115 { 00116 // Make sure a search radius is set 00117 if (search_radius_ == 0.0) 00118 { 00119 PCL_ERROR ("[pcl::%s::computeFeature] The search radius must be set before computing the feature!\n", 00120 getClassName ().c_str ()); 00121 output.width = output.height = 0; 00122 output.points.clear (); 00123 return; 00124 } 00125 00126 // Make sure the RIFT descriptor has valid dimensions 00127 if (nr_gradient_bins_ <= 0) 00128 { 00129 PCL_ERROR ("[pcl::%s::computeFeature] The number of gradient bins must be greater than zero!\n", 00130 getClassName ().c_str ()); 00131 output.width = output.height = 0; 00132 output.points.clear (); 00133 return; 00134 } 00135 if (nr_distance_bins_ <= 0) 00136 { 00137 PCL_ERROR ("[pcl::%s::computeFeature] The number of distance bins must be greater than zero!\n", 00138 getClassName ().c_str ()); 00139 output.width = output.height = 0; 00140 output.points.clear (); 00141 return; 00142 } 00143 00144 // Check for valid input gradient 00145 if (!gradient_) 00146 { 00147 PCL_ERROR ("[pcl::%s::computeFeature] No input gradient was given!\n", getClassName ().c_str ()); 00148 output.width = output.height = 0; 00149 output.points.clear (); 00150 return; 00151 } 00152 if (gradient_->points.size () != surface_->points.size ()) 00153 { 00154 PCL_ERROR ("[pcl::%s::computeFeature] ", getClassName ().c_str ()); 00155 PCL_ERROR ("The number of points in the input dataset differs from the number of points in the gradient!\n"); 00156 output.width = output.height = 0; 00157 output.points.clear (); 00158 return; 00159 } 00160 00161 Eigen::MatrixXf rift_descriptor (nr_distance_bins_, nr_gradient_bins_); 00162 std::vector<int> nn_indices; 00163 std::vector<float> nn_dist_sqr; 00164 00165 // Iterating over the entire index vector 00166 for (size_t idx = 0; idx < indices_->size (); ++idx) 00167 { 00168 // Find neighbors within the search radius 00169 tree_->radiusSearch ((*indices_)[idx], search_radius_, nn_indices, nn_dist_sqr); 00170 00171 // Compute the RIFT descriptor 00172 computeRIFT (*surface_, *gradient_, (*indices_)[idx], search_radius_, nn_indices, nn_dist_sqr, rift_descriptor); 00173 00174 // Copy into the resultant cloud 00175 int bin = 0; 00176 for (int g_bin = 0; g_bin < rift_descriptor.cols (); ++g_bin) 00177 for (int d_bin = 0; d_bin < rift_descriptor.rows (); ++d_bin) 00178 output.points[idx].histogram[bin++] = rift_descriptor (d_bin, g_bin); 00179 } 00180 } 00181 00183 template <typename PointInT, typename GradientT> void 00184 pcl::RIFTEstimation<PointInT, GradientT, Eigen::MatrixXf>::computeFeatureEigen (pcl::PointCloud<Eigen::MatrixXf> &output) 00185 { 00186 // These should be moved into initCompute () 00187 { 00188 // Make sure a search radius is set 00189 if (search_radius_ == 0.0) 00190 { 00191 PCL_ERROR ("[pcl::%s::computeFeature] The search radius must be set before computing the feature!\n", 00192 getClassName ().c_str ()); 00193 output.width = output.height = 0; 00194 output.points.resize (0, 0); 00195 return; 00196 } 00197 00198 // Make sure the RIFT descriptor has valid dimensions 00199 if (nr_gradient_bins_ <= 0) 00200 { 00201 PCL_ERROR ("[pcl::%s::computeFeature] The number of gradient bins must be greater than zero!\n", 00202 getClassName ().c_str ()); 00203 output.width = output.height = 0; 00204 output.points.resize (0, 0); 00205 return; 00206 } 00207 if (nr_distance_bins_ <= 0) 00208 { 00209 PCL_ERROR ("[pcl::%s::computeFeature] The number of distance bins must be greater than zero!\n", 00210 getClassName ().c_str ()); 00211 output.width = output.height = 0; 00212 output.points.resize (0, 0); 00213 return; 00214 } 00215 00216 // Check for valid input gradient 00217 if (!gradient_) 00218 { 00219 PCL_ERROR ("[pcl::%s::computeFeature] No input gradient was given!\n", getClassName ().c_str ()); 00220 output.width = output.height = 0; 00221 output.points.resize (0, 0); 00222 return; 00223 } 00224 if (gradient_->points.size () != surface_->points.size ()) 00225 { 00226 PCL_ERROR ("[pcl::%s::computeFeature] ", getClassName ().c_str ()); 00227 PCL_ERROR ("The number of points in the input dataset differs from the number of points in the gradient!\n"); 00228 output.width = output.height = 0; 00229 output.points.resize (0, 0); 00230 return; 00231 } 00232 } 00233 00234 output.points.resize (indices_->size (), nr_gradient_bins_ * nr_distance_bins_); 00235 Eigen::MatrixXf rift_descriptor (nr_distance_bins_, nr_gradient_bins_); 00236 std::vector<int> nn_indices; 00237 std::vector<float> nn_dist_sqr; 00238 00239 output.is_dense = true; 00240 // Iterating over the entire index vector 00241 for (size_t idx = 0; idx < indices_->size (); ++idx) 00242 { 00243 // Find neighbors within the search radius 00244 if (tree_->radiusSearch ((*indices_)[idx], search_radius_, nn_indices, nn_dist_sqr) == 0) 00245 { 00246 output.points.row (idx).setConstant (std::numeric_limits<float>::quiet_NaN ()); 00247 output.is_dense = false; 00248 continue; 00249 } 00250 00251 // Compute the RIFT descriptor 00252 this->computeRIFT (*surface_, *gradient_, (*indices_)[idx], search_radius_, nn_indices, nn_dist_sqr, 00253 rift_descriptor); 00254 00255 // Copy into the resultant cloud 00256 int bin = 0; 00257 for (int g_bin = 0; g_bin < rift_descriptor.cols (); ++g_bin) 00258 for (int d_bin = 0; d_bin < rift_descriptor.rows (); ++d_bin) 00259 output.points (idx, bin++) = rift_descriptor (d_bin, g_bin); 00260 00261 } 00262 } 00263 00264 #define PCL_INSTANTIATE_RIFTEstimation(T,NT,OutT) template class PCL_EXPORTS pcl::RIFTEstimation<T,NT,OutT>; 00265 00266 #endif // PCL_FEATURES_IMPL_RIFT_H_ 00267
1.8.0