00001
00002 #include "sdet_nonmax_suppression.h"
00003
00004
00005 #include <vcl_cstdlib.h>
00006 #include <vsol/vsol_point_2d.h>
00007 #include <vsol/vsol_line_2d.h>
00008 #include <vgl/vgl_point_2d.h>
00009 #include <vnl/vnl_matrix.h>
00010 #include <vnl/algo/vnl_svd.h>
00011 #include <vgl/vgl_homg_point_2d.h>
00012 #include <vgl/algo/vgl_homg_operators_2d.h>
00013 #include <vcl_cassert.h>
00014
00015
00016
00017
00018
00019
00020
00021
00022 sdet_nonmax_suppression::sdet_nonmax_suppression(sdet_nonmax_suppression_params& nsp,
00023 vbl_array_2d<double> &grad_x,
00024 vbl_array_2d<double> &grad_y)
00025 : sdet_nonmax_suppression_params(nsp)
00026 {
00027 width_ = grad_x.rows();
00028 height_ = grad_x.cols();
00029 grad_x_.resize(width_, height_);
00030 grad_y_.resize(width_, height_);
00031 grad_mag_.resize(width_, height_);
00032 grad_x_ = grad_x;
00033 grad_y_ = grad_y;
00034
00035 for (int j = 0; j < height_; j++)
00036 {
00037 for (int i = 0; i < width_; i++)
00038 {
00039 double val = vcl_sqrt(vcl_pow(grad_x_(i,j),2.0) + vcl_pow(grad_y_(i,j),2.0));
00040 grad_mag_(i,j) = val;
00041 if (val > max_grad_mag_)
00042 max_grad_mag_ = val;
00043 }
00044 }
00045 points_valid_ = false;
00046 parabola_fit_type_ = nsp.pfit_type_;
00047 }
00048
00049
00050
00051 sdet_nonmax_suppression::sdet_nonmax_suppression(sdet_nonmax_suppression_params& nsp,
00052 vbl_array_2d<double> &dir_x,
00053 vbl_array_2d<double> &dir_y,
00054 vbl_array_2d<double> &grad_mag)
00055 : sdet_nonmax_suppression_params(nsp)
00056 {
00057 width_ = grad_mag.rows();
00058 height_ = grad_mag.cols();
00059 grad_x_.resize(width_, height_);
00060 grad_y_.resize(width_, height_);
00061 grad_mag_.resize(width_, height_);
00062 grad_x_ = dir_x;
00063 grad_y_ = dir_y;
00064 grad_mag_ = grad_mag;
00065
00066 for (int j = 0; j < height_; j++)
00067 {
00068 for (int i = 0; i < width_; i++)
00069 {
00070 double val = grad_mag_(i,j);
00071 if (val > max_grad_mag_)
00072 max_grad_mag_ = val;
00073 }
00074 }
00075 points_valid_ = false;
00076 parabola_fit_type_ = nsp.pfit_type_;
00077 }
00078
00079
00080
00081 sdet_nonmax_suppression::sdet_nonmax_suppression(sdet_nonmax_suppression_params& nsp,
00082 vbl_array_2d<double> &grad_mag,
00083 vbl_array_2d<vgl_vector_2d <double> > &directions)
00084 : sdet_nonmax_suppression_params(nsp)
00085 {
00086 width_ = grad_mag.rows();
00087 height_ = grad_mag.cols();
00088 grad_x_.resize(width_, height_);
00089 grad_y_.resize(width_, height_);
00090 grad_mag_.resize(width_, height_);
00091 grad_mag_ = grad_mag;
00092 for (int j = 0; j < height_; j++)
00093 {
00094 for (int i = 0; i < width_; i++)
00095 {
00096 vgl_vector_2d<double> direction = directions(i,j);
00097 normalize(direction);
00098 grad_x_(i,j) = grad_mag_(i,j) * direction.x();
00099 grad_y_(i,j) = grad_mag_(i,j) * direction.y();
00100 double val = grad_mag_(i,j);
00101 if (val > max_grad_mag_)
00102 max_grad_mag_ = val;
00103 }
00104 }
00105 points_valid_ = false;
00106 parabola_fit_type_ = nsp.pfit_type_;
00107 }
00108
00109
00110
00111 sdet_nonmax_suppression::sdet_nonmax_suppression(sdet_nonmax_suppression_params& nsp,
00112 vil_image_view<double> &grad_x,
00113 vil_image_view<double> &grad_y)
00114 : sdet_nonmax_suppression_params(nsp)
00115 {
00116 width_ = grad_x.ni();
00117 height_ = grad_x.nj();
00118 grad_x_.resize(width_, height_);
00119 grad_y_.resize(width_, height_);
00120 grad_mag_.resize(width_, height_);
00121
00122 for (int j = 0; j < height_; j++)
00123 {
00124 for (int i = 0; i < width_; i++)
00125 {
00126 double val_x = grad_x(i,j);
00127 double val_y = grad_y(i,j);
00128 grad_x_(i,j) = val_x;
00129 grad_y_(i,j) = val_y;
00130 double val = vcl_sqrt(vcl_pow(val_x,2.0) + vcl_pow(val_y,2.0));
00131 grad_mag_(i,j) = val;
00132 if (val > max_grad_mag_)
00133 max_grad_mag_ = val;
00134 }
00135 }
00136 points_valid_ = false;
00137 parabola_fit_type_ = nsp.pfit_type_;
00138 }
00139
00140
00141
00142 sdet_nonmax_suppression::sdet_nonmax_suppression(sdet_nonmax_suppression_params& nsp,
00143 vil_image_view<double> &dir_x,
00144 vil_image_view<double> &dir_y,
00145 vil_image_view<double> &grad_mag)
00146 : sdet_nonmax_suppression_params(nsp)
00147 {
00148 width_ = grad_mag.ni();
00149 height_ = grad_mag.nj();
00150 grad_x_.resize(width_, height_);
00151 grad_y_.resize(width_, height_);
00152 grad_mag_.resize(width_, height_);
00153
00154 for (int j = 0; j < height_; j++)
00155 {
00156 for (int i = 0; i < width_; i++)
00157 {
00158 grad_x_(i,j) = dir_x(i,j);
00159 grad_y_(i,j) = dir_y(i,j);
00160 double val = grad_mag(i,j);
00161 grad_mag_(i,j) = val;
00162 if (val > max_grad_mag_)
00163 max_grad_mag_ = val;
00164 }
00165 }
00166 points_valid_ = false;
00167 parabola_fit_type_ = nsp.pfit_type_;
00168 }
00169
00170
00171
00172 sdet_nonmax_suppression::sdet_nonmax_suppression(sdet_nonmax_suppression_params& nsp,
00173 vil_image_view<double> &grad_mag,
00174 vbl_array_2d<vgl_vector_2d <double> > &directions)
00175 : sdet_nonmax_suppression_params(nsp)
00176 {
00177 width_ = grad_mag.ni();
00178 height_ = grad_mag.nj();
00179 grad_x_.resize(width_, height_);
00180 grad_y_.resize(width_, height_);
00181 grad_mag_.resize(width_, height_);
00182 for (int j = 0; j < height_; j++)
00183 {
00184 for (int i = 0; i < width_; i++)
00185 {
00186 double val = grad_mag(i,j);
00187 grad_mag_(i,j) = val;
00188 vgl_vector_2d<double> direction = directions(i,j);
00189 normalize(direction);
00190 grad_x_(i,j) = val * direction.x();
00191 grad_y_(i,j) = val * direction.y();
00192 if (val > max_grad_mag_)
00193 max_grad_mag_ = val;
00194 }
00195 }
00196 points_valid_ = false;
00197 parabola_fit_type_ = nsp.pfit_type_;
00198 }
00199
00200
00201 sdet_nonmax_suppression::~sdet_nonmax_suppression()
00202 {
00203 }
00204
00205
00206
00207
00208 void sdet_nonmax_suppression::apply()
00209 {
00210 if (points_valid_)
00211 return;
00212 points_.clear();
00213
00214
00215
00216 for (int y = 1; y < height_-1; y++)
00217 {
00218 for (int x = 1; x < width_-1; x++)
00219 {
00220
00221 if (grad_mag_(x,y) > thresh_)
00222 {
00223 double gx = grad_x_(x,y);
00224 double gy = grad_y_(x,y);
00225 vgl_vector_2d<double> direction(gx,gy);
00226 normalize(direction);
00227 if (vcl_abs(gx) > 10e-6 && vcl_abs(gy) > 10e-6)
00228 {
00229 int face_num = intersected_face_number(gx, gy);
00230 assert(face_num != -1);
00231 double s = intersection_parameter(gx, gy, face_num);
00232 assert(s != -1000);
00233 double f[3];
00234 f_values(x, y, gx, gy, s, face_num, f);
00235 double s_list[3];
00236 s_list[0] = -s;
00237 s_list[1] = 0.0;
00238 s_list[2] = s;
00239 if (f[1] > f[0] && f[1] > f[2])
00240 {
00241 double s_star = (parabola_fit_type_ == PFIT_3_POINTS)
00242 ? subpixel_s(s_list, f)
00243 : subpixel_s(x, y, direction);
00244 if (-1.5 < s_star && s_star < 1.5)
00245 {
00246 vgl_point_2d<double> subpix(x + s_star * direction.x(), y + s_star * direction.y());
00247 vsol_point_2d_sptr p = new vsol_point_2d(subpix.x(), subpix.y());
00248 vsol_point_2d_sptr line_start = new vsol_point_2d(subpix.x()-direction.y()*0.5, subpix.y()+direction.x()*0.5);
00249 vsol_point_2d_sptr line_end = new vsol_point_2d(subpix.x()+direction.y()*0.5, subpix.y()-direction.x()*0.5);
00250 vsol_line_2d_sptr l = new vsol_line_2d(line_start, line_end);
00251 points_.push_back(p);
00252 lines_.push_back(l);
00253 directions_.push_back(direction);
00254 }
00255 }
00256 }
00257 }
00258 }
00259 }
00260 points_valid_ = true;
00261 }
00262
00263 int sdet_nonmax_suppression::intersected_face_number(double gx, double gy)
00264 {
00265 if (gx >= 0 && gy >= 0)
00266 {
00267 if (gx >= gy)
00268 return 1;
00269 else
00270 return 2;
00271 }
00272 else if (gx < 0 && gy >= 0)
00273 {
00274 if (vcl_abs(gx) < gy)
00275 return 3;
00276 else
00277 return 4;
00278 }
00279 else if (gx < 0 && gy < 0)
00280 {
00281 if (vcl_abs(gx) >= vcl_abs(gy))
00282 return 5;
00283 else
00284 return 6;
00285 }
00286 else if (gx >= 0 && gy < 0)
00287 {
00288 if (gx < vcl_abs(gy))
00289 return 7;
00290 else
00291 return 8;
00292 }
00293 return -1;
00294 }
00295
00296 double sdet_nonmax_suppression::intersection_parameter(double gx, double gy, int face_num)
00297 {
00298 vgl_vector_2d<double> direction(gx,gy);
00299 normalize(direction);
00300 if (face_num == 1 || face_num == 8)
00301 return 1.0/direction.x();
00302 else if (face_num == 2 || face_num == 3)
00303 return 1.0/direction.y();
00304 else if (face_num == 4 || face_num == 5)
00305 return -1.0/direction.x();
00306 else if (face_num == 6 || face_num == 7)
00307 return -1.0/direction.y();
00308 return -1000.0;
00309 }
00310
00311 void sdet_nonmax_suppression::f_values(int x, int y, double gx, double gy, double s, int face_num, double *f)
00312 {
00313 vgl_vector_2d<double> direction(gx,gy);
00314 normalize(direction);
00315
00316 int corners[4];
00317 get_relative_corner_coordinates(face_num, corners);
00318
00319 vgl_vector_2d<double> intersection_point = s * direction;
00320 vgl_vector_2d<double> corner1(corners[0], corners[1]);
00321 vgl_vector_2d<double> corner2(corners[2], corners[3]);
00322 double distance1 = length(intersection_point - corner1);
00323 double distance2 = length(intersection_point - corner2);
00324 double value1 = grad_mag_(x+corners[0], y+corners[1]);
00325 double value2 = grad_mag_(x+corners[2], y+corners[3]);
00326 double f_plus = value1 * distance2 + value2 * distance1;
00327
00328 intersection_point = -s * direction;
00329 corner1.set(-corners[0], -corners[1]);
00330 corner2.set(-corners[2], -corners[3]);
00331 distance1 = length(intersection_point - corner1);
00332 distance2 = length(intersection_point - corner2);
00333 value1 = grad_mag_(x-corners[0], y-corners[1]);
00334 value2 = grad_mag_(x-corners[2], y-corners[3]);
00335 double f_minus = value1 * distance2 + value2 * distance1;
00336
00337 f[0] = f_minus;
00338 f[1] = grad_mag_(x,y);
00339 f[2] = f_plus;
00340 }
00341
00342 void sdet_nonmax_suppression::get_relative_corner_coordinates(int face_num, int *corners)
00343 {
00344 switch (face_num)
00345 {
00346 case 1:
00347 corners[0] = 1;
00348 corners[1] = 0;
00349 corners[2] = 1;
00350 corners[3] = 1;
00351 break;
00352 case 2:
00353 corners[0] = 1;
00354 corners[1] = 1;
00355 corners[2] = 0;
00356 corners[3] = 1;
00357 break;
00358 case 3:
00359 corners[0] = 0;
00360 corners[1] = 1;
00361 corners[2] = -1;
00362 corners[3] = 1;
00363 break;
00364 case 4:
00365 corners[0] = -1;
00366 corners[1] = 1;
00367 corners[2] = -1;
00368 corners[3] = 0;
00369 break;
00370 case 5:
00371 corners[0] = -1;
00372 corners[1] = 0;
00373 corners[2] = -1;
00374 corners[3] = -1;
00375 break;
00376 case 6:
00377 corners[0] = -1;
00378 corners[1] = -1;
00379 corners[2] = 0;
00380 corners[3] = -1;
00381 break;
00382 case 7:
00383 corners[0] = 0;
00384 corners[1] = -1;
00385 corners[2] = 1;
00386 corners[3] = -1;
00387 break;
00388 case 8:
00389 corners[0] = 1;
00390 corners[1] = -1;
00391 corners[2] = 1;
00392 corners[3] = 0;
00393 break;
00394 default:
00395 corners[0] = 0;
00396 corners[1] = 0;
00397 corners[2] = 0;
00398 corners[3] = 0;
00399 }
00400 }
00401
00402 double sdet_nonmax_suppression::subpixel_s(double *s, double *f)
00403 {
00404 double A = f[2] / ((s[2]-s[0])*(s[2]-s[1]));
00405 double B = f[1] / ((s[1]-s[0])*(s[1]-s[2]));
00406 double C = f[0] / ((s[0]-s[1])*(s[0]-s[2]));
00407 double s_star = ((A+B)*s[0] + (A+C)*s[1] + (B+C)*s[2]) / (2*(A+B+C));
00408 return s_star;
00409 }
00410
00411 double sdet_nonmax_suppression::subpixel_s(int x, int y, vgl_vector_2d<double> direction)
00412 {
00413 double d;
00414 double s;
00415 double f;
00416 vgl_homg_point_2d<double> p1(0.0, 0.0);
00417 vgl_homg_point_2d<double> p2(direction.x(), direction.y());
00418 vgl_homg_line_2d<double> line1(p1,p2);
00419
00420 vnl_matrix<double> A(9, 3);
00421 vnl_matrix<double> B(9, 1);
00422 vnl_matrix<double> P(3, 1);
00423 int index = 0;
00424 for (int j = -1; j <= 1; j++)
00425 {
00426 for (int i = -1; i <= 1; i++)
00427 {
00428 find_distance_s_and_f_for_point(i, j, line1, d, s, direction);
00429 f = grad_mag_(x+i,y+j);
00430 A(index, 0) = vcl_pow(s,2.0);
00431 A(index, 1) = s;
00432 A(index, 2) = 1.0;
00433 B(index, 0) = f;
00434 index++;
00435 }
00436 }
00437 #if 0
00438 vnl_matrix<double> A_trans = A.transpose();
00439 P = (vnl_matrix_inverse<double>(A_trans*A) * A_trans) * B;
00440 #else
00441 vnl_svd<double> svd(A);
00442 P = svd.solve(B);
00443 #endif
00444 double s_star = -P(1,0)/(2*P(0,0));
00445 return s_star;
00446 }
00447
00448 void sdet_nonmax_suppression::find_distance_s_and_f_for_point(int x, int y, vgl_homg_line_2d<double> line,
00449 double &d, double &s, vgl_vector_2d<double> direction)
00450 {
00451 vgl_homg_point_2d<double> point(x,y);
00452 vgl_homg_line_2d<double> perp_line = vgl_homg_operators_2d<double>::perp_line_through_point(line, point);
00453 vgl_homg_point_2d<double> intersection_point_homg = vgl_homg_operators_2d<double>::intersection(line, perp_line);
00454 vgl_point_2d<double> intersection_point(intersection_point_homg);
00455 vgl_vector_2d<double> d_helper(x-intersection_point.x(), y-intersection_point.y());
00456 d = length(d_helper);
00457 s = intersection_point.x() / direction.x();
00458 }
00459
00460
00461
00462
00463 void sdet_nonmax_suppression::clear()
00464 {
00465 points_.clear();
00466 points_valid_ = false;
00467 }