|
Point Cloud Library (PCL)
1.4.0
|
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: intensity_spin.hpp 3755 2011-12-31 23:45:30Z rusu $ 00037 * 00038 */ 00039 00040 #ifndef PCL_FEATURES_IMPL_INTENSITY_SPIN_H_ 00041 #define PCL_FEATURES_IMPL_INTENSITY_SPIN_H_ 00042 00043 #include "pcl/features/intensity_spin.h" 00044 00046 template <typename PointInT, typename PointOutT> void 00047 pcl::IntensitySpinEstimation<PointInT, PointOutT>::computeIntensitySpinImage ( 00048 const PointCloudIn &cloud, float radius, float sigma, 00049 int k, 00050 const std::vector<int> &indices, 00051 const std::vector<float> &squared_distances, Eigen::MatrixXf &intensity_spin_image) 00052 { 00053 // Determine the number of bins to use based on the size of intensity_spin_image 00054 int nr_distance_bins = intensity_spin_image.cols (); 00055 int nr_intensity_bins = intensity_spin_image.rows (); 00056 00057 // Find the min and max intensity values in the given neighborhood 00058 float min_intensity = std::numeric_limits<float>::max (); 00059 float max_intensity = std::numeric_limits<float>::min (); 00060 for (int idx = 0; idx < k; ++idx) 00061 { 00062 min_intensity = (std::min) (min_intensity, cloud.points[indices[idx]].intensity); 00063 max_intensity = (std::max) (max_intensity, cloud.points[indices[idx]].intensity); 00064 } 00065 00066 // Compute the intensity spin image 00067 intensity_spin_image.setZero (); 00068 for (int idx = 0; idx < k; ++idx) 00069 { 00070 // Normalize distance and intensity values to: 0.0 <= d,i < nr_distance_bins,nr_intensity_bins 00071 const float eps = std::numeric_limits<float>::epsilon (); 00072 float d = nr_distance_bins * sqrt (squared_distances[idx]) / (radius + eps); 00073 float i = nr_intensity_bins * 00074 (cloud.points[indices[idx]].intensity - min_intensity) / (max_intensity - min_intensity + eps); 00075 00076 if (sigma == 0) 00077 { 00078 // If sigma is zero, update the histogram with no smoothing kernel 00079 int d_idx = (int) d; 00080 int i_idx = (int) i; 00081 intensity_spin_image (i_idx, d_idx) += 1; 00082 } 00083 else 00084 { 00085 // Compute the bin indices that need to be updated (+/- 3 standard deviations) 00086 int d_idx_min = (std::max)((int) floor (d - 3*sigma), 0); 00087 int d_idx_max = (std::min)((int) ceil (d + 3*sigma), nr_distance_bins - 1); 00088 int i_idx_min = (std::max)((int) floor (i - 3*sigma), 0); 00089 int i_idx_max = (std::min)((int) ceil (i + 3*sigma), nr_intensity_bins - 1); 00090 00091 // Update the appropriate bins of the histogram 00092 for (int i_idx = i_idx_min; i_idx <= i_idx_max; ++i_idx) 00093 { 00094 for (int d_idx = d_idx_min; d_idx <= d_idx_max; ++d_idx) 00095 { 00096 // Compute a "soft" update weight based on the distance between the point and the bin 00097 float w = exp (-pow (d - d_idx, 2) / (2.0*sigma_*sigma_) 00098 -pow (i - i_idx, 2) / (2.0*sigma_*sigma_)); 00099 intensity_spin_image (i_idx, d_idx) += w; 00100 } 00101 } 00102 } 00103 } 00104 } 00105 00107 template <typename PointInT, typename PointOutT> void 00108 pcl::IntensitySpinEstimation<PointInT, PointOutT>::computeFeature (PointCloudOut &output) 00109 { 00110 // Make sure a search radius is set 00111 if (search_radius_ == 0.0) 00112 { 00113 PCL_ERROR ("[pcl::%s::computeFeature] The search radius must be set before computing the feature!\n", 00114 getClassName ().c_str ()); 00115 output.width = output.height = 0; 00116 output.points.clear (); 00117 return; 00118 } 00119 00120 // Make sure the spin image has valid dimensions 00121 if (nr_intensity_bins_ <= 0) 00122 { 00123 PCL_ERROR ("[pcl::%s::computeFeature] The number of intensity bins must be greater than zero!\n", 00124 getClassName ().c_str ()); 00125 output.width = output.height = 0; 00126 output.points.clear (); 00127 return; 00128 } 00129 if (nr_distance_bins_ <= 0) 00130 { 00131 PCL_ERROR ("[pcl::%s::computeFeature] The number of distance bins must be greater than zero!\n", 00132 getClassName ().c_str ()); 00133 output.width = output.height = 0; 00134 output.points.clear (); 00135 return; 00136 } 00137 00138 Eigen::MatrixXf intensity_spin_image (nr_intensity_bins_, nr_distance_bins_); 00139 // Allocate enough space to hold the radiusSearch results 00140 std::vector<int> nn_indices (surface_->points.size ()); 00141 std::vector<float> nn_dist_sqr (surface_->points.size ()); 00142 00143 output.is_dense = true; 00144 // Iterating over the entire index vector 00145 for (size_t idx = 0; idx < indices_->size (); ++idx) 00146 { 00147 // Find neighbors within the search radius 00148 // TODO: do we want to use searchForNeigbors instead? 00149 int k = tree_->radiusSearch ((*indices_)[idx], search_radius_, nn_indices, nn_dist_sqr); 00150 if (k == 0) 00151 { 00152 for (int bin = 0; bin < nr_intensity_bins_ * nr_distance_bins_; ++bin) 00153 output.points[idx].histogram[bin] = std::numeric_limits<float>::quiet_NaN (); 00154 output.is_dense = false; 00155 continue; 00156 } 00157 00158 // Compute the intensity spin image 00159 computeIntensitySpinImage (*surface_, search_radius_, sigma_, k, nn_indices, nn_dist_sqr, intensity_spin_image); 00160 00161 // Copy into the resultant cloud 00162 int bin = 0; 00163 for (int bin_j = 0; bin_j < intensity_spin_image.cols (); ++bin_j) 00164 for (int bin_i = 0; bin_i < intensity_spin_image.rows (); ++bin_i) 00165 output.points[idx].histogram[bin++] = intensity_spin_image (bin_i, bin_j); 00166 } 00167 } 00168 00170 template <typename PointInT> void 00171 pcl::IntensitySpinEstimation<PointInT, Eigen::MatrixXf>::computeFeature (pcl::PointCloud<Eigen::MatrixXf> &output) 00172 { 00173 // These should be moved into initCompute () 00174 { 00175 // Make sure a search radius is set 00176 if (search_radius_ == 0.0) 00177 { 00178 PCL_ERROR ("[pcl::%s::computeFeature] The search radius must be set before computing the feature!\n", 00179 getClassName ().c_str ()); 00180 output.width = output.height = 0; 00181 output.points.resize (0, 0); 00182 return; 00183 } 00184 00185 // Make sure the spin image has valid dimensions 00186 if (nr_intensity_bins_ <= 0) 00187 { 00188 PCL_ERROR ("[pcl::%s::computeFeature] The number of intensity bins must be greater than zero!\n", 00189 getClassName ().c_str ()); 00190 output.width = output.height = 0; 00191 output.points.resize (0, 0); 00192 return; 00193 } 00194 if (nr_distance_bins_ <= 0) 00195 { 00196 PCL_ERROR ("[pcl::%s::computeFeature] The number of distance bins must be greater than zero!\n", 00197 getClassName ().c_str ()); 00198 output.width = output.height = 0; 00199 output.points.resize (0, 0); 00200 return; 00201 } 00202 } 00203 00204 output.points.resize (indices_->size (), nr_intensity_bins_ * nr_distance_bins_); 00205 Eigen::MatrixXf intensity_spin_image (nr_intensity_bins_, nr_distance_bins_); 00206 // Allocate enough space to hold the radiusSearch results 00207 std::vector<int> nn_indices; 00208 std::vector<float> nn_dist_sqr; 00209 00210 output.is_dense = true; 00211 // Iterating over the entire index vector 00212 for (size_t idx = 0; idx < indices_->size (); ++idx) 00213 { 00214 // Find neighbors within the search radius 00215 int k = tree_->radiusSearch ((*indices_)[idx], search_radius_, nn_indices, nn_dist_sqr); 00216 if (k == 0) 00217 { 00218 output.points.row (idx).setConstant (std::numeric_limits<float>::quiet_NaN ()); 00219 output.is_dense = false; 00220 continue; 00221 } 00222 00223 // Compute the intensity spin image 00224 this->computeIntensitySpinImage (*surface_, search_radius_, sigma_, k, nn_indices, nn_dist_sqr, intensity_spin_image); 00225 00226 // Copy into the resultant cloud 00227 int bin = 0; 00228 for (int bin_j = 0; bin_j < intensity_spin_image.cols (); ++bin_j) 00229 for (int bin_i = 0; bin_i < intensity_spin_image.rows (); ++bin_i) 00230 output.points (idx, bin++) = intensity_spin_image (bin_i, bin_j); 00231 } 00232 } 00233 00234 00235 #define PCL_INSTANTIATE_IntensitySpinEstimation(T,NT) template class PCL_EXPORTS pcl::IntensitySpinEstimation<T,NT>; 00236 00237 #endif // PCL_FEATURES_IMPL_INTENSITY_SPIN_H_ 00238
1.7.6.1