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 #include "pcl/features/integral_image_normal.h"
00037
00038 #include "pcl/win32_macros.h"
00039
00040 #define SQR(a) ((a)*(a))
00041
00043 pcl::IntegralImageNormalEstimation::IntegralImageNormalEstimation ()
00044 : integral_image_x_(NULL),
00045 integral_image_y_(NULL),
00046 diff_x_(NULL),
00047 diff_y_(NULL),
00048 depth_data_(NULL)
00049 {
00050 }
00051
00053 pcl::IntegralImageNormalEstimation::~IntegralImageNormalEstimation ()
00054 {
00055 if (integral_image_x_ != NULL) delete integral_image_x_;
00056 if (integral_image_y_ != NULL) delete integral_image_y_;
00057 if (diff_x_ != NULL) delete diff_x_;
00058 if (diff_y_ != NULL) delete diff_y_;
00059 if (depth_data_ != NULL) delete depth_data_;
00060 }
00061
00063 void
00064 pcl::IntegralImageNormalEstimation::setInputData (
00065 float * data,
00066 const int width, const int height,
00067 const int dimensions, const int element_stride,
00068 const int row_stride, const float distance_threshold)
00069 {
00070 data_ = data;
00071 width_ = width;
00072 height_ = height;
00073 dimensions_ = dimensions;
00074 element_stride_ = element_stride;
00075 row_stride_ = row_stride;
00076
00077 distance_threshold_ = distance_threshold;
00078
00079
00080 if (diff_x_ != NULL) delete diff_x_;
00081 if (diff_y_ != NULL) delete diff_y_;
00082 if (depth_data_ != NULL) delete depth_data_;
00083
00084 diff_x_ = new float[4*width_*height_];
00085 diff_y_ = new float[4*width_*height_];
00086
00087 depth_data_ = new float[width_*height_];
00088
00089 memset(diff_x_, 0, sizeof(float)*4*width_*height_);
00090 memset(diff_y_, 0, sizeof(float)*4*width_*height_);
00091
00092
00093
00094 for (int row_index = 0; row_index < height_; ++row_index)
00095 {
00096 float * data_pointer = data_ + row_index*row_stride_;
00097
00098 float * diff_x_pointer = diff_x_ + row_index*4*width_;
00099 float * diff_y_pointer = diff_y_ + row_index*4*width_;
00100
00101 for (int col_index = 0; col_index < width_; ++col_index)
00102 {
00103 depth_data_[row_index*width_ + col_index] = data_pointer[2];
00104
00105 diff_x_pointer[3] = 1;
00106 diff_y_pointer[3] = 1;
00107
00108 data_pointer += element_stride_;
00109 diff_x_pointer += 4;
00110 diff_y_pointer += 4;
00111 }
00112 }
00113
00114 for (int row_index = 1; row_index < height_-1; ++row_index)
00115 {
00116 float * data_pointer_y_up = data_ + (row_index-1)*row_stride_ + element_stride_;
00117 float * data_pointer_y_down = data_ + (row_index+1)*row_stride_ + element_stride_;
00118 float * data_pointer_x_left = data_ + row_index*row_stride_;
00119 float * data_pointer_x_right = data_ + row_index*row_stride_ + 2*element_stride_;
00120
00121 float * diff_x_pointer = diff_x_ + row_index*4*width_ + 4;
00122 float * diff_y_pointer = diff_y_ + row_index*4*width_ + 4;
00123
00124 for (int col_index = 1; col_index < width_-1; ++col_index)
00125 {
00126 if (pcl_isfinite (data_pointer_x_right[0]) && pcl_isfinite (data_pointer_x_left[0]))
00127 {
00128 diff_x_pointer[0] = data_pointer_x_right[0]-data_pointer_x_left[0];
00129 diff_x_pointer[1] = data_pointer_x_right[1]-data_pointer_x_left[1];
00130 diff_x_pointer[2] = data_pointer_x_right[2]-data_pointer_x_left[2];
00131
00132
00133 const float l_lengthX = fabs(diff_x_pointer[2]);
00134
00135
00136
00137
00138 if (l_lengthX < distance_threshold)
00139 {
00140 diff_x_pointer[3] = 0;
00141 }
00142
00143
00144
00145
00146
00147 }
00148
00149 if (pcl_isfinite (data_pointer_y_down[0]) && pcl_isfinite (data_pointer_y_up[0]))
00150 {
00151 diff_y_pointer[0] = data_pointer_y_down[0]-data_pointer_y_up[0];
00152 diff_y_pointer[1] = data_pointer_y_down[1]-data_pointer_y_up[1];
00153 diff_y_pointer[2] = data_pointer_y_down[2]-data_pointer_y_up[2];
00154
00155
00156 const float l_lengthY = fabs(diff_y_pointer[2]);
00157
00158
00159 if (l_lengthY < distance_threshold)
00160 {
00161 diff_y_pointer[3] = 0;
00162 }
00163 }
00164
00165 diff_x_pointer += 4;
00166 diff_y_pointer += 4;
00167
00168 data_pointer_y_up += element_stride_;
00169 data_pointer_y_down += element_stride_;
00170 data_pointer_x_left += element_stride_;
00171 data_pointer_x_right += element_stride_;
00172 }
00173 }
00174
00175
00176
00177 integral_image_x_ = new ::pcl::IntegralImage2D<float, float>(
00178 diff_x_,
00179 width_,
00180 height_,
00181 4,
00182 false,
00183 4,
00184 4*width_ );
00185
00186 integral_image_y_ = new ::pcl::IntegralImage2D<float, float>(
00187 diff_y_,
00188 width_,
00189 height_,
00190 4,
00191 false,
00192 4,
00193 4*width_ );
00194 }
00195
00196
00198 void
00199 pcl::IntegralImageNormalEstimation::setRectSize (const int width, const int height)
00200 {
00201 rect_width_ = width;
00202 rect_height_ = height;
00203 }
00204
00206 pcl::Normal
00207 pcl::IntegralImageNormalEstimation::compute (const int pos_x, const int pos_y)
00208 {
00209 const float threshold_violation_count_x = integral_image_x_->getSum(pos_x-rect_width_/2, pos_y-rect_height_/2, rect_width_, rect_height_, 3);
00210 const float threshold_violation_count_y = integral_image_y_->getSum(pos_x-rect_width_/2, pos_y-rect_height_/2, rect_width_, rect_height_, 3);
00211
00212
00213
00214
00215 if (threshold_violation_count_x < 1.0f && threshold_violation_count_y < 1.0f)
00216 {
00217 const float mean_x_x = integral_image_x_->getSum(pos_x-rect_width_/2, pos_y-rect_height_/2, rect_width_, rect_height_, 0);
00218 const float mean_x_y = integral_image_x_->getSum(pos_x-rect_width_/2, pos_y-rect_height_/2, rect_width_, rect_height_, 1);
00219 const float mean_x_z = integral_image_x_->getSum(pos_x-rect_width_/2, pos_y-rect_height_/2, rect_width_, rect_height_, 2);
00220
00221 const float mean_y_x = integral_image_y_->getSum(pos_x-rect_width_/2, pos_y-rect_height_/2, rect_width_, rect_height_, 0);
00222 const float mean_y_y = integral_image_y_->getSum(pos_x-rect_width_/2, pos_y-rect_height_/2, rect_width_, rect_height_, 1);
00223 const float mean_y_z = integral_image_y_->getSum(pos_x-rect_width_/2, pos_y-rect_height_/2, rect_width_, rect_height_, 2);
00224
00225 const float normal_x = mean_x_y * mean_y_z - mean_x_z * mean_y_y;
00226 const float normal_y = mean_x_z * mean_y_x - mean_x_x * mean_y_z;
00227 const float normal_z = mean_x_x * mean_y_y - mean_x_y * mean_y_x;
00228
00229 const float normal_length = sqrt(SQR(normal_x) + SQR(normal_y) + SQR(normal_z));
00230
00231 if (normal_length == 0.0f)
00232 {
00233 pcl::Normal normal;
00234 normal.normal_x = 0.0f;
00235 normal.normal_y = 0.0f;
00236 normal.normal_z = 0.0f;
00237 normal.curvature = 0.0f;
00238
00239 return normal;
00240 }
00241
00242 const float scale = -1.0f/normal_length;
00243
00244 pcl::Normal normal;
00245 normal.normal_x = normal_x*scale;
00246 normal.normal_y = normal_y*scale;
00247 normal.normal_z = normal_z*scale;
00248 normal.curvature = 0.0f;
00249
00250 return normal;
00251 }
00252 else
00253 {
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292 }
00293
00294 pcl::Normal normal;
00295 normal.normal_x = 0.0f;
00296 normal.normal_y = 0.0f;
00297 normal.normal_z = 0.0f;
00298 normal.curvature = 0.0f;
00299
00300 return normal;
00301 }
00302