00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <iostream>
00039 using std::cout;
00040 using std::cerr;
00041 #include <map>
00042 #include <set>
00043 #include <cmath>
00044 #include <pcl/pcl_macros.h>
00045 #include <pcl/common/common_headers.h>
00046 #include <pcl/range_image/range_image.h>
00047 #include <pcl/point_cloud.h>
00048 #include <pcl/common/vector_average.h>
00049 #include <pcl/features/eigen.h>
00050 #include <pcl/features/range_image_border_extractor.h>
00051
00052 namespace pcl
00053 {
00054
00056 RangeImageBorderExtractor::RangeImageBorderExtractor(const RangeImage* range_image) : BaseClass(),
00057 parameters_ (), range_image_(range_image), range_image_size_during_extraction_(0),
00058 border_scores_left_(NULL), border_scores_right_(NULL), border_scores_top_(NULL), border_scores_bottom_(NULL),
00059 surface_structure_(NULL), border_descriptions_(NULL), shadow_border_informations_(NULL), border_directions_(NULL),
00060 surface_change_scores_(NULL), surface_change_directions_(NULL)
00061 {
00062 }
00063
00065 RangeImageBorderExtractor::~RangeImageBorderExtractor()
00066 {
00067 clearData ();
00068 }
00069
00071 void
00072 RangeImageBorderExtractor::setRangeImage (const RangeImage* range_image)
00073 {
00074 clearData ();
00075 range_image_ = range_image;
00076 }
00077
00079 void
00080 RangeImageBorderExtractor::clearData ()
00081 {
00082 delete[] border_scores_left_; border_scores_left_ = NULL;
00083 delete[] border_scores_right_; border_scores_right_ = NULL;
00084 delete[] border_scores_top_; border_scores_top_ = NULL;
00085 delete[] border_scores_bottom_; border_scores_bottom_ = NULL;
00086
00087 for (int i=0; i<range_image_size_during_extraction_; ++i)
00088 {
00089 if (surface_structure_!=NULL)
00090 delete surface_structure_[i];
00091 if (shadow_border_informations_!=NULL)
00092 delete shadow_border_informations_[i];
00093 if (border_directions_!=NULL)
00094 delete border_directions_[i];
00095 }
00096 delete[] surface_structure_; surface_structure_ = NULL;
00097 delete border_descriptions_; border_descriptions_ = NULL;
00098 delete[] shadow_border_informations_; shadow_border_informations_ = NULL;
00099 delete[] border_directions_; border_directions_ = NULL;
00100
00101 delete[] surface_change_scores_; surface_change_scores_ = NULL;
00102 delete[] surface_change_directions_; surface_change_directions_ = NULL;
00103 }
00104
00106 void
00107 RangeImageBorderExtractor::extractLocalSurfaceStructure ()
00108 {
00109 if (surface_structure_ != NULL)
00110 return;
00111
00112
00113
00114 int width = range_image_->width,
00115 height = range_image_->height;
00116 range_image_size_during_extraction_ = width*height;
00117 int array_size = range_image_size_during_extraction_;
00118 surface_structure_ = new LocalSurface*[array_size];
00119 int step_size = (std::max)(1, parameters_.pixel_radius_plane_extraction/2);
00120
00121 int no_of_nearest_neighbors = static_cast<int> (pow (static_cast<double> (parameters_.pixel_radius_plane_extraction/step_size + 1), 2.0));
00122
00123 # pragma omp parallel for num_threads(parameters_.max_no_of_threads) default(shared) schedule(dynamic, 10)
00124 for (int y=0; y<height; ++y)
00125 {
00126 for (int x=0; x<width; ++x)
00127 {
00128 int index = y*width + x;
00129 LocalSurface*& local_surface = surface_structure_[index];
00130 local_surface = NULL;
00131 if (!range_image_->isValid(index))
00132 continue;
00133 local_surface = new LocalSurface;
00134 Eigen::Vector3f point;
00135 range_image_->getPoint(x, y, point);
00136
00137 if (!range_image_->getSurfaceInformation(x, y, parameters_.pixel_radius_plane_extraction, point,
00138 no_of_nearest_neighbors, step_size, local_surface->max_neighbor_distance_squared,
00139 local_surface->normal_no_jumps, local_surface->neighborhood_mean_no_jumps,
00140 local_surface->eigen_values_no_jumps, &local_surface->normal,
00141 &local_surface->neighborhood_mean, &local_surface->eigen_values))
00142 {
00143 delete local_surface;
00144 local_surface = NULL;
00145 }
00146
00147
00148 }
00149 }
00150 }
00151
00153 void
00154 RangeImageBorderExtractor::extractBorderScoreImages ()
00155 {
00156 if (border_scores_left_ != NULL)
00157 return;
00158
00159 extractLocalSurfaceStructure();
00160
00161
00162
00163 int width = range_image_->width,
00164 height = range_image_->height,
00165 size = width*height;
00166 border_scores_left_ = new float[size];
00167 border_scores_right_ = new float[size];
00168 border_scores_top_ = new float[size];
00169 border_scores_bottom_ = new float[size];
00170
00171 # pragma omp parallel for num_threads(parameters_.max_no_of_threads) default(shared) schedule(dynamic, 10)
00172 for (int y=0; y<height; ++y) {
00173 for (int x=0; x<width; ++x) {
00174 int index = y*width + x;
00175 float& left=border_scores_left_[index]; float& right=border_scores_right_[index];
00176 float& top=border_scores_top_[index]; float& bottom=border_scores_bottom_[index];
00177 LocalSurface* local_surface_ptr = surface_structure_[index];
00178 if (local_surface_ptr==NULL)
00179 {
00180 left=right=top=bottom = 0.0f;
00181 continue;
00182 }
00183
00184 left = getNeighborDistanceChangeScore(*local_surface_ptr, x, y, -1, 0, parameters_.pixel_radius_borders);
00185 right = getNeighborDistanceChangeScore(*local_surface_ptr, x, y, 1, 0, parameters_.pixel_radius_borders);
00186 top = getNeighborDistanceChangeScore(*local_surface_ptr, x, y, 0, -1, parameters_.pixel_radius_borders);
00187 bottom = getNeighborDistanceChangeScore(*local_surface_ptr, x, y, 0, 1, parameters_.pixel_radius_borders);
00188 }
00189 }
00190 }
00191
00193 float*
00194 RangeImageBorderExtractor::updatedScoresAccordingToNeighborValues (const float* border_scores) const
00195 {
00196 float* new_scores = new float[range_image_->width*range_image_->height];
00197 float* new_scores_ptr = new_scores;
00198 for (int y=0; y < static_cast<int> (range_image_->height); ++y)
00199 for (int x=0; x < static_cast<int> (range_image_->width); ++x)
00200 *(new_scores_ptr++) = updatedScoreAccordingToNeighborValues(x, y, border_scores);
00201 return (new_scores);
00202 }
00203
00205 void
00206 RangeImageBorderExtractor::updateScoresAccordingToNeighborValues ()
00207 {
00208 extractBorderScoreImages();
00209
00210
00211
00212 float* left_with_propagated_neighbors = updatedScoresAccordingToNeighborValues(border_scores_left_);
00213 delete[] border_scores_left_;
00214 border_scores_left_ = left_with_propagated_neighbors;
00215 float* right_with_propagated_neighbors = updatedScoresAccordingToNeighborValues(border_scores_right_);
00216 delete[] border_scores_right_;
00217 border_scores_right_ = right_with_propagated_neighbors;
00218 float* top_with_propagated_neighbors = updatedScoresAccordingToNeighborValues(border_scores_top_);
00219 delete[] border_scores_top_;
00220 border_scores_top_ = top_with_propagated_neighbors;
00221 float* bottom_with_propagated_neighbors = updatedScoresAccordingToNeighborValues(border_scores_bottom_);
00222 delete[] border_scores_bottom_;
00223 border_scores_bottom_ = bottom_with_propagated_neighbors;
00224 }
00225
00227 void
00228 RangeImageBorderExtractor::findAndEvaluateShadowBorders ()
00229 {
00230 if (shadow_border_informations_ != NULL)
00231 return;
00232
00233 if (border_scores_left_==NULL)
00234 {
00235 std::cerr << __PRETTY_FUNCTION__<<": border score images not available!\n";
00236 }
00237
00238
00239
00240 int width = range_image_->width,
00241 height = range_image_->height;
00242 shadow_border_informations_ = new ShadowBorderIndices*[width*height];
00243 for (int y = 0; y < static_cast<int> (height); ++y)
00244 {
00245 for (int x = 0; x < static_cast<int> (width); ++x)
00246 {
00247 int index = y*width+x;
00248 ShadowBorderIndices*& shadow_border_indices = shadow_border_informations_[index];
00249 shadow_border_indices = NULL;
00250 int shadow_border_idx;
00251
00252 if (changeScoreAccordingToShadowBorderValue(x, y, -1, 0, border_scores_left_, border_scores_right_, shadow_border_idx))
00253 {
00254 shadow_border_indices = (shadow_border_indices==NULL ? new ShadowBorderIndices : shadow_border_indices);
00255 shadow_border_indices->left = shadow_border_idx;
00256 }
00257 if (changeScoreAccordingToShadowBorderValue(x, y, 1, 0, border_scores_right_, border_scores_left_, shadow_border_idx))
00258 {
00259 shadow_border_indices = (shadow_border_indices==NULL ? new ShadowBorderIndices : shadow_border_indices);
00260 shadow_border_indices->right = shadow_border_idx;
00261 }
00262 if (changeScoreAccordingToShadowBorderValue(x, y, 0, -1, border_scores_top_, border_scores_bottom_, shadow_border_idx))
00263 {
00264 shadow_border_indices = (shadow_border_indices==NULL ? new ShadowBorderIndices : shadow_border_indices);
00265 shadow_border_indices->top = shadow_border_idx;
00266 }
00267 if (changeScoreAccordingToShadowBorderValue(x, y, 0, 1, border_scores_bottom_, border_scores_top_, shadow_border_idx))
00268 {
00269 shadow_border_indices = (shadow_border_indices==NULL ? new ShadowBorderIndices : shadow_border_indices);
00270 shadow_border_indices->bottom = shadow_border_idx;
00271 }
00272 }
00273 }
00274 }
00275
00277 float*
00278 RangeImageBorderExtractor::getAnglesImageForBorderDirections ()
00279 {
00280 calculateBorderDirections();
00281
00282 int width = range_image_->width,
00283 height = range_image_->height,
00284 array_size = width*height;
00285 float* angles_image = new float[array_size];
00286
00287 for (int y=0; y<height; ++y)
00288 {
00289 for (int x=0; x<width; ++x)
00290 {
00291 int index = y*width + x;
00292 float& angle = angles_image[index];
00293 angle = -std::numeric_limits<float>::infinity ();
00294 const Eigen::Vector3f* border_direction_ptr = border_directions_[index];
00295 if (border_direction_ptr == NULL)
00296 continue;
00297 const Eigen::Vector3f& border_direction = *border_direction_ptr;
00298 const PointWithRange& point = range_image_->getPoint(index);
00299
00300 float border_direction_in_image_x, border_direction_in_image_y;
00301 float tmp_factor = point.range*range_image_->getAngularResolution();
00302 range_image_->getImagePoint(point.x+tmp_factor*border_direction[0], point.y+tmp_factor*border_direction[1], point.z+tmp_factor*border_direction[2],
00303 border_direction_in_image_x, border_direction_in_image_y);
00304 border_direction_in_image_x -= static_cast<float> (x); border_direction_in_image_y -= static_cast<float> (y);
00305 angle = atan2f (border_direction_in_image_y, border_direction_in_image_x);
00306 }
00307 }
00308 return angles_image;
00309 }
00310
00312 float*
00313 RangeImageBorderExtractor::getAnglesImageForSurfaceChangeDirections ()
00314 {
00315
00316
00317 calculateSurfaceChanges();
00318
00319 int width = range_image_->width,
00320 height = range_image_->height,
00321 array_size = width*height;
00322 float* angles_image = new float[array_size];
00323
00324 for (int y=0; y<height; ++y)
00325 {
00326 for (int x=0; x<width; ++x)
00327 {
00328 int index = y*width + x;
00329 float& angle = angles_image[index];
00330 angle = -std::numeric_limits<float>::infinity ();
00331 float surface_change_score = surface_change_scores_[index];
00332 if (surface_change_score <= 0.1f)
00333 continue;
00334 const Eigen::Vector3f& direction = surface_change_directions_[index];
00335 const PointWithRange& point = range_image_->getPoint(index);
00336
00337 float border_direction_in_image_x, border_direction_in_image_y;
00338 float tmp_factor = point.range*range_image_->getAngularResolution();
00339 range_image_->getImagePoint(point.x+tmp_factor*direction[0], point.y+tmp_factor*direction[1], point.z+tmp_factor*direction[2],
00340 border_direction_in_image_x, border_direction_in_image_y);
00341 border_direction_in_image_x -= static_cast<float> (x); border_direction_in_image_y -= static_cast<float> (y);
00342 angle = atan2f (border_direction_in_image_y, border_direction_in_image_x);
00343 if (angle <= deg2rad (-90.0f))
00344 angle += static_cast<float> (M_PI);
00345 else if (angle > deg2rad (90.0f))
00346 angle -= static_cast<float> (M_PI);
00347 }
00348 }
00349 return (angles_image);
00350 }
00351
00352
00354 void
00355 RangeImageBorderExtractor::classifyBorders ()
00356 {
00357 if (border_descriptions_ != NULL)
00358 return;
00359
00360
00361 extractLocalSurfaceStructure();
00362
00363
00364 extractBorderScoreImages();
00365
00366
00367 updateScoresAccordingToNeighborValues();
00368
00369
00370 findAndEvaluateShadowBorders();
00371
00372 int width = range_image_->width,
00373 height = range_image_->height,
00374 size = width*height;
00375
00376 BorderDescription initial_border_description;
00377 initial_border_description.traits = 0;
00378 border_descriptions_ = new PointCloudOut;
00379 border_descriptions_->width = width;
00380 border_descriptions_->height = height;
00381 border_descriptions_->is_dense = true;
00382 border_descriptions_->points.resize(size, initial_border_description);
00383
00384 for (int y = 0; y < static_cast<int> (height); ++y)
00385 {
00386 for (int x = 0; x < static_cast<int> (width); ++x)
00387 {
00388 int index = y*width+x;
00389 BorderDescription& border_description = border_descriptions_->points[index];
00390 border_description.x = x;
00391 border_description.y = y;
00392 BorderTraits& border_traits = border_description.traits;
00393
00394 ShadowBorderIndices* shadow_border_indices = shadow_border_informations_[index];
00395 if (shadow_border_indices == NULL)
00396 continue;
00397
00398 int shadow_border_index = shadow_border_indices->left;
00399 if (shadow_border_index >= 0 && checkIfMaximum(x, y, -1, 0, border_scores_left_, shadow_border_index))
00400 {
00401 BorderTraits& shadow_traits = border_descriptions_->points[shadow_border_index].traits;
00402 border_traits[BORDER_TRAIT__OBSTACLE_BORDER] = border_traits[BORDER_TRAIT__OBSTACLE_BORDER_LEFT] = true;
00403 shadow_traits[BORDER_TRAIT__SHADOW_BORDER] = shadow_traits[BORDER_TRAIT__SHADOW_BORDER_RIGHT] = true;
00404 for (int index3=index-1; index3>shadow_border_index; --index3)
00405 {
00406 BorderTraits& veil_point = border_descriptions_->points[index3].traits;
00407 veil_point[BORDER_TRAIT__VEIL_POINT] = veil_point[BORDER_TRAIT__VEIL_POINT_RIGHT] = true;
00408 }
00409 }
00410
00411 shadow_border_index = shadow_border_indices->right;
00412 if (shadow_border_index >= 0 && checkIfMaximum(x, y, 1, 0, border_scores_right_, shadow_border_index))
00413 {
00414 BorderTraits& shadow_traits = border_descriptions_->points[shadow_border_index].traits;
00415 border_traits[BORDER_TRAIT__OBSTACLE_BORDER] = border_traits[BORDER_TRAIT__OBSTACLE_BORDER_RIGHT] = true;
00416 shadow_traits[BORDER_TRAIT__SHADOW_BORDER] = shadow_traits[BORDER_TRAIT__SHADOW_BORDER_LEFT] = true;
00417 for (int index3=index+1; index3<shadow_border_index; ++index3)
00418 {
00419 BorderTraits& veil_point = border_descriptions_->points[index3].traits;
00420 veil_point[BORDER_TRAIT__VEIL_POINT] = veil_point[BORDER_TRAIT__VEIL_POINT_LEFT] = true;
00421 }
00422 }
00423
00424 shadow_border_index = shadow_border_indices->top;
00425 if (shadow_border_index >= 0 && checkIfMaximum(x, y, 0, -1, border_scores_top_, shadow_border_index))
00426 {
00427 BorderTraits& shadow_traits = border_descriptions_->points[shadow_border_index].traits;
00428 border_traits[BORDER_TRAIT__OBSTACLE_BORDER] = border_traits[BORDER_TRAIT__OBSTACLE_BORDER_TOP] = true;
00429 shadow_traits[BORDER_TRAIT__SHADOW_BORDER] = shadow_traits[BORDER_TRAIT__SHADOW_BORDER_BOTTOM] = true;
00430 for (int index3=index-width; index3>shadow_border_index; index3-=width)
00431 {
00432
00433 BorderTraits& veil_point = border_descriptions_->points[index3].traits;
00434 veil_point[BORDER_TRAIT__VEIL_POINT] = veil_point[BORDER_TRAIT__VEIL_POINT_BOTTOM] = true;
00435 }
00436 }
00437
00438 shadow_border_index = shadow_border_indices->bottom;
00439 if (shadow_border_index >= 0 && checkIfMaximum(x, y, 0, 1, border_scores_bottom_, shadow_border_index))
00440 {
00441 BorderTraits& shadow_traits = border_descriptions_->points[shadow_border_index].traits;
00442 border_traits[BORDER_TRAIT__OBSTACLE_BORDER] = border_traits[BORDER_TRAIT__OBSTACLE_BORDER_BOTTOM] = true;
00443 shadow_traits[BORDER_TRAIT__SHADOW_BORDER] = shadow_traits[BORDER_TRAIT__SHADOW_BORDER_TOP] = true;
00444 for (int index3=index+width; index3<shadow_border_index; index3+=width)
00445 {
00446
00447 BorderTraits& veil_point = border_descriptions_->points[index3].traits;
00448 veil_point[BORDER_TRAIT__VEIL_POINT] = veil_point[BORDER_TRAIT__VEIL_POINT_TOP] = true;
00449 }
00450 }
00451
00452
00453
00454
00455
00456 }
00457 }
00458 }
00459
00461 void
00462 RangeImageBorderExtractor::calculateBorderDirections ()
00463 {
00464 if (border_directions_!=NULL)
00465 return;
00466 classifyBorders();
00467
00468
00469
00470 int width = range_image_->width,
00471 height = range_image_->height,
00472 size = width*height;
00473 border_directions_ = new Eigen::Vector3f*[size];
00474 for (int y=0; y<height; ++y)
00475 {
00476 for (int x=0; x<width; ++x)
00477 {
00478 calculateBorderDirection(x, y);
00479 }
00480 }
00481
00482 Eigen::Vector3f** average_border_directions = new Eigen::Vector3f*[size];
00483 int radius = parameters_.pixel_radius_border_direction;
00484 int minimum_weight = radius+1;
00485 float min_cos_angle=cosf(deg2rad(120.0f));
00486 for (int y=0; y<height; ++y)
00487 {
00488 for (int x=0; x<width; ++x)
00489 {
00490 int index = y*width + x;
00491 Eigen::Vector3f*& average_border_direction = average_border_directions[index];
00492 average_border_direction = NULL;
00493 const Eigen::Vector3f* border_direction = border_directions_[index];
00494 if (border_direction==NULL)
00495 continue;
00496 average_border_direction = new Eigen::Vector3f(*border_direction);
00497 float weight_sum = 1.0f;
00498 for (int y2=(std::max)(0, y-radius); y2<=(std::min)(y+radius, height-1); ++y2)
00499 {
00500 for (int x2=(std::max)(0, x-radius); x2<=(std::min)(x+radius, width-1); ++x2)
00501 {
00502 int index2 = y2*width + x2;
00503 const Eigen::Vector3f* neighbor_border_direction = border_directions_[index2];
00504 if (neighbor_border_direction==NULL || index2==index)
00505 continue;
00506
00507
00508 float cos_angle = neighbor_border_direction->dot(*border_direction);
00509 if (cos_angle<min_cos_angle)
00510 {
00511
00512 continue;
00513 }
00514
00515
00516
00517
00518 float border_between_points_score = getNeighborDistanceChangeScore(*surface_structure_[index], x, y, x2-x, y2-y, 1);
00519 if (fabsf(border_between_points_score) >= 0.95f*parameters_.minimum_border_probability)
00520 continue;
00521
00522 *average_border_direction += *neighbor_border_direction;
00523 weight_sum += 1.0f;
00524 }
00525 }
00526 if (pcl_lrint (weight_sum) < minimum_weight)
00527 {
00528 delete average_border_direction;
00529 average_border_direction=NULL;
00530 }
00531 else
00532 average_border_direction->normalize();
00533 }
00534 }
00535
00536 for (int i=0; i<size; ++i)
00537 delete border_directions_[i];
00538 delete[] border_directions_;
00539 border_directions_ = average_border_directions;
00540 }
00541
00543 void
00544 RangeImageBorderExtractor::calculateSurfaceChanges ()
00545 {
00546 if (surface_change_scores_!=NULL)
00547 return;
00548
00549 calculateBorderDirections();
00550
00551
00552
00553 int width = range_image_->width,
00554 height = range_image_->height,
00555 size = width*height;
00556 surface_change_scores_ = new float[size];
00557 surface_change_directions_ = new Eigen::Vector3f[size];
00558 # pragma omp parallel for num_threads(parameters_.max_no_of_threads) default(shared) schedule(dynamic, 10)
00559 for (int y=0; y<height; ++y)
00560 {
00561 for (int x=0; x<width; ++x)
00562 {
00563 int index = y*width + x;
00564 float& surface_change_score = surface_change_scores_[index];
00565 surface_change_score = 0.0f;
00566 Eigen::Vector3f& surface_change_direction = surface_change_directions_[index];
00567 surface_change_direction.setZero();
00568
00569 const BorderTraits& border_traits = border_descriptions_->points[index].traits;
00570 if (border_traits[BORDER_TRAIT__VEIL_POINT] || border_traits[BORDER_TRAIT__SHADOW_BORDER])
00571 continue;
00572 if (border_directions_[index]!=NULL)
00573 {
00574 surface_change_score = 1.0f;
00575 surface_change_direction = *border_directions_[index];
00576 }
00577 else
00578 {
00579 if (!calculateMainPrincipalCurvature(x, y, parameters_.pixel_radius_principal_curvature,
00580 surface_change_score, surface_change_direction))
00581 {
00582 surface_change_score = 0.0f;
00583 continue;
00584 }
00585 }
00586 }
00587 }
00588
00589 }
00590
00592 void
00593 RangeImageBorderExtractor::blurSurfaceChanges ()
00594 {
00595 int blur_radius = 1;
00596 if (blur_radius==0)
00597 return;
00598
00599 const RangeImage& range_image = *range_image_;
00600
00601 Eigen::Vector3f* blurred_directions = new Eigen::Vector3f[range_image.width*range_image.height];
00602 float* blurred_scores = new float[range_image.width*range_image.height];
00603 for (int y=0; y<int(range_image.height); ++y)
00604 {
00605 for (int x=0; x<int(range_image.width); ++x)
00606 {
00607 int index = y*range_image.width + x;
00608 Eigen::Vector3f& new_point = blurred_directions[index];
00609 new_point.setZero();
00610 float& new_score = blurred_scores[index];
00611 new_score = 0.0f;
00612 if (!range_image.isValid(index))
00613 continue;
00614 const BorderTraits& border_traits = border_descriptions_->points[index].traits;
00615 if (border_traits[BORDER_TRAIT__VEIL_POINT] || border_traits[BORDER_TRAIT__SHADOW_BORDER])
00616 continue;
00617 const Eigen::Vector3f& point = surface_change_directions_[index];
00618 float counter = 0.0f;
00619 for (int y2=y-blur_radius; y2<y+blur_radius; ++y2)
00620 {
00621 for (int x2=x-blur_radius; x2<x+blur_radius; ++x2)
00622 {
00623 if (!range_image.isInImage(x2,y2))
00624 continue;
00625 int index2 = y2*range_image.width + x2;
00626 float score = surface_change_scores_[index2];
00627
00628
00629
00630 if (score > 0.0f)
00631 {
00632 Eigen::Vector3f& neighbor = surface_change_directions_[index2];
00633
00634
00635 if (point.dot(neighbor)<0.0f)
00636 neighbor *= -1.0f;
00637 new_point += score*neighbor;
00638 }
00639 new_score += score;
00640 counter += 1.0f;
00641 }
00642 }
00643 new_point.normalize();
00644 if (counter > 0.0f)
00645 new_score /= counter;
00646 }
00647 }
00648 delete[] surface_change_directions_;
00649 surface_change_directions_ = blurred_directions;
00650 delete[] surface_change_scores_;
00651 surface_change_scores_ = blurred_scores;
00652 }
00653
00655 void
00656 RangeImageBorderExtractor::computeFeature (PointCloudOut& output)
00657 {
00658 output.points.clear();
00659
00660 if (indices_)
00661 {
00662 std::cerr << __PRETTY_FUNCTION__
00663 << ": Sorry, usage of indices for the extraction is not supported for range image border extraction (yet).\n\n";
00664 output.width = output.height = 0;
00665 output.points.clear ();
00666 return;
00667 }
00668
00669 if (range_image_==NULL)
00670 {
00671 std::cerr << __PRETTY_FUNCTION__
00672 << ": RangeImage is not set. Sorry, the border extraction works on range images, not on normal point clouds."
00673 << " Use setRangeImage(...).\n\n";
00674 output.width = output.height = 0;
00675 output.points.clear ();
00676 return;
00677 }
00678 output = getBorderDescriptions ();
00679 }
00680
00682 void
00683 RangeImageBorderExtractor::compute (PointCloudOut& output)
00684 {
00685 computeFeature (output);
00686 }
00687
00688 }