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
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 #ifndef SHAPE_RECONSTRUCTION_RANGE_IMAGE_PLANAR_IMPL
00049 #define SHAPE_RECONSTRUCTION_RANGE_IMAGE_PLANAR_IMPL
00050
00051 #include "shape_reconstruction/RangeImagePlanar.h"
00052
00053 #include <opencv2/core/core.hpp>
00054
00055 namespace shape_reconstruction {
00056
00057 template <typename PointCloudType> void
00058 RangeImagePlanar::doZBufferAndStorePoints (const PointCloudType& point_cloud,
00059 float noise_level, float min_range, int& top, int& right, int& bottom, int& left)
00060 {
00061 typedef typename PointCloudType::PointType PointType2;
00062 const typename pcl::PointCloud<PointType2>::VectorType &points2 = point_cloud.points;
00063
00064 unsigned int size = width*height;
00065 int* counters = new int[size];
00066 ERASE_ARRAY (counters, size);
00067
00068 resetPointIndex(width, height);
00069
00070 top=height; right=-1; bottom=-1; left=width;
00071
00072 float x_real, y_real, range_of_current_point;
00073 int x, y;
00074 int idx=0;
00075
00076 for (typename pcl::PointCloud<PointType2>::VectorType::const_iterator it=points2.begin (); it!=points2.end (); ++it, ++idx)
00077 {
00078 if (!isFinite (*it))
00079 continue;
00080 pcl::Vector3fMapConst current_point = it->getVector3fMap ();
00081
00082 this->getImagePoint (current_point, x_real, y_real, range_of_current_point);
00083 this->real2DToInt2D (x_real, y_real, x, y);
00084
00085 if (range_of_current_point < min_range|| !isInImage (x, y))
00086 continue;
00087
00088
00089
00090 int floor_x = pcl_lrint (floor (x_real)), floor_y = pcl_lrint (floor (y_real)),
00091 ceil_x = pcl_lrint (ceil (x_real)), ceil_y = pcl_lrint (ceil (y_real));
00092
00093 int neighbor_x[4], neighbor_y[4];
00094 neighbor_x[0]=floor_x; neighbor_y[0]=floor_y;
00095 neighbor_x[1]=floor_x; neighbor_y[1]=ceil_y;
00096 neighbor_x[2]=ceil_x; neighbor_y[2]=floor_y;
00097 neighbor_x[3]=ceil_x; neighbor_y[3]=ceil_y;
00098
00099
00100 for (int i=0; i<4; ++i)
00101 {
00102 int n_x=neighbor_x[i], n_y=neighbor_y[i];
00103
00104 if (n_x==x && n_y==y)
00105 continue;
00106 if (isInImage (n_x, n_y))
00107 {
00108 int neighbor_array_pos = n_y*width + n_x;
00109 if (counters[neighbor_array_pos]==0)
00110 {
00111 float& neighbor_range = points[neighbor_array_pos].range;
00112
00113 top= (std::min) (top, n_y); right= (std::max) (right, n_x); bottom= (std::max) (bottom, n_y); left= (std::min) (left, n_x);
00114
00115 if (pcl_isinf (neighbor_range) || range_of_current_point < neighbor_range) {
00116 neighbor_range = range_of_current_point;
00117 setPointIndex(n_x, n_y, idx);
00118 }
00119
00120
00121
00122
00123 }
00124 }
00125 }
00126
00127
00128
00129 int arrayPos = y*width + x;
00130 float& range_at_image_point = points[arrayPos].range;
00131 int& counter = counters[arrayPos];
00132 bool addCurrentPoint=false, replace_with_current_point=false;
00133
00134 if (counter==0)
00135 {
00136 replace_with_current_point = true;
00137 }
00138 else
00139 {
00140 if (range_of_current_point < range_at_image_point-noise_level)
00141 {
00142 replace_with_current_point = true;
00143 }
00144 else if (fabs (range_of_current_point-range_at_image_point)<=noise_level)
00145 {
00146 addCurrentPoint = true;
00147 }
00148 }
00149
00150 if (replace_with_current_point)
00151 {
00152
00153
00154
00155
00156
00157
00158
00159
00160 counter = 1;
00161 range_at_image_point = range_of_current_point;
00162 top= (std::min) (top, y); right= (std::max) (right, x); bottom= (std::max) (bottom, y); left= (std::min) (left, x);
00163
00164 setPointIndex(x, y, idx);
00165 }
00166 else if (addCurrentPoint)
00167 {
00168 ++counter;
00169 range_at_image_point += (range_of_current_point-range_at_image_point)/counter;
00170
00171 }
00172
00173 }
00174 delete[] counters;
00175 }
00176
00178 template <typename PointCloudType> void
00179 RangeImagePlanar::createFromPointCloudWithFixedSizeAndStorePoints(const PointCloudType& point_cloud,
00180 int di_width, int di_height,
00181 float di_center_x, float di_center_y,
00182 float di_focal_length_x, float di_focal_length_y,
00183 const Eigen::Affine3f& sensor_pose,
00184 CoordinateFrame coordinate_frame, float noise_level,
00185 float min_range)
00186 {
00187
00188
00189 width = di_width;
00190 height = di_height;
00191 center_x_ = di_center_x;
00192 center_y_ = di_center_y;
00193 focal_length_x_ = di_focal_length_x;
00194 focal_length_y_ = di_focal_length_y;
00195 focal_length_x_reciprocal_ = 1 / focal_length_x_;
00196 focal_length_y_reciprocal_ = 1 / focal_length_y_;
00197
00198 is_dense = false;
00199
00200 getCoordinateFrameTransformation (coordinate_frame, to_world_system_);
00201 to_world_system_ = sensor_pose * to_world_system_;
00202
00203 to_range_image_system_ = to_world_system_.inverse (Eigen::Isometry);
00204
00205 unsigned int size = width*height;
00206 points.clear ();
00207 points.resize (size, unobserved_point);
00208
00209 int top=height, right=-1, bottom=-1, left=width;
00210
00211 doZBufferAndStorePoints (point_cloud, noise_level, min_range, top, right, bottom, left);
00212
00213
00214
00215 recalculate3DPointPositions ();
00216 }
00217
00219
00220 template <typename PointCloudType> void
00221 RangeImagePlanar::computeZandMatchingPoints (const PointCloudType& point_cloud,
00222
00223 float min_range,
00224 const cv::Mat& matching_im, const float matching_im_min_range,
00225 pcl::PointIndicesPtr& matching_indices_in_pc,
00226 pcl::PointIndicesPtr& matching_indices_in_matching_im,
00227 pcl::PointIndicesPtr& indices_to_remove,
00228 int height, int width)
00229 {
00230 assert (height == matching_im.rows);
00231 assert (width == matching_im.cols);
00232 assert (matching_indices_in_pc);
00233 assert (matching_indices_in_matching_im);
00234 assert (indices_to_remove);
00235 assert (matching_im.type() == CV_32FC1);
00236
00237
00238 pcl::PointIndicesPtr occluded_indices(new pcl::PointIndices);
00239
00240 int top=height;
00241 int right=-1;
00242 int bottom=-1;
00243 int left=width;
00244
00245 typedef typename PointCloudType::PointType PointType2;
00246 const typename pcl::PointCloud<PointType2>::VectorType &points2 = point_cloud.points;
00247
00248 unsigned int size = width*height;
00249 int* counters = new int[size];
00250 ERASE_ARRAY (counters, size);
00251
00252 std::vector<bool> removal_candidates(points2.size(), true);
00253 std::vector<bool> matching_in_matching_m(size, false);
00254
00255 top=height; right=-1; bottom=-1; left=width;
00256
00257 float x_real, y_real, range_of_current_point;
00258 int x, y;
00259 int idx=0;
00260 int matching_im_idx=0;
00261 for (typename pcl::PointCloud<PointType2>::VectorType::const_iterator it=points2.begin (); it!=points2.end (); ++it, ++idx)
00262 {
00263 if (!isFinite (*it)) {
00264 ROS_ERROR_STREAM_NAMED("RangeImagePlanar.computeZandMatchingPoints", "Error! Point " << idx << " is NaN!");
00265 throw 0;
00266
00267 }
00268
00269 pcl::Vector3fMapConst current_point = it->getVector3fMap ();
00270
00271 this->getImagePoint (current_point, x_real, y_real, range_of_current_point);
00272 this->real2DToInt2D (x_real, y_real, x, y);
00273
00274 if (range_of_current_point < min_range|| !isInImage (x, y)) {
00275 removal_candidates[idx] = false;
00276 occluded_indices->indices.push_back(idx);
00277 continue;
00278 }
00279
00280
00281 Eigen::Vector3f current_point_z;
00282 calculate3DPoint(x, y, range_of_current_point, current_point_z);
00283
00284
00285 float m_im_z = matching_im.at< float >(y,x);
00286 matching_im_idx = y*width+x;
00287
00288
00289
00290
00291 int floor_x = pcl_lrint (floor (x_real)), floor_y = pcl_lrint (floor (y_real)),
00292 ceil_x = pcl_lrint (ceil (x_real)), ceil_y = pcl_lrint (ceil (y_real));
00293 int neighbor_x[4], neighbor_y[4];
00294 neighbor_x[0]=floor_x; neighbor_y[0]=floor_y;
00295 neighbor_x[1]=floor_x; neighbor_y[1]=ceil_y;
00296 neighbor_x[2]=ceil_x; neighbor_y[2]=floor_y;
00297 neighbor_x[3]=ceil_x; neighbor_y[3]=ceil_y;
00298
00299 for (int i=0; i<4; ++i)
00300 {
00301 int n_x=neighbor_x[i], n_y=neighbor_y[i];
00302 if (n_x==x && n_y==y)
00303 continue;
00304
00305
00306
00307
00308
00309 if (!isInImage (n_x, n_y)) {
00310 continue;
00311 }
00312 float n_m_im_z = matching_im.at< float >(n_y,n_x);
00313
00314
00315 if (isnan(n_m_im_z)) {
00316 continue;
00317 }
00318
00319
00320
00321 if ( fabs(n_m_im_z - current_point_z[2]) < matching_im_min_range) {
00322 removal_candidates[idx] = false;
00323
00324 matching_im_idx = n_y*width+n_x;
00325
00326 if (!matching_in_matching_m[matching_im_idx]) {
00327 matching_indices_in_matching_im->indices.push_back(matching_im_idx);
00328 matching_in_matching_m[matching_im_idx] = true;
00329 }
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340 }
00341
00342
00343
00344 }
00345 if (removal_candidates[idx] == false) {
00346
00347 matching_indices_in_pc->indices.push_back(idx);
00348
00349 continue;
00350 }
00351
00352
00353 if (isnan(m_im_z)) {
00354 removal_candidates[idx] = false;
00355 occluded_indices->indices.push_back(idx);
00356 continue;
00357 }
00358
00359
00360 if ( fabs(m_im_z - current_point_z[2]) < matching_im_min_range) {
00361
00362 removal_candidates[idx] = false;
00363 matching_indices_in_pc->indices.push_back(idx);
00364 matching_indices_in_matching_im->indices.push_back(matching_im_idx);
00365 continue;
00366 }
00367
00368
00369
00370 if ( m_im_z < current_point_z[2] ) {
00371 removal_candidates[idx] = false;
00372 occluded_indices->indices.push_back(idx);
00373 continue;
00374 }
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418 }
00419
00420
00421 for (int i = 0; i < points2.size(); i++) {
00422 if (removal_candidates[i]) {
00423 indices_to_remove->indices.push_back(i);
00424 }
00425 }
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445 delete[] counters;
00446
00447 }
00448
00449
00450 template <typename PointCloudType> void
00451 RangeImagePlanar::matchPointCloudAndImage (const PointCloudType& point_cloud,
00452 int di_width, int di_height,
00453 float di_center_x, float di_center_y,
00454 float di_focal_length_x, float di_focal_length_y,
00455 const Eigen::Affine3f& sensor_pose,
00456 CoordinateFrame coordinate_frame,
00457 const cv::Mat& matching_im, const float matching_im_min_range,
00458 pcl::PointIndicesPtr& matching_indices,
00459 pcl::PointIndicesPtr& matching_indices_in_matching_im,
00460 pcl::PointIndicesPtr& indices_to_remove,
00461 float min_range
00462 )
00463 {
00464
00465
00466 width = di_width;
00467 height = di_height;
00468 center_x_ = di_center_x;
00469 center_y_ = di_center_y;
00470 focal_length_x_ = di_focal_length_x;
00471 focal_length_y_ = di_focal_length_y;
00472 focal_length_x_reciprocal_ = 1 / focal_length_x_;
00473 focal_length_y_reciprocal_ = 1 / focal_length_y_;
00474
00475 is_dense = false;
00476
00477 getCoordinateFrameTransformation (coordinate_frame, to_world_system_);
00478 to_world_system_ = sensor_pose * to_world_system_;
00479
00480 to_range_image_system_ = to_world_system_.inverse (Eigen::Isometry);
00481
00482 unsigned int size = width*height;
00483 points.clear ();
00484 points.resize (size, unobserved_point);
00485
00486 computeZandMatchingPoints (point_cloud,
00487 min_range,
00488 matching_im,
00489 matching_im_min_range,
00490 matching_indices,
00491 matching_indices_in_matching_im,
00492 indices_to_remove,
00493 height, width);
00494
00495 }
00496
00497
00498 }
00499
00500 #endif