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