|
Point Cloud Library (PCL)
1.5.1
|
00001 /* 00002 * Software License Agreement (BSD License) 00003 * 00004 * Copyright (c) 2011, 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 #ifndef PCL_FEATURES_INTEGRALIMAGE_BASED_IMPL_NORMAL_ESTIMATOR_H_ 00037 #define PCL_FEATURES_INTEGRALIMAGE_BASED_IMPL_NORMAL_ESTIMATOR_H_ 00038 00039 #include "pcl/features/integral_image_normal.h" 00040 00042 template <typename PointInT, typename PointOutT> 00043 pcl::IntegralImageNormalEstimation<PointInT, PointOutT>::~IntegralImageNormalEstimation () 00044 { 00045 if (diff_x_ != NULL) delete diff_x_; 00046 if (diff_y_ != NULL) delete diff_y_; 00047 if (depth_data_ != NULL) delete depth_data_; 00048 } 00049 00051 template <typename PointInT, typename PointOutT> void 00052 pcl::IntegralImageNormalEstimation<PointInT, PointOutT>::initData () 00053 { 00054 // compute derivatives 00055 if (diff_x_ != NULL) delete diff_x_; 00056 if (diff_y_ != NULL) delete diff_y_; 00057 if (depth_data_ != NULL) delete depth_data_; 00058 diff_x_ = NULL; 00059 diff_y_ = NULL; 00060 depth_data_ = NULL; 00061 00062 if (normal_estimation_method_ == COVARIANCE_MATRIX) 00063 initCovarianceMatrixMethod (); 00064 else if (normal_estimation_method_ == AVERAGE_3D_GRADIENT) 00065 initAverage3DGradientMethod (); 00066 else if (normal_estimation_method_ == AVERAGE_DEPTH_CHANGE) 00067 initAverageDepthChangeMethod (); 00068 else if (normal_estimation_method_ == SIMPLE_3D_GRADIENT) 00069 initSimple3DGradientMethod (); 00070 } 00071 00072 00074 template <typename PointInT, typename PointOutT> void 00075 pcl::IntegralImageNormalEstimation<PointInT, PointOutT>::setRectSize (const int width, const int height) 00076 { 00077 rect_width_ = width; 00078 rect_width_2_ = width >> 1; 00079 rect_width_4_ = width >> 2; 00080 rect_height_ = height; 00081 rect_height_2_ = height >> 1; 00082 rect_height_4_ = height >> 2; 00083 } 00084 00086 template <typename PointInT, typename PointOutT> void 00087 pcl::IntegralImageNormalEstimation<PointInT, PointOutT>::initSimple3DGradientMethod () 00088 { 00089 // number of DataType entries per element (equal or bigger than dimensions) 00090 int element_stride = sizeof (PointInT) / sizeof (float); 00091 // number of DataType entries per row (equal or bigger than element_stride number of elements per row) 00092 int row_stride = element_stride * input_->width; 00093 00094 float *data_ = reinterpret_cast<float*>((PointInT*)(&(input_->points[0]))); 00095 00096 integral_image_XYZ_.setSecondOrderComputation (false); 00097 integral_image_XYZ_.setInput (data_, input_->width, input_->height, element_stride, row_stride); 00098 00099 init_simple_3d_gradient_ = true; 00100 init_covariance_matrix_ = init_average_3d_gradient_ = init_depth_change_ = false; 00101 } 00102 00104 template <typename PointInT, typename PointOutT> void 00105 pcl::IntegralImageNormalEstimation<PointInT, PointOutT>::initCovarianceMatrixMethod () 00106 { 00107 // number of DataType entries per element (equal or bigger than dimensions) 00108 int element_stride = sizeof (PointInT) / sizeof (float); 00109 // number of DataType entries per row (equal or bigger than element_stride number of elements per row) 00110 int row_stride = element_stride * input_->width; 00111 00112 float *data_ = reinterpret_cast<float*>((PointInT*)(&(input_->points[0]))); 00113 00114 integral_image_XYZ_.setSecondOrderComputation (true); 00115 integral_image_XYZ_.setInput (data_, input_->width, input_->height, element_stride, row_stride); 00116 00117 init_covariance_matrix_ = true; 00118 init_average_3d_gradient_ = init_depth_change_ = init_simple_3d_gradient_ = false; 00119 } 00120 00122 template <typename PointInT, typename PointOutT> void 00123 pcl::IntegralImageNormalEstimation<PointInT, PointOutT>::initAverage3DGradientMethod () 00124 { 00125 size_t data_size = (input_->points.size () << 2); 00126 diff_x_ = new float[data_size]; 00127 diff_y_ = new float[data_size]; 00128 00129 memset (diff_x_, 0, sizeof(float) * data_size); 00130 memset (diff_y_, 0, sizeof(float) * data_size); 00131 00132 // x u x 00133 // l x r 00134 // x d x 00135 const PointInT* point_up = &(input_->points [1]); 00136 const PointInT* point_dn = point_up + (input_->width << 1);//&(input_->points [1 + (input_->width << 1)]); 00137 const PointInT* point_lf = &(input_->points [input_->width]); 00138 const PointInT* point_rg = point_lf + 2; //&(input_->points [input_->width + 2]); 00139 float* diff_x_ptr = diff_x_ + ((input_->width + 1) << 2); 00140 float* diff_y_ptr = diff_y_ + ((input_->width + 1) << 2); 00141 unsigned diff_skip = 8; // skip last element in row and the first in the next row 00142 00143 for (size_t ri = 1; ri < input_->height - 1; ++ri 00144 , point_up += input_->width 00145 , point_dn += input_->width 00146 , point_lf += input_->width 00147 , point_rg += input_->width 00148 , diff_x_ptr += diff_skip 00149 , diff_y_ptr += diff_skip) 00150 { 00151 for (size_t ci = 0; ci < input_->width - 2; ++ci, diff_x_ptr += 4, diff_y_ptr += 4) 00152 { 00153 diff_x_ptr[0] = point_rg[ci].x - point_lf[ci].x; 00154 diff_x_ptr[1] = point_rg[ci].y - point_lf[ci].y; 00155 diff_x_ptr[2] = point_rg[ci].z - point_lf[ci].z; 00156 00157 diff_y_ptr[0] = point_dn[ci].x - point_up[ci].x; 00158 diff_y_ptr[1] = point_dn[ci].y - point_up[ci].y; 00159 diff_y_ptr[2] = point_dn[ci].z - point_up[ci].z; 00160 } 00161 } 00162 00163 // Compute integral images 00164 integral_image_DX_.setInput (diff_x_, input_->width, input_->height, 4, input_->width << 2); 00165 integral_image_DY_.setInput (diff_y_, input_->width, input_->height, 4, input_->width << 2); 00166 init_covariance_matrix_ = init_depth_change_ = init_simple_3d_gradient_ = false; 00167 init_average_3d_gradient_ = true; 00168 } 00169 00171 template <typename PointInT, typename PointOutT> void 00172 pcl::IntegralImageNormalEstimation<PointInT, PointOutT>::initAverageDepthChangeMethod () 00173 { 00174 // number of DataType entries per element (equal or bigger than dimensions) 00175 int element_stride = sizeof (PointInT) / sizeof (float); 00176 // number of DataType entries per row (equal or bigger than element_stride number of elements per row) 00177 int row_stride = element_stride * input_->width; 00178 00179 float *data_ = reinterpret_cast<float*>((PointInT*)(&(input_->points[0]))); 00180 00181 // integral image over the z - value 00182 integral_image_depth_.setInput (&(data_[2]), input_->width, input_->height, element_stride, row_stride); 00183 init_depth_change_ = true; 00184 init_covariance_matrix_ = init_average_3d_gradient_ = init_simple_3d_gradient_ = false; 00185 } 00186 00188 template <typename PointInT, typename PointOutT> void 00189 pcl::IntegralImageNormalEstimation<PointInT, PointOutT>::computePointNormal ( 00190 const int pos_x, const int pos_y, const unsigned point_index, PointOutT &normal) 00191 { 00192 float bad_point = std::numeric_limits<float>::quiet_NaN (); 00193 00194 if (normal_estimation_method_ == COVARIANCE_MATRIX) 00195 { 00196 if (!init_covariance_matrix_) 00197 initCovarianceMatrixMethod (); 00198 00199 unsigned count = integral_image_XYZ_.getFiniteElementsCount (pos_x - (rect_width_2_), pos_y - (rect_height_2_), rect_width_, rect_height_); 00200 00201 // no valid points within the rectangular reagion? 00202 if (count == 0) 00203 { 00204 normal.normal_x = normal.normal_y = normal.normal_z = normal.curvature = std::numeric_limits<float>::quiet_NaN (); 00205 return; 00206 } 00207 00208 EIGEN_ALIGN16 Eigen::Matrix3f covariance_matrix; 00209 Eigen::Vector3f center; 00210 typename IntegralImage2D<float, 3>::SecondOrderType so_elements; 00211 center = integral_image_XYZ_.getFirstOrderSum(pos_x - rect_width_2_, pos_y - rect_height_2_, rect_width_, rect_height_).cast<float> (); 00212 so_elements = integral_image_XYZ_.getSecondOrderSum(pos_x - rect_width_2_, pos_y - rect_height_2_, rect_width_, rect_height_); 00213 00214 covariance_matrix.coeffRef (0) = so_elements [0]; 00215 covariance_matrix.coeffRef (1) = covariance_matrix.coeffRef (3) = so_elements [1]; 00216 covariance_matrix.coeffRef (2) = covariance_matrix.coeffRef (6) = so_elements [2]; 00217 covariance_matrix.coeffRef (4) = so_elements [3]; 00218 covariance_matrix.coeffRef (5) = covariance_matrix.coeffRef (7) = so_elements [4]; 00219 covariance_matrix.coeffRef (8) = so_elements [5]; 00220 covariance_matrix -= (center * center.transpose ()) / count; 00221 float eigen_value; 00222 Eigen::Vector3f eigen_vector; 00223 pcl::eigen33 (covariance_matrix, eigen_value, eigen_vector); 00224 if (eigen_vector [2] < 0.0f) 00225 normal.getNormalVector4fMap () = Eigen::Vector4f (eigen_vector [0], eigen_vector [1], eigen_vector [2], 0); 00226 else 00227 normal.getNormalVector4fMap () = Eigen::Vector4f (-eigen_vector [0], -eigen_vector [1], -eigen_vector [2], 0); 00228 00229 // Compute the curvature surface change 00230 if (eigen_value > 0.0) 00231 normal.curvature = fabs ( eigen_value / (covariance_matrix.coeff (0) + covariance_matrix.coeff (4) + covariance_matrix.coeff (8)) ); 00232 else 00233 normal.curvature = 0; 00234 00235 return; 00236 } 00237 else if (normal_estimation_method_ == AVERAGE_3D_GRADIENT) 00238 { 00239 if (!init_average_3d_gradient_) 00240 initAverage3DGradientMethod (); 00241 00242 unsigned count_x = integral_image_DX_.getFiniteElementsCount (pos_x - rect_width_2_, pos_y - rect_height_2_, rect_width_, rect_height_); 00243 unsigned count_y = integral_image_DY_.getFiniteElementsCount (pos_x - rect_width_2_, pos_y - rect_height_2_, rect_width_, rect_height_); 00244 if (count_x == 0 || count_y == 0) 00245 { 00246 normal.normal_x = normal.normal_y = normal.normal_z = normal.curvature = std::numeric_limits<float>::quiet_NaN (); 00247 return; 00248 } 00249 Eigen::Vector3d gradient_x = integral_image_DX_.getFirstOrderSum (pos_x - rect_width_2_, pos_y - rect_height_2_, rect_width_, rect_height_); 00250 Eigen::Vector3d gradient_y = integral_image_DY_.getFirstOrderSum (pos_x - rect_width_2_, pos_y - rect_height_2_, rect_width_, rect_height_); 00251 00252 Eigen::Vector3d normal_vector = gradient_y.cross (gradient_x); 00253 double normal_length = normal_vector.squaredNorm (); 00254 if (normal_length == 0.0f) 00255 { 00256 normal.getNormalVector4fMap ().setConstant (bad_point); 00257 normal.curvature = bad_point; 00258 return; 00259 } 00260 00261 normal_vector /= sqrt(normal_length); 00262 normal.normal_x = normal_vector [0]; 00263 normal.normal_y = normal_vector [1]; 00264 normal.normal_z = normal_vector [2]; 00265 normal.curvature = bad_point; 00266 return; 00267 } 00268 else if (normal_estimation_method_ == AVERAGE_DEPTH_CHANGE) 00269 { 00270 if (!init_depth_change_) 00271 initAverageDepthChangeMethod (); 00272 00273 // unsigned count = integral_image_depth_.getFiniteElementsCount (pos_x - rect_width_2_, pos_y - rect_height_2_, rect_width_, rect_height_); 00274 // if (count == 0) 00275 // { 00276 // normal.normal_x = normal.normal_y = normal.normal_z = normal.curvature = std::numeric_limits<float>::quiet_NaN (); 00277 // return; 00278 // } 00279 // const float mean_L_z = integral_image_depth_.getFirstOrderSum (pos_x - rect_width_2_ - 1, pos_y - rect_height_2_ , rect_width_ - 1, rect_height_ - 1) / ((rect_width_-1)*(rect_height_-1)); 00280 // const float mean_R_z = integral_image_depth_.getFirstOrderSum (pos_x - rect_width_2_ + 1, pos_y - rect_height_2_ , rect_width_ - 1, rect_height_ - 1) / ((rect_width_-1)*(rect_height_-1)); 00281 // const float mean_U_z = integral_image_depth_.getFirstOrderSum (pos_x - rect_width_2_ , pos_y - rect_height_2_ - 1, rect_width_ - 1, rect_height_ - 1) / ((rect_width_-1)*(rect_height_-1)); 00282 // const float mean_D_z = integral_image_depth_.getFirstOrderSum (pos_x - rect_width_2_ , pos_y - rect_height_2_ + 1, rect_width_ - 1, rect_height_ - 1) / ((rect_width_-1)*(rect_height_-1)); 00283 00284 // width and height are at least 3 x 3 00285 unsigned count_L_z = integral_image_depth_.getFiniteElementsCount (pos_x - rect_width_2_, pos_y - rect_height_4_, rect_width_2_, rect_height_2_); 00286 unsigned count_R_z = integral_image_depth_.getFiniteElementsCount (pos_x + 1 , pos_y - rect_height_4_, rect_width_2_, rect_height_2_); 00287 unsigned count_U_z = integral_image_depth_.getFiniteElementsCount (pos_x - rect_width_4_, pos_y - rect_height_2_, rect_width_2_, rect_height_2_); 00288 unsigned count_D_z = integral_image_depth_.getFiniteElementsCount (pos_x - rect_width_4_, pos_y + 1 , rect_width_2_, rect_height_2_); 00289 00290 if (count_L_z == 0 || count_R_z == 0 || count_U_z == 0 || count_D_z == 0) 00291 { 00292 normal.normal_x = normal.normal_y = normal.normal_z = normal.curvature = std::numeric_limits<float>::quiet_NaN (); 00293 return; 00294 } 00295 00296 float mean_L_z = integral_image_depth_.getFirstOrderSum (pos_x - rect_width_2_, pos_y - rect_height_4_, rect_width_2_, rect_height_2_) / count_L_z; 00297 float mean_R_z = integral_image_depth_.getFirstOrderSum (pos_x + 1 , pos_y - rect_height_4_, rect_width_2_, rect_height_2_) / count_R_z; 00298 float mean_U_z = integral_image_depth_.getFirstOrderSum (pos_x - rect_width_4_, pos_y - rect_height_2_, rect_width_2_, rect_height_2_) / count_U_z; 00299 float mean_D_z = integral_image_depth_.getFirstOrderSum (pos_x - rect_width_4_, pos_y + 1 , rect_width_2_, rect_height_2_) / count_D_z; 00300 00301 PointInT pointL = input_->points[point_index - rect_width_4_ - 1]; 00302 PointInT pointR = input_->points[point_index + rect_width_4_ + 1]; 00303 PointInT pointU = input_->points[point_index - rect_height_4_ * input_->width - 1]; 00304 PointInT pointD = input_->points[point_index + rect_height_4_ * input_->width + 1]; 00305 00306 const float mean_x_z = mean_R_z - mean_L_z; 00307 const float mean_y_z = mean_D_z - mean_U_z; 00308 00309 const float mean_x_x = pointR.x - pointL.x; 00310 const float mean_x_y = pointR.y - pointL.y; 00311 const float mean_y_x = pointD.x - pointU.x; 00312 const float mean_y_y = pointD.y - pointU.y; 00313 00314 const float normal_x = mean_x_y * mean_y_z - mean_x_z * mean_y_y; 00315 const float normal_y = mean_x_z * mean_y_x - mean_x_x * mean_y_z; 00316 const float normal_z = mean_x_x * mean_y_y - mean_x_y * mean_y_x; 00317 00318 const float normal_length = (normal_x * normal_x + normal_y * normal_y + normal_z * normal_z); 00319 00320 if (normal_length == 0.0f) 00321 { 00322 normal.getNormalVector4fMap ().setConstant (bad_point); 00323 normal.curvature = bad_point; 00324 return; 00325 } 00326 00327 const float scale = -1.0f / sqrt (normal_length); 00328 00329 normal.normal_x = normal_x * scale; 00330 normal.normal_y = normal_y * scale; 00331 normal.normal_z = normal_z * scale; 00332 normal.curvature = bad_point; 00333 00334 return; 00335 } 00336 else if (normal_estimation_method_ == SIMPLE_3D_GRADIENT) 00337 { 00338 if (!init_simple_3d_gradient_) 00339 initSimple3DGradientMethod (); 00340 00341 // this method does not work if lots of NaNs are in the neighborhood of the point 00342 Eigen::Vector3d gradient_x = integral_image_XYZ_.getFirstOrderSum (pos_x + rect_width_2_, pos_y - rect_height_2_, 1, rect_height_) - 00343 integral_image_XYZ_.getFirstOrderSum (pos_x - rect_width_2_, pos_y - rect_height_2_, 1, rect_height_); 00344 00345 Eigen::Vector3d gradient_y = integral_image_XYZ_.getFirstOrderSum (pos_x - rect_width_2_, pos_y + rect_height_2_, rect_width_, 1) - 00346 integral_image_XYZ_.getFirstOrderSum (pos_x - rect_width_2_, pos_y - rect_height_2_, rect_width_, 1); 00347 Eigen::Vector3d normal_vector = gradient_y.cross (gradient_x); 00348 double normal_length = normal_vector.squaredNorm (); 00349 if (normal_length == 0.0f) 00350 { 00351 normal.getNormalVector4fMap ().setConstant (bad_point); 00352 normal.curvature = bad_point; 00353 return; 00354 } 00355 00356 normal_vector /= sqrt(normal_length); 00357 normal.normal_x = normal_vector [0]; 00358 normal.normal_y = normal_vector [1]; 00359 normal.normal_z = normal_vector [2]; 00360 normal.curvature = bad_point; 00361 return; 00362 } 00363 00364 normal.getNormalVector4fMap ().setConstant (bad_point); 00365 normal.curvature = bad_point; 00366 return; 00367 } 00368 00370 template <typename PointInT, typename PointOutT> void 00371 pcl::IntegralImageNormalEstimation<PointInT, PointOutT>::computeFeature (PointCloudOut &output) 00372 { 00373 float bad_point = std::numeric_limits<float>::quiet_NaN (); 00374 00375 // compute depth-change map 00376 unsigned char * depthChangeMap = new unsigned char[input_->points.size ()]; 00377 memset (depthChangeMap, 255, input_->points.size ()); 00378 00379 unsigned index = 0; 00380 for (unsigned int ri = 0; ri < input_->height-1; ++ri) 00381 { 00382 for (unsigned int ci = 0; ci < input_->width-1; ++ci, ++index) 00383 { 00384 // const float depth = (*input_)(ci, ri ).z; 00385 // const float depthR = (*input_)(ci + 1, ri ).z; 00386 // const float depthD = (*input_)(ci, ri + 1).z; 00387 00388 const float depth = input_->points [index].z; 00389 const float depthR = input_->points [index + 1].z; 00390 const float depthD = input_->points [index + input_->width].z; 00391 00392 //const float depthDependendDepthChange = (max_depth_change_factor_ * (fabs(depth)+1.0f))/(500.0f*0.001f); 00393 const float depthDependendDepthChange = (max_depth_change_factor_ * (fabs (depth) + 1.0f) * 2.0f); 00394 00395 if (abs (depth - depthR) > depthDependendDepthChange 00396 || !pcl_isfinite (depth) || !pcl_isfinite (depthR)) 00397 { 00398 depthChangeMap[index] = 0; 00399 depthChangeMap[index] = 0; 00400 } 00401 if (abs (depth - depthD) > depthDependendDepthChange 00402 || !pcl_isfinite (depth) || !pcl_isfinite (depthD)) 00403 { 00404 depthChangeMap[index] = 0; 00405 depthChangeMap[index + input_->width] = 0; 00406 } 00407 } 00408 } 00409 00410 // compute distance map 00411 float *distanceMap = new float[input_->points.size ()]; 00412 for (size_t index = 0; index < input_->points.size (); ++index) 00413 { 00414 if (depthChangeMap[index] == 0) 00415 distanceMap[index] = 0.0f; 00416 else 00417 distanceMap[index] = input_->width + input_->height; 00418 } 00419 00420 // first pass 00421 float* previous_row = distanceMap; 00422 float* current_row = previous_row + input_->width; 00423 for (size_t ri = 1; ri < input_->height; ++ri) 00424 { 00425 for (size_t ci = 1; ci < input_->width; ++ci) 00426 { 00427 const float upLeft = previous_row [ci - 1] + 1.4f; //distanceMap[(ri-1)*input_->width + ci-1] + 1.4f; 00428 const float up = previous_row [ci] + 1.0f; //distanceMap[(ri-1)*input_->width + ci] + 1.0f; 00429 const float upRight = previous_row [ci + 1] + 1.4f; //distanceMap[(ri-1)*input_->width + ci+1] + 1.4f; 00430 const float left = current_row [ci - 1] + 1.0f; //distanceMap[ri*input_->width + ci-1] + 1.0f; 00431 const float center = current_row [ci]; //distanceMap[ri*input_->width + ci]; 00432 00433 const float minValue = std::min (std::min (upLeft, up), std::min (left, upRight)); 00434 00435 if (minValue < center) 00436 current_row [ci] = minValue; //distanceMap[ri * input_->width + ci] = minValue; 00437 } 00438 previous_row = current_row; 00439 current_row += input_->width; 00440 } 00441 00442 float* next_row = distanceMap + input_->width * (input_->height - 1); 00443 current_row = next_row - input_->width; 00444 // second pass 00445 for (int ri = input_->height-2; ri >= 0; --ri) 00446 { 00447 for (int ci = input_->width-2; ci >= 0; --ci) 00448 { 00449 const float lowerLeft = next_row [ci - 1] + 1.4f; //distanceMap[(ri+1)*input_->width + ci-1] + 1.4f; 00450 const float lower = next_row [ci] + 1.0f; //distanceMap[(ri+1)*input_->width + ci] + 1.0f; 00451 const float lowerRight = next_row [ci + 1] + 1.4f; //distanceMap[(ri+1)*input_->width + ci+1] + 1.4f; 00452 const float right = current_row [ci + 1] + 1.0f; //distanceMap[ri*input_->width + ci+1] + 1.0f; 00453 const float center = current_row [ci]; //distanceMap[ri*input_->width + ci]; 00454 00455 const float minValue = std::min (std::min (lowerLeft, lower), std::min (right, lowerRight)); 00456 00457 if (minValue < center) 00458 current_row [ci] = minValue; //distanceMap[ri*input_->width + ci] = minValue; 00459 } 00460 } 00461 00462 // Set all normals that we do not touch to NaN 00463 // top and bottom borders 00464 unsigned border = int(normal_smoothing_size_); 00465 PointOutT* vec1 = &output [0]; 00466 PointOutT* vec2 = vec1 + input_->width * (input_->height - border); 00467 00468 size_t count = border * input_->width; 00469 for (size_t idx = 0; idx < count; ++idx) 00470 { 00471 vec1 [idx].getNormalVector4fMap ().setConstant (bad_point); 00472 vec1 [idx].curvature = bad_point; 00473 vec2 [idx].getNormalVector4fMap ().setConstant (bad_point); 00474 vec2 [idx].curvature = bad_point; 00475 } 00476 00477 // left and right borders actually columns 00478 vec1 = &output [border * input_->width]; 00479 vec2 = vec1 + input_->width - border; 00480 for (size_t ri = border; ri < input_->height - border; ++ri, vec1 += input_->width, vec2 += input_->width) 00481 { 00482 for (size_t ci = 0; ci < border; ++ci) 00483 { 00484 vec1 [ci].getNormalVector4fMap ().setConstant (bad_point); 00485 vec1 [ci].curvature = bad_point; 00486 vec2 [ci].getNormalVector4fMap ().setConstant (bad_point); 00487 vec2 [ci].curvature = bad_point; 00488 } 00489 } 00490 00491 if (use_depth_dependent_smoothing_) 00492 { 00493 index = border + input_->width * border; 00494 unsigned skip = (border << 1); 00495 for (unsigned ri = border; ri < input_->height - border; ++ri, index += skip) 00496 { 00497 for (unsigned ci = border; ci < input_->width - border; ++ci, ++index) 00498 { 00499 const float depth = input_->points[index].z; 00500 if (!pcl_isfinite (depth)) 00501 { 00502 output[index].getNormalVector4fMap ().setConstant (bad_point); 00503 output[index].curvature = bad_point; 00504 continue; 00505 } 00506 00507 float smoothing = (std::min)(distanceMap[index], normal_smoothing_size_ + static_cast<float>(depth)/10.0f); 00508 00509 if (smoothing > 2.0f) 00510 { 00511 setRectSize (smoothing, smoothing); 00512 computePointNormal (ci, ri, index, output [index]); 00513 } 00514 else 00515 { 00516 output[index].getNormalVector4fMap ().setConstant (bad_point); 00517 output[index].curvature = bad_point; 00518 } 00519 } 00520 } 00521 } 00522 else 00523 { 00524 float smoothing_constant = normal_smoothing_size_ * 2.0f; 00525 00526 index = border + input_->width * border; 00527 unsigned skip = (border << 1); 00528 for (unsigned ri = border; ri < input_->height - border; ++ri, index += skip) 00529 { 00530 for (unsigned ci = border; ci < input_->width - border; ++ci, ++index) 00531 { 00532 if (!pcl_isfinite (input_->points[index].z)) 00533 { 00534 output [index].getNormalVector4fMap ().setConstant (bad_point); 00535 output [index].curvature = bad_point; 00536 continue; 00537 } 00538 00539 float smoothing = (std::min)(distanceMap[index], smoothing_constant); 00540 00541 if (smoothing > 2.0f) 00542 { 00543 setRectSize (smoothing, smoothing); 00544 computePointNormal (ci, ri, index, output [index]); 00545 } 00546 else 00547 { 00548 output [index].getNormalVector4fMap ().setConstant (bad_point); 00549 output [index].curvature = bad_point; 00550 } 00551 } 00552 } 00553 } 00554 00555 delete[] depthChangeMap; 00556 delete[] distanceMap; 00557 } 00558 00560 template <typename PointInT, typename PointOutT> bool 00561 pcl::IntegralImageNormalEstimation<PointInT, PointOutT>::initCompute () 00562 { 00563 if (!input_->isOrganized ()) 00564 { 00565 PCL_ERROR ("[pcl::IntegralImageNormalEstimation::initCompute] Input dataset is not organized (height = 1).\n"); 00566 return (false); 00567 } 00568 return (Feature<PointInT, PointOutT>::initCompute ()); 00569 } 00570 00571 #define PCL_INSTANTIATE_IntegralImageNormalEstimation(T,NT) template class PCL_EXPORTS pcl::IntegralImageNormalEstimation<T,NT>; 00572 00573 #endif 00574
1.8.0