00001
00002 #include "sdet_grid_finder.h"
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <vcl_fstream.h>
00018 #include <vcl_algorithm.h>
00019 #include <vnl/vnl_matrix_fixed.h>
00020 #include <vnl/vnl_numeric_traits.h>
00021 #include <vnl/vnl_math.h>
00022 #include <vnl/vnl_det.h>
00023 #include <vbl/vbl_bounding_box.h>
00024 #include <vgl/vgl_homg_line_2d.h>
00025 #include <vgl/vgl_homg_point_2d.h>
00026 #include <vgl/vgl_point_2d.h>
00027 #include <vgl/vgl_vector_2d.h>
00028 #include <vgl/algo/vgl_homg_operators_2d.h>
00029 #include <vgl/algo/vgl_h_matrix_2d_compute_4point.h>
00030 #include <vgl/algo/vgl_h_matrix_2d_compute_linear.h>
00031 #include <vsol/vsol_point_2d.h>
00032 #include <vsol/vsol_line_2d.h>
00033 #include <bsol/bsol_hough_line_index.h>
00034 #include <bsol/bsol_algs.h>
00035 #include <bsol/bsol_distance_histogram.h>
00036 #include <vnl/algo/vnl_convolve.h>
00037 #include <gevd/gevd_bufferxy.h>
00038 static const double collection_grid_radius = 15;
00039 static const double grid_radius = 15;
00040
00041 static void print_lines(vcl_vector<vsol_line_2d_sptr>& lines)
00042 {
00043 for (vcl_vector<vsol_line_2d_sptr>::iterator lit = lines.begin(); lit != lines.end();
00044 lit++)
00045 {
00046 vgl_homg_line_2d<double> l = (*lit)->vgl_hline_2d();
00047 l.normalize();
00048 vcl_cout << l << '\n';
00049 }
00050 }
00051
00052
00053
00054
00055
00056 static bool line_distance(const vsol_line_2d_sptr & l1,
00057 const vsol_line_2d_sptr & l2)
00058 {
00059 vgl_homg_line_2d<double> hl1 = l1->vgl_hline_2d();
00060 vgl_homg_line_2d<double> hl2 = l2->vgl_hline_2d();
00061 hl1.normalize(); hl2.normalize();
00062 return hl1.c() > hl2.c();
00063 }
00064
00065 #if 0
00066 line_chamfer_1d::line_chamfer_1d()
00067 {
00068 size_=0;
00069 dmin_=0;
00070 dmax_=0;
00071 }
00072
00073 line_chamfer_1d::~line_chamfer_1d()
00074 {
00075 for (int i = 0; i<size_; i++)
00076 delete line_index_[i];
00077 }
00078
00079 bool line_chamfer_1d::insert_lines(vcl_vector<vsol_line_2d_sptr> const& lines,
00080 bool horizontal_lines)
00081 {
00082 if (!lines.size())
00083 return false;
00084 dmin_ = vnl_numeric_traits<double>::maxval;
00085 dmax_ = -dmin_;
00086 distances_.clear();
00087
00088 for (vcl_vector<vsol_line_2d_sptr>::const_iterator lit = lines.begin();
00089 lit != lines.end(); lit++)
00090 {
00091 vgl_homg_line_2d<double> l = (*lit)->vgl_hline_2d();
00092 l.normalize();
00093 double d = -l.c();
00094 distances_.push_back(d);
00095 dmin_ = vnl_math_min(d,dmin_);
00096 dmax_ = vnl_math_max(d,dmax_);
00097 }
00098 if (!(dmax_>=dmin_))
00099 return false;
00100 size_=(int)(dmax_-dmin_ +1);
00101 index_.resize(size_, vnl_numeric_traits<int>::maxval);
00102
00103 line_index_.resize(size_);
00104 for (int i = 0; i<size_; i++)
00105 line_index_[i]= new vcl_vector<vsol_line_2d_sptr>;
00106
00107 int line = 0;
00108 for (vcl_vector<double>::iterator dit = distances_.begin();
00109 dit != distances_.end(); dit++, line++)
00110 {
00111 int id = (int)((*dit)-dmin_);
00112 index_[id]=0;
00113 line_index_[id]->push_back(lines[line]);
00114 }
00115 this->forward_champher();
00116 this->backward_champher();
00117 #ifdef DEBUG
00118 for (int i = 0; i<size_; i++)
00119 vcl_cout << "line_index_["<<i+(int)dmin_<<"]="<<line_index_[i]->size() << '\n';
00120 #endif
00121 return true;
00122 }
00123
00124 void line_chamfer_1d::forward_champher()
00125 {
00126 for (int i = 1; i<size_; i++)
00127 if (index_[i-1]+1<=index_[i])
00128 index_[i]=index_[i-1]+1;
00129 }
00130
00131 void line_chamfer_1d::backward_champher()
00132 {
00133 for (int i = size_-2; i>=0; i--)
00134 if (index_[i]>index_[i+1]+1)
00135 index_[i]=index_[i+1]+1;
00136 }
00137
00138 double line_chamfer_1d::distance(double x) const
00139 {
00140 if (x<dmin_)
00141 return vnl_numeric_traits<double>::maxval;
00142 if (x>dmax_)
00143 return vnl_numeric_traits<double>::maxval;
00144 int i = (int)(x-dmin_);
00145 return index_[i];
00146 }
00147
00148 bool
00149 line_chamfer_1d::get_lines_in_interval(const double x,
00150 const double radius,
00151 vcl_vector<vsol_line_2d_sptr>& lines) const
00152 {
00153 lines.clear();
00154 if (x<dmin_)
00155 return false;
00156 if (x>dmax_)
00157 return false;
00158 double x0 = x - dmin_;
00159 int lo = (int)(x0 - radius);
00160 int hi = (int)(x0 + radius);
00161 if (lo<0)
00162 lo=0;
00163 if (hi>(size_-1))
00164 hi = size_ - 1;
00165 for (int d = lo; d<=hi; d++)
00166 if (line_index_[d])
00167 for (vcl_vector<vsol_line_2d_sptr>::iterator lit=line_index_[d]->begin();
00168 lit != line_index_[d]->end(); lit++)
00169 lines.push_back(*lit);
00170 return true;
00171 }
00172 #endif
00173
00174
00175 grid_profile_matcher::grid_profile_matcher()
00176 {
00177 size_=0;
00178 dmin_=0;
00179 dmax_=0;
00180 }
00181
00182 grid_profile_matcher::~grid_profile_matcher()
00183 {
00184 for (int i = 0; i<size_; i++)
00185 delete line_index_[i];
00186 }
00187
00188 bool grid_profile_matcher::insert_lines(vcl_vector<vsol_line_2d_sptr> const& lines,
00189 bool horizontal_lines)
00190 {
00191 if (!lines.size())
00192 return false;
00193 dmin_ = vnl_numeric_traits<double>::maxval;
00194 dmax_ = -dmin_;
00195 distances_.clear();
00196 for (vcl_vector<vsol_line_2d_sptr>::const_iterator lit = lines.begin();
00197 lit != lines.end(); lit++)
00198 {
00199 double d;
00200 #ifdef USE_C_FOR_DISTANCE
00201 vgl_homg_line_2d<double> l = (*lit)->vgl_hline_2d();
00202 l.normalize();
00203 d = -l.c();
00204 #else
00205 vsol_point_2d_sptr mid = (*lit)->middle();
00206 if (horizontal_lines)
00207 d = mid->y();
00208 else
00209 d = mid->x();
00210 #endif
00211 distances_.push_back(d);
00212 dmin_ = vnl_math_min(d,dmin_);
00213 dmax_ = vnl_math_max(d,dmax_);
00214 }
00215 if (!(dmax_>=dmin_))
00216 return false;
00217 size_=(int)(dmax_-dmin_ +1);
00218 image_profile_.set_size(size_);
00219 image_profile_.fill(0.0);
00220
00221 line_index_.resize(size_);
00222 for (int i = 0; i<size_; i++)
00223 line_index_[i]= new vcl_vector<vsol_line_2d_sptr>;
00224
00225 int line = 0;
00226 for (vcl_vector<double>::iterator dit = distances_.begin();
00227 dit != distances_.end(); dit++, line++)
00228 {
00229 int id = (int)((*dit)-dmin_);
00230 image_profile_[id] += lines[line]->length();
00231 line_index_[id]->push_back(lines[line]);
00232 }
00233
00234 if (false)
00235 {
00236 if (horizontal_lines)
00237 vcl_cout << "------horizontal profile: ---------\n";
00238 else
00239 vcl_cout << "------vertical profile: -----------\n";
00240 for (int i = 0; i < size_; i++)
00241 {
00242 vcl_cout <<"profile["<<int(i+dmin_)<<"] = "<<image_profile_[i]<<'\n';
00243 }
00244 }
00245 return true;
00246 }
00247
00248 bool
00249 grid_profile_matcher::get_lines_in_interval(const double x,
00250 const double radius,
00251 vcl_vector<vsol_line_2d_sptr>& lines) const
00252 {
00253 lines.clear();
00254 if (x<dmin_)
00255 return false;
00256 if (x>dmax_)
00257 return false;
00258 double x0 = x - dmin_;
00259 int lo = (int)(x0 - radius);
00260 int hi = (int)(x0 + radius);
00261 if (lo<0)
00262 lo=0;
00263 if (hi>(size_-1))
00264 hi = size_ - 1;
00265 for (int d = lo; d<=hi; d++)
00266 if (line_index_[d])
00267 for (vcl_vector<vsol_line_2d_sptr>::iterator lit=line_index_[d]->begin();
00268 lit != line_index_[d]->end(); lit++)
00269 lines.push_back(*lit);
00270 return true;
00271 }
00272
00273 double grid_profile_matcher::calculate_grid_offset(int n_grid_lines, double spacing)
00274 {
00275
00276 int grid_profile_len = int((n_grid_lines+1) * spacing) + 1;
00277 vnl_vector<double> grid_profile(grid_profile_len,0.0);
00278 int max_offset = int(grid_radius);
00279 #ifdef DEBUG
00280 vcl_cout <<"max_offset = "<<max_offset<<'\n';
00281 #endif
00282 for (int i = 1; i <= n_grid_lines; i++)
00283 {
00284 for (int offset = -max_offset; offset < max_offset; offset++)
00285 {
00286 grid_profile[int(i*spacing)+offset] = ((double)(max_offset -
00287 vcl_abs(double(offset))))/(max_offset);
00288 }
00289 }
00290 #ifdef DEBUG
00291 vcl_cout << "___GRID PROFILE__\n";
00292 for (int i = 0; i < grid_profile_len; i++)
00293 vcl_cout << "grid_profile["<<i<<"] = "<<grid_profile[i]<<'\n';
00294 #endif
00295
00296 vnl_vector<double> convolution = vnl_convolve(image_profile_,grid_profile,0);
00297
00298 double max_value = -vnl_numeric_traits<double>::maxval;
00299 int max_index = -1;
00300 #ifdef DEBUG
00301 vcl_cout << "__CONVOLUTION__\n";
00302 #endif
00303 for (unsigned int i = 0; i < convolution.size(); i++)
00304 {
00305 #ifdef DEBUG
00306 vcl_cout << "convolution["<<i-grid_profile_len+spacing+dmin_<<"] = "<<convolution[i]<<'\n';
00307 #endif
00308 if (convolution[i] > max_value)
00309 {
00310 max_index = i;
00311 max_value = convolution[i];
00312 }
00313 }
00314 return max_index - grid_profile_len + spacing + dmin_;
00315 }
00316
00317
00318
00319
00320
00321
00322
00323
00324 sdet_grid_finder::sdet_grid_finder(sdet_grid_finder_params& gfp)
00325 : sdet_grid_finder_params(gfp),
00326 length_threshold_(15.0)
00327 {
00328 groups_valid_ = false;
00329 vanishing_points_valid_=false;
00330 projective_homography_valid_ = false;
00331 affine_homography_valid_ = false;
00332 homography_valid_ = false;
00333 index_ = 0;
00334 }
00335
00336
00337 sdet_grid_finder::~sdet_grid_finder()
00338 {
00339 }
00340
00341 static void group_angle_stats(vcl_vector<vsol_line_2d_sptr> const & group,
00342 const double angle_tol,
00343 double & avg_angle, double& min_angle,
00344 double& max_angle)
00345 {
00346 min_angle = 360;
00347 max_angle = -360;
00348 int n_lines = 0;
00349 avg_angle=0;
00350
00351 for (vcl_vector<vsol_line_2d_sptr>::const_iterator lit = group.begin();
00352 lit != group.end(); lit++)
00353 {
00354 double ang = (*lit)->tangent_angle();
00355 if (ang>180)
00356 ang -= 180.0;
00357 if (ang<min_angle)
00358 min_angle = ang;
00359 if (ang>max_angle)
00360 max_angle = ang;
00361 }
00362
00363 double cut_thresh = 3.0*angle_tol + 15.0;
00364 bool on_cut = (max_angle-min_angle)>cut_thresh;
00365 if (on_cut)
00366 vcl_cout << "On cut [" << min_angle << ' ' << max_angle << "] >"
00367 << cut_thresh << '\n';
00368 for (vcl_vector<vsol_line_2d_sptr>::const_iterator lit = group.begin();
00369 lit != group.end(); lit++, n_lines++)
00370 {
00371 double ang = (*lit)->tangent_angle();
00372 if (ang>180.0)
00373 ang-=180.0;
00374 if (on_cut&&ang>90)
00375 ang -=180;
00376 avg_angle += ang;
00377 }
00378 if (n_lines)
00379 {
00380 avg_angle /= n_lines;
00381 }
00382 else
00383 avg_angle=0;
00384 }
00385
00386
00387
00388
00389 bool sdet_grid_finder::set_lines(const float xsize, const float ysize,
00390 vcl_vector<vsol_line_2d_sptr> const& lines)
00391 {
00392 debug_lines_.clear();
00393 debug_grid_lines_.clear();
00394 display_lines_.clear();
00395 matched_lines_.clear();
00396 groups_valid_ = false;
00397 vanishing_points_valid_=false;
00398 projective_homography_valid_=false;
00399 affine_homography_valid_ = false;
00400 homography_valid_=false;
00401 lines_=lines;
00402 xmax_ = xsize;
00403 ymax_ = ysize;
00404 index_ = new bsol_hough_line_index(0,0,xsize, ysize);
00405 for (vcl_vector<vsol_line_2d_sptr>::const_iterator lit = lines.begin();
00406 lit != lines.end(); lit++)
00407 index_->index(*lit);
00408 vcl_vector<vcl_vector<vsol_line_2d_sptr> > groups;
00409 if (index_->dominant_line_groups(thresh_, angle_tol_, groups)<2)
00410 return false;
00411 group0_ = groups[0];
00412 group1_ = groups[1];
00413 groups_valid_ = true;
00414 if (debug_state_==VANISHING_POINT)
00415 {
00416 for (vcl_vector<vsol_line_2d_sptr>::const_iterator lit = groups[0].begin();
00417 lit != groups[0].end(); lit++)
00418 debug_lines_.push_back(*lit);
00419 for (vcl_vector<vsol_line_2d_sptr>::const_iterator lit = groups[1].begin();
00420 lit != groups[1].end(); lit++)
00421 debug_lines_.push_back(*lit);
00422 }
00423 return true;
00424 }
00425
00426 bool sdet_grid_finder::
00427 get_vanishing_point(vcl_vector<vsol_line_2d_sptr> const & para_lines,
00428 vgl_homg_point_2d<double>& vp)
00429 {
00430 vcl_vector<vgl_homg_line_2d<double> > vlines, tvlines, stvlines;
00431
00432 int nlines =0;
00433 double tx = 0, ty =0;
00434
00435
00436
00437
00438
00439
00440 for (vcl_vector<vsol_line_2d_sptr>::const_iterator lit = para_lines.begin();
00441 lit != para_lines.end(); lit++)
00442 {
00443 if ((*lit)->length() < length_threshold_)
00444 {
00445 vcl_cout << "discarding line with length < "<<length_threshold_<<'\n';
00446 continue;
00447 }
00448 vgl_homg_line_2d<double> l= (*lit)->vgl_hline_2d();
00449 l.normalize();
00450 tx -= l.a()*l.c();
00451 ty -= l.b()*l.c();
00452 vlines.push_back(l);
00453 nlines++;
00454 }
00455 if (nlines<2)
00456 return false;
00457 tx /=nlines;
00458 ty /=nlines;
00459
00460 for (vcl_vector<vgl_homg_line_2d<double> >::iterator lit = vlines.begin();
00461 lit != vlines.end(); lit++)
00462 {
00463 vgl_homg_line_2d<double>& l = (*lit);
00464 double c = l.c();
00465 c -= l.a()*tx + l.b()*ty;
00466 l.set(l.a(), l.b(), c);
00467 tvlines.push_back(l);
00468 }
00469
00470 double c_sq = 0;
00471 for (vcl_vector<vgl_homg_line_2d<double> >::iterator lit = tvlines.begin();
00472 lit != tvlines.end(); lit++)
00473 {
00474 vgl_homg_line_2d<double>& l = (*lit);
00475 c_sq += l.c()*l.c();
00476 }
00477 c_sq /=nlines;
00478 double sigma_c = vcl_sqrt(c_sq);
00479 for (vcl_vector<vgl_homg_line_2d<double> >::iterator lit = tvlines.begin();
00480 lit != tvlines.end(); lit++)
00481 {
00482 vgl_homg_line_2d<double>& l = (*lit);
00483 double c = l.c();
00484 if (sigma_c>1e-8)
00485 c /= sigma_c;
00486 l.set(l.a(), l.b(), c);
00487 stvlines.push_back(l);
00488 }
00489
00490 vp = vgl_homg_operators_2d<double>::lines_to_point(stvlines);
00491
00492
00493
00494 double lambda = vp.w()/sigma_c;
00495 vp.set((vp.x()+lambda*tx), (vp.y()+lambda*ty), lambda);
00496
00497 vcl_cout << "returning from get_vanishing_point()\n";
00498
00499 return true;
00500 }
00501
00502 bool sdet_grid_finder::compute_vanishing_points()
00503 {
00504 if (!groups_valid_)
00505 return false;
00506 vgl_homg_point_2d<double> vp0, vp1;
00507 if (!get_vanishing_point(group0_, vp0))
00508 return false;
00509 if (!get_vanishing_point(group1_, vp1))
00510 return false;
00511
00512
00513 if (vcl_fabs(vp0.x())>vcl_fabs(vp0.y()))
00514 {
00515 vp0_= vp0;
00516 vp90_= vp1;
00517 }
00518 else
00519 {
00520 vp0_ = vp1;
00521 vp90_=vp0;
00522 }
00523 vanishing_points_valid_ = true;
00524 vcl_cout << "returning from compute_vanishing_points()\n";
00525 return true;
00526 }
00527
00528
00529
00530 bool sdet_grid_finder::match_grid()
00531 {
00532 return true;
00533 }
00534
00535
00536
00537 bool sdet_grid_finder::compute_projective_homography()
00538 {
00539 if (projective_homography_valid_)
00540 return true;
00541
00542 if (!this->compute_vanishing_points())
00543 {
00544 vcl_cout<< "In sdet_grid_finder::compute_projective_homography() -"
00545 << " vanishing point computation failed\n";
00546 return false;
00547 }
00548 affine_homography_valid_ = false;
00549 homography_valid_ = false;
00550 if (verbose_)
00551 {
00552 vcl_cout << "VP0 " << vp0_ << '\n'
00553 << "VP90 " << vp90_ << '\n';
00554 }
00555
00556
00557 vgl_homg_point_2d<double> x_inf(1,0,0), x_minus_inf(-1,0,0);
00558 vgl_homg_point_2d<double> y_inf(0,1,0), y_minus_inf(0,-1,0);
00559 vgl_homg_point_2d<double> origin(0,0,1);
00560 vgl_homg_point_2d<double> x_finite(xmax_,0,1), y_finite(0,ymax_,1);
00561 vgl_homg_point_2d<double> max_corner(xmax_,ymax_,1);
00562
00563
00564
00565 vcl_vector<vgl_homg_point_2d<double> > image;
00566 vcl_vector<vgl_homg_point_2d<double> > grid;
00567
00568
00569 double at_infinity = 1.0e-8;
00570 if (vcl_fabs(vp0_.w())<at_infinity)
00571 {
00572 image.push_back(x_finite);
00573 grid.push_back(x_finite);
00574 }
00575 else
00576 {
00577 image.push_back(vp0_);
00578 if (vp0_.x()/vp0_.w()>0)
00579 grid.push_back(x_inf);
00580 else
00581 grid.push_back(x_minus_inf);
00582 }
00583
00584 if (vcl_fabs(vp90_.w())<at_infinity)
00585 {
00586 image.push_back(y_finite);
00587 grid.push_back(y_finite);
00588 }
00589 else
00590 {
00591 image.push_back(vp90_);
00592 if (vp90_.y()/vp90_.w()>0)
00593 grid.push_back(y_inf);
00594 else
00595 grid.push_back(y_minus_inf);
00596 }
00597
00598 image.push_back(origin); image.push_back(max_corner);
00599 grid.push_back(origin); grid.push_back(max_corner);
00600 vgl_h_matrix_2d_compute_4point comp_4pt;
00601 if (!comp_4pt.compute(image, grid, projective_homography_))
00602 return false;
00603 if (verbose_)
00604 vcl_cout << "The projective homography\n" << projective_homography_ << '\n';
00605 projective_homography_valid_ = true;
00606 return true;
00607 }
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624 static vnl_matrix_fixed<double, 3,3> skew_transform(const double ah,
00625 const double av)
00626 {
00627 vnl_matrix_fixed<double, 3, 3> Q;
00628 Q.put(0, 0, vcl_sin(av)); Q.put(0,1, -vcl_cos(av)); Q.put(0,2,0);
00629 Q.put(1, 0, -vcl_sin(ah)); Q.put(1,1, vcl_cos(ah)); Q.put(1,2,0);
00630 Q.put(2, 0, 0); Q.put(2,1, 0); Q.put(2,2,1);
00631 return Q;
00632 }
00633
00634
00635
00636
00637
00638
00639
00640
00641 bool sdet_grid_finder::scale_transform(const double ,
00642 vcl_vector<vsol_line_2d_sptr> const& gh,
00643 vcl_vector<vsol_line_2d_sptr> const& gv,
00644 vnl_matrix_fixed<double, 3, 3>& S)
00645 {
00646 int nbins = 100;
00647 bsol_distance_histogram Hh(nbins, gh), Hv(nbins, gv);
00648 double hp1=0, hp2=0, vp1=0, vp2=0;
00649
00650 #undef DEC_DEBUG
00651 #ifdef DEC_DEBUG
00652 vcl_cout << "\nHorizontal Distances\n"
00653 << "*********************************\n";
00654 for (vcl_vector<vsol_line_2d_sptr>::const_iterator lit = gh.begin();
00655 lit != gh.end(); lit++)
00656 {
00657 vgl_homg_line_2d<double> hline = (*lit)->vgl_hline_2d();
00658 hline.normalize();
00659 vcl_cout << hline.c() << '\n';
00660 }
00661 vcl_cout << "********************************\n\n"
00662 << "Vertical Distances\n"
00663 << "*********************************\n";
00664 for (vcl_vector<vsol_line_2d_sptr>::const_iterator lit = gv.begin();
00665 lit != gv.end(); lit++)
00666 {
00667 vgl_homg_line_2d<double> hline = (*lit)->vgl_hline_2d();
00668 hline.normalize();
00669 vcl_cout << hline.c() << '\n';
00670 }
00671 vcl_cout << "********************************\n\n";
00672 #endif
00673 if (verbose_)
00674 {
00675 vcl_cout << "Horizontal Histogram\n" << Hh << "\n\n"
00676 << "Vertical Histogram\n" << Hv << "\n\n";
00677 }
00678 if (!Hh.distance_peaks(hp1, hp2))
00679 {
00680 vcl_cout << "In sdet_grid_finder::scale_transform(.) - failed"
00681 << " to find horizontal distance peaks\n";
00682 return false;
00683 }
00684 if (!Hv.distance_peaks(vp1, vp2))
00685 {
00686 vcl_cout << "In sdet_grid_finder::scale_transform(.) - failed"
00687 << " to find vertical distance peaks\n";
00688 return false;
00689 }
00690 double ph = (hp2-hp1), pv = (vp2-vp1);
00691 if (verbose_)
00692 {
00693 vcl_cout << "Horizontal Peaks " << hp1 << ' ' << hp2 << '\n'
00694 << "Vertical Peaks " << vp1 << ' ' << vp2 << '\n'
00695 << "Horizontal Dist " << ph << '\n'
00696 << "Vertical Dist " << pv << '\n';
00697 }
00698
00699 if (ph<0||pv<0)
00700 return false;
00701
00702
00703 S.put(0, 0, spacing_/pv); S.put(0,1, 0); S.put(0,2,0);
00704 S.put(1, 0, 0); S.put(1,1, spacing_/ph); S.put(1,2,0);
00705 S.put(2, 0, 0); S.put(2,1, 0); S.put(2,2,1);
00706 return true;
00707 }
00708
00709 bool sdet_grid_finder::compute_affine_homography()
00710 {
00711 if (!projective_homography_valid_)
00712 return false;
00713 if (affine_homography_valid_)
00714 return true;
00715 float affine_angle_factor = 3.0;
00716
00717
00718
00719 vcl_vector<vsol_line_2d_sptr> affine_lines;
00720 for (vcl_vector<vsol_line_2d_sptr>::const_iterator lit = lines_.begin();
00721 lit != lines_.end(); lit++)
00722 {
00723 vsol_line_2d_sptr pline = this->transform_line(projective_homography_,*lit);
00724 if (verbose_)
00725 {
00726 vcl_cout << "*lit = ["<<(*lit)->p0()->x()<<','<<(*lit)->p0()->y()<<"] ["
00727 << (*lit)->p1()->x()<<','<<(*lit)->p1()->y()<<"]\n"
00728 << "pline = ["<<pline->p0()->x()<<','<<pline->p0()->y()<<"] ["
00729 << pline->p1()->x()<<','<<pline->p1()->y()<<"]\n";
00730 }
00731
00732 if ( (vcl_abs(pline->p0()->x()) > 10000) ||
00733 (vcl_abs(pline->p0()->y()) > 10000) ||
00734 (vcl_abs(pline->p1()->x()) > 10000) ||
00735 (vcl_abs(pline->p1()->y()) > 10000) )
00736 continue;
00737 affine_lines.push_back(pline);
00738 }
00739
00740
00741 vbl_bounding_box<double, 2> b = bsol_algs::bounding_box(affine_lines);
00742 index_ = new bsol_hough_line_index(b);
00743
00744 for (vcl_vector<vsol_line_2d_sptr>::iterator lit = affine_lines.begin();
00745 lit != affine_lines.end(); lit++)
00746 index_->index(*lit);
00747
00748 vcl_vector<vcl_vector<vsol_line_2d_sptr> > groups;
00749 if (index_->dominant_line_groups(thresh_,
00750 affine_angle_factor*angle_tol_,
00751 groups)<2)
00752 return false;
00753
00754 afgroup0_ = groups[0];
00755 afgroup1_ = groups[1];
00756 if (debug_state_==AFFINE_GROUP_BEFORE_SKEW_SCALE)
00757 {
00758 for (vcl_vector<vsol_line_2d_sptr>::const_iterator lit = afgroup0_.begin();
00759 lit != afgroup0_.end(); lit++)
00760 debug_lines_.push_back(*lit);
00761 for (vcl_vector<vsol_line_2d_sptr>::const_iterator lit = afgroup1_.begin();
00762 lit != afgroup1_.end(); lit++)
00763 debug_lines_.push_back(*lit);
00764 }
00765
00766 double avg_angle0=0, avg_angle1=0, min_angle0=0, max_angle0=0,
00767 min_angle1=0, max_angle1=0;
00768
00769 group_angle_stats(afgroup0_, angle_tol_,avg_angle0, min_angle0, max_angle0);
00770 group_angle_stats(afgroup1_, angle_tol_,avg_angle1, min_angle1, max_angle1);
00771
00772 if (verbose_)
00773 {
00774 vcl_cout << "Affine angles\n"
00775 << "G[" << afgroup0_.size() << "] avg_angle = " << avg_angle0
00776 << " min_angle = " << min_angle0 << " max_angle = "
00777 << max_angle0 << '\n'
00778 << "G[" << afgroup1_.size() << "] avg_angle = " << avg_angle1
00779 << " min_angle = " << min_angle1 << " max_angle = "
00780 << max_angle1 << '\n';
00781 }
00782
00783
00784 double deg_to_rad = vnl_math::pi_over_180;
00785 double ang0 =0, ang90=0;
00786 bool zero_is_zero=true;;
00787 if (vcl_fabs(vcl_fabs(avg_angle0)-90)>vcl_fabs(vcl_fabs(avg_angle1)-90))
00788 {
00789 ang0 = avg_angle0*deg_to_rad;
00790 ang90= avg_angle1*deg_to_rad;
00791 zero_is_zero = true;
00792 }
00793 else
00794 {
00795 ang0 = avg_angle1*deg_to_rad;
00796 ang90 = avg_angle0*deg_to_rad;
00797 zero_is_zero = false;
00798 }
00799
00800 if (ang0>vnl_math::pi_over_2)
00801 ang0-=vnl_math::pi;
00802
00803 if (ang90<0)
00804 ang90+=vnl_math::pi;
00805
00806 if ((vcl_fabs(ang90)-vcl_fabs(ang0))< vnl_math::pi/3.0)
00807 {
00808 vcl_cout << "In sdet_grid_finder::compute_affine_homography() -"
00809 << " failed to find dominant groups with at least 60 deg"
00810 << " orientation\n";
00811 return false;
00812 }
00813 vnl_matrix_fixed<double, 3,3> Q = skew_transform(ang0, ang90);
00814
00815 if (verbose_)
00816 vcl_cout << "The skew transform\n" << Q << '\n';
00817
00818
00819
00820 double dx = vcl_fabs(b.xmax()-b.xmin()), dy = vcl_fabs(b.ymax()-b.ymin());
00821 double max_distance = dx;
00822 if (dx<dy)
00823 max_distance = dy;
00824 vnl_matrix_fixed<double, 3, 3> S;
00825 if (zero_is_zero)
00826 {
00827 if (!scale_transform(max_distance, afgroup0_, afgroup1_, S))
00828 return false;
00829 }
00830 else
00831 if (!scale_transform(max_distance, afgroup1_, afgroup0_, S))
00832 return false;
00833 if (verbose_)
00834 vcl_cout << "The scale transform\n" << S << '\n';
00835
00836 affine_homography_ = vgl_h_matrix_2d<double>(S*Q);
00837
00838
00839 #if 0 // Hack! needs to be removed JLM
00840 double length_threshold = 7.0;
00841 #endif
00842 vcl_vector<vsol_line_2d_sptr> grid_lines0, grid_lines90;
00843 for (vcl_vector<vsol_line_2d_sptr>::iterator lit = afgroup0_.begin();
00844 lit != afgroup0_.end(); lit++)
00845 {
00846 #if 0 // Hack! needs to be removed JLM
00847 if ((*lit)->length()<length_threshold)
00848 continue;
00849 #endif
00850 if (zero_is_zero)
00851 grid_lines0.push_back(this->transform_line(affine_homography_,*lit));
00852 else
00853 grid_lines90.push_back(this->transform_line(affine_homography_,*lit));
00854 }
00855 for (vcl_vector<vsol_line_2d_sptr>::iterator lit = afgroup1_.begin();
00856 lit != afgroup1_.end(); lit++)
00857 {
00858 #if 0 // Hack! needs to be removed JLM
00859 if ((*lit)->length()<length_threshold)
00860 continue;
00861 #endif
00862 if (zero_is_zero)
00863 grid_lines90.push_back(this->transform_line(affine_homography_,*lit));
00864 else
00865 grid_lines0.push_back(this->transform_line(affine_homography_,*lit));
00866 }
00867 if ( (debug_state_==AFFINE_GROUP_AFTER_SKEW_SCALE) ||
00868 (debug_state_==TRANS_PERIM_LINES) )
00869 {
00870 for (vcl_vector<vsol_line_2d_sptr>::const_iterator lit =
00871 grid_lines0.begin(); lit != grid_lines0.end(); lit++)
00872 debug_lines_.push_back(*lit);
00873 for (vcl_vector<vsol_line_2d_sptr>::const_iterator lit =
00874 grid_lines90.begin(); lit != grid_lines90.end(); lit++)
00875 debug_lines_.push_back(*lit);
00876 }
00877
00878 vcl_sort(grid_lines0.begin(), grid_lines0.end(), line_distance);
00879 vcl_sort(grid_lines90.begin(), grid_lines90.end(), line_distance);
00880
00881 #ifdef DEBUG
00882 vcl_cout << "Grid Lines 0\n"
00883 #endif
00884 if (!chamf0_.insert_lines(grid_lines0,true))
00885 return false;
00886
00887 #ifdef DEBUG
00888 vcl_cout << "Grid Lines 90\n"
00889 #endif
00890 if (!chamf90_.insert_lines(grid_lines90,false))
00891 return false;
00892
00893 if (false)
00894 {
00895 vcl_cout << "Grid Lines 0\n";
00896 print_lines(grid_lines0);
00897 vcl_cout << "\n\nGrid Lines 90\n";
00898 print_lines(grid_lines90);
00899 }
00900 for (vcl_vector<vsol_line_2d_sptr>::iterator lit = grid_lines0.begin();
00901 lit != grid_lines0.end(); lit++)
00902 display_lines_.push_back(*lit);
00903
00904 for (vcl_vector<vsol_line_2d_sptr>::iterator lit = grid_lines90.begin();
00905 lit != grid_lines90.end(); lit++)
00906 display_lines_.push_back(*lit);
00907
00908 vgl_h_matrix_2d<double> T;
00909 this->compute_homography_linear_chamfer(T);
00910 affine_homography_ = T*affine_homography_;
00911 if (verbose_)
00912 vcl_cout << "The affine homography\n" << affine_homography_ << '\n';
00913 affine_homography_valid_ = true;
00914 return true;
00915 }
00916
00917
00918
00919
00920
00921 bool sdet_grid_finder::
00922 compute_homography_linear_chamfer(vgl_h_matrix_2d<double> & H)
00923 {
00924 double transx=0, transy=0;
00925
00926 transx = chamf90_.calculate_grid_offset(n_lines_y_,spacing_);
00927 transy = chamf0_.calculate_grid_offset(n_lines_x_,spacing_);
00928
00929 if (verbose_)
00930 vcl_cout << " Translation (" << transx << ' ' << transy << ")\n";
00931
00932 if (debug_state_ == TRANS_PERIM_LINES)
00933 {
00934 float xmin = 0, ymin = 0;
00935 float xmax = 2000, ymax = 2000;
00936
00937 for (int i = 0; i < n_lines_y_; i++)
00938 {
00939 vsol_point_2d_sptr p0 = new vsol_point_2d(i*spacing_+transx,ymin);
00940 vsol_point_2d_sptr p1 = new vsol_point_2d(i*spacing_+transx,ymax);
00941 vsol_line_2d_sptr line = new vsol_line_2d(p0,p1);
00942 debug_grid_lines_.push_back(line);
00943 }
00944
00945 for (int i = 0; i < n_lines_x_; i++)
00946 {
00947 vsol_point_2d_sptr p0 = new vsol_point_2d(xmin,i*spacing_+transy);
00948 vsol_point_2d_sptr p1 = new vsol_point_2d(xmax,i*spacing_+transy);
00949 vsol_line_2d_sptr line = new vsol_line_2d(p0,p1);
00950 debug_grid_lines_.push_back(line);
00951 }
00952 }
00953
00954
00955 vnl_matrix_fixed<double, 3, 3> T;
00956 T.put(0, 0, 1); T.put(0,1, 0); T.put(0,2,-transx);
00957 T.put(1, 0, 0); T.put(1,1, 1); T.put(1,2,-transy);
00958 T.put(2, 0, 0); T.put(2,1, 0); T.put(2,2,1);
00959 vgl_h_matrix_2d<double> Htrans(T);
00960 double min_x_offset = -10.0, max_x_offset =(n_lines_y_-1)*spacing_ + 10;
00961 double min_y_offset = -10.0, max_y_offset =(n_lines_x_-1)*spacing_ + 10;
00962 vcl_vector<vgl_homg_line_2d<double> > lines_grid, lines_image;
00963 vcl_vector<double> weights;
00964
00965 double length_sum = 0;
00966 for (int i0 = 0; i0< n_lines_x_; i0++)
00967 {
00968 double dy = i0*spacing_;
00969 vgl_homg_line_2d<double> lh(0.0, 1.0, -dy);
00970 dy += transy;
00971 vcl_vector<vsol_line_2d_sptr> h_lines;
00972 chamf0_.get_lines_in_interval(dy, collection_grid_radius, h_lines);
00973
00974 if (!h_lines.size())
00975 continue;
00976 for (unsigned int j0 = 0; j0<h_lines.size(); j0++)
00977 {
00978 vsol_line_2d_sptr l0 = h_lines[j0];
00979
00980
00981 vsol_line_2d_sptr l0_xformed = this->transform_line(Htrans,l0);
00982 vsol_point_2d_sptr mid = l0_xformed->middle();
00983 #ifdef DEBUG
00984 vcl_cout << "horizontal, p=("<<mid->x()<<','<<mid->y()<<")\n";
00985 #endif
00986 if ( (mid->x() < min_x_offset) || (mid->x() > max_x_offset) )
00987 {
00988 #ifdef DEBUG
00989 vcl_cout << "discarding line with offset "<<mid->x()<<'\n';
00990 #endif
00991 continue;
00992 }
00993
00994 lines_grid.push_back(lh);
00995 matched_lines_.push_back(l0);
00996 if (debug_state_==AFFINE_GROUP_AFTER_TRANS)
00997 debug_lines_.push_back(l0);
00998 double length = l0->length();
00999 length_sum += length;
01000 weights.push_back(length);
01001 vgl_homg_line_2d<double> homgl = l0->vgl_hline_2d();
01002 homgl.normalize();
01003 #ifdef DEBUG
01004 vcl_cout << homgl << '\n';
01005 #endif
01006 lines_image.push_back(homgl);
01007 }
01008 }
01009
01010 for (int i90 = 0; i90< n_lines_y_; i90++)
01011 {
01012 double dx = i90*spacing_;
01013 vgl_homg_line_2d<double> lv(1.0, 0.0, -dx);
01014 dx += transx;
01015 vcl_vector<vsol_line_2d_sptr> v_lines;
01016 chamf90_.get_lines_in_interval(dx, collection_grid_radius, v_lines);
01017 if (!v_lines.size())
01018 continue;
01019 for (unsigned int j90 = 0; j90<v_lines.size(); j90++)
01020 {
01021 vsol_line_2d_sptr l90 = v_lines[j90];
01022
01023 vsol_line_2d_sptr l90_xformed = this->transform_line(Htrans,l90);
01024 vsol_point_2d_sptr mid = l90_xformed->middle();
01025 #ifdef DEBUG
01026 vcl_cout << "vertical, p=("<<mid->x()<<','<<mid->y()<<")\n";
01027 #endif
01028 if ( (mid->y() < min_y_offset) || (mid->y() > max_y_offset) )
01029 {
01030 #ifdef DEBUG
01031 vcl_cout << "discarding line with offset "<<mid->y()<<'\n';
01032 #endif
01033 continue;
01034 }
01035
01036 lines_grid.push_back(lv);
01037
01038 matched_lines_.push_back(l90);
01039 if (debug_state_==AFFINE_GROUP_AFTER_TRANS)
01040 debug_lines_.push_back(l90);
01041 double length = l90->length();
01042 length_sum += length;
01043 weights.push_back(length);
01044 vgl_homg_line_2d<double> homgl = l90->vgl_hline_2d();
01045 homgl.normalize();
01046 #ifdef DEBUG
01047 vcl_cout << homgl << '\n';
01048 #endif
01049 lines_image.push_back(homgl);
01050 }
01051 }
01052 if (debug_state_==AFFINE_GROUP_AFTER_TRANS)
01053 {
01054 vnl_matrix_fixed<double, 3, 3> T;
01055 T.put(0, 0, 1); T.put(0,1, 0); T.put(0,2,-transx);
01056 T.put(1, 0, 0); T.put(1,1, 1); T.put(1,2,-transy);
01057 T.put(2, 0, 0); T.put(2,1, 0); T.put(2,2,1);
01058 vgl_h_matrix_2d<double> h(T);
01059 vcl_vector<vsol_line_2d_sptr> temp;
01060 for (vcl_vector<vsol_line_2d_sptr>::iterator lit = debug_lines_.begin();
01061 lit != debug_lines_.end(); lit++)
01062 {
01063 vsol_line_2d_sptr l = this->transform_line(h,*lit);
01064 temp.push_back(l);
01065 }
01066 debug_lines_.clear();
01067 debug_lines_ = temp;
01068 }
01069
01070 if (length_sum)
01071 for (vcl_vector<double>::iterator wit = weights.begin();
01072 wit != weights.end(); wit++)
01073 (*wit)/=length_sum;
01074
01075 vgl_h_matrix_2d_compute_linear hcl;
01076 #if 0
01077 double error_term = -1;
01078 #endif
01079 H = hcl.compute(lines_image, lines_grid, weights );
01080 vcl_cout << "Translation\n" << H << '\n';
01081 #if 0
01082 vcl_cout << "Error Term = " << error_term << "\n\n";
01083 #endif
01084
01085 return true;
01086 }
01087
01088
01089
01090
01091 bool sdet_grid_finder::compute_manual_homography(vsol_point_2d_sptr ul,
01092 vsol_point_2d_sptr ur,
01093 vsol_point_2d_sptr lr,
01094 vsol_point_2d_sptr ll)
01095 {
01096
01097 vcl_vector<vgl_homg_point_2d<double> > image_pts, grid_pts;
01098
01099 vgl_homg_point_2d<double> im_ul(ul->x(), ul->y());
01100 vgl_homg_point_2d<double> im_ur(ur->x(), ur->y());
01101 vgl_homg_point_2d<double> im_lr(lr->x(), lr->y());
01102 vgl_homg_point_2d<double> im_ll(ll->x(), ll->y());
01103 image_pts.push_back(im_ul);
01104 image_pts.push_back(im_ur);
01105 image_pts.push_back(im_lr);
01106 image_pts.push_back(im_ll);
01107
01108 double min_x = 0, min_y = 0;
01109 double max_x = (n_lines_x_ - 1) * spacing_;
01110 double max_y = (n_lines_y_ - 1) * spacing_;
01111 vgl_homg_point_2d<double> gr_ul(min_x, min_y);
01112 vgl_homg_point_2d<double> gr_ur(max_x, min_y);
01113 vgl_homg_point_2d<double> gr_lr(max_x, max_y);
01114 vgl_homg_point_2d<double> gr_ll(min_x, max_y);
01115 grid_pts.push_back(gr_ul);
01116 grid_pts.push_back(gr_ur);
01117 grid_pts.push_back(gr_lr);
01118 grid_pts.push_back(gr_ll);
01119 vgl_h_matrix_2d_compute_linear hcl;
01120 vgl_h_matrix_2d<double> H = hcl.compute(image_pts, grid_pts);
01121 vcl_cout << "initial homography estimate\n" << H << '\n';
01122 vgl_h_matrix_2d<double> Hinv = H.get_inverse();
01123 vcl_cout << "initial homography estimate inverse\n" << Hinv << '\n';
01124
01125
01126 double bound_x_min = min_x - 5;
01127 double bound_x_max = max_x + 5;
01128 double bound_y_min = min_y - 5;
01129 double bound_y_max = max_y + 5;
01130 vcl_vector<vgl_homg_line_2d<double> > grid_lines, image_lines;
01131 vcl_vector<double> weights;
01132 double length_sum = 0;
01133
01134 for (vcl_vector<vsol_line_2d_sptr>::const_iterator lit = lines_.begin();
01135 lit != lines_.end(); lit++)
01136 {
01137
01138 if ( *((*lit)->p0()) == *((*lit)->p1()) )
01139 continue;
01140
01141 vgl_homg_line_2d<double> homgl = (*lit)->vgl_hline_2d();
01142 homgl.normalize();
01143
01144 vsol_line_2d_sptr tline = this->transform_line(H,*lit);
01145
01146 #ifdef USE_HTLINE // currently not active
01147 vgl_homg_line_2d<double> htline = tline->vgl_hline_2d();
01148 htline.normalize();
01149 #endif
01150
01151 if ( (tline->p0()->x() > bound_x_max) || (tline->p0()->x() < bound_x_min) ||
01152 (tline->p0()->y() > bound_y_max) || (tline->p0()->y() < bound_y_min) ||
01153 (tline->p1()->y() > bound_x_max) || (tline->p1()->x() < bound_x_min) ||
01154 (tline->p1()->y() > bound_y_max) || (tline->p1()->y() < bound_y_min) )
01155 continue;
01156
01157 vgl_vector_2d<double> direction = tline->direction();
01158
01159 double direction_len = direction.length();
01160 direction.set(direction.x()/direction_len,
01161 direction.y()/direction_len);
01162 double max_orthog_component = 0.1;
01163
01164 if (vcl_fabs(direction.y()) < max_orthog_component)
01165 {
01166
01167
01168 double length = (*lit)->length();
01169 #ifdef USE_HTLINE // currently not active
01170 int closest_line = vnl_math_rnd(-htline.c() / spacing_);
01171 #else
01172 int closest_line = vnl_math_rnd(tline->middle()->y() / spacing_);
01173 #endif
01174
01175 vgl_homg_line_2d<double> gl(0.0, 1.0, -spacing_*closest_line);
01176 grid_lines.push_back(gl);
01177 length_sum += length;
01178 weights.push_back(length);
01179 image_lines.push_back(homgl);
01180 if (debug_state_==TRANS_PERIM_LINES)
01181 debug_lines_.push_back(*lit);
01182 if (debug_state_==AFFINE_GROUP_AFTER_TRANS)
01183 debug_lines_.push_back(tline);
01184 }
01185 else if (vcl_fabs(direction.x()) < max_orthog_component)
01186 {
01187
01188
01189 double length = (*lit)->length();
01190 vgl_homg_line_2d<double> homgl = (*lit)->vgl_hline_2d();
01191 homgl.normalize();
01192 #ifdef USE_HTLINE // currently not active
01193 int closest_line = vnl_math_rnd(-htline.c() / spacing_);
01194 #else
01195 int closest_line = vnl_math_rnd(tline->middle()->x() / spacing_);
01196 #endif
01197
01198 vgl_homg_line_2d<double> gl(1.0, 0.0, -spacing_*closest_line);
01199 grid_lines.push_back(gl);
01200 length_sum += length;
01201 weights.push_back(length);
01202 image_lines.push_back(homgl);
01203 if (debug_state_==TRANS_PERIM_LINES)
01204 debug_lines_.push_back(*lit);
01205 if (debug_state_==AFFINE_GROUP_AFTER_TRANS)
01206 debug_lines_.push_back(tline);
01207 }
01208 }
01209 if (length_sum)
01210 for (vcl_vector<double>::iterator wit = weights.begin();
01211 wit != weights.end(); wit++)
01212 (*wit)/=length_sum;
01213
01214 #if 0
01215 double error_term = -1;
01216 #endif
01217 H = hcl.compute(image_lines, grid_lines, weights );
01218 vcl_cout << "fine tuned homography\n" << H << '\n';
01219 Hinv = H.get_inverse();
01220 vcl_cout << "inverse H =\n" << Hinv << '\n';
01221 #if 0
01222 vcl_cout << "Error Term = " << error_term << "\n\n";
01223 #endif
01224
01225 homography_ = H;
01226
01227 homography_valid_ = true;
01228
01229 return true;
01230 }
01231
01232 bool sdet_grid_finder::compute_homography()
01233 {
01234 static int framenum = 0;
01235 vcl_cout << "framenum = "<<framenum++<<'\n';
01236
01237 if (!this->compute_projective_homography())
01238 {
01239 vcl_cout << "In sdet_grid_finder::compute_homography() -"
01240 << " projective homography failed\n";
01241 return false;
01242 }
01243
01244 if (!this->compute_affine_homography())
01245 {
01246 vcl_cout << "In sdet_grid_finder::compute_homography() -"
01247 << " affine homography failed\n";
01248 return false;
01249 }
01250
01251 homography_ = affine_homography_*projective_homography_;
01252
01253 if (verbose_)
01254 {
01255 vcl_cout << "The composite homography\n" << homography_ << '\n';
01256 }
01257
01258 double det = vnl_det(homography_.get_matrix());
01259 if (det != 0.0)
01260 homography_valid_ = true;
01261
01262 return true;
01263 }
01264
01265
01266
01267
01268 vsol_line_2d_sptr
01269 sdet_grid_finder::transform_line(vgl_h_matrix_2d<double> const& h,
01270 vsol_line_2d_sptr const & l)
01271 {
01272 vsol_point_2d_sptr p0 = l->p0();
01273 vsol_point_2d_sptr p1 = l->p1();
01274 vgl_homg_point_2d<double> vp0(p0->x(), p0->y());
01275 vgl_homg_point_2d<double> vp1(p1->x(), p1->y());
01276 vgl_point_2d<double> tvp0 = h(vp0);
01277 vgl_point_2d<double> tvp1 = h(vp1);
01278 vsol_point_2d_sptr tp0 = new vsol_point_2d(tvp0.x(), tvp0.y());
01279 vsol_point_2d_sptr tp1 = new vsol_point_2d(tvp1.x(), tvp1.y());
01280 return new vsol_line_2d(tp0, tp1);
01281 }
01282
01283 bool
01284 sdet_grid_finder::get_affine_lines(vcl_vector<vsol_line_2d_sptr> & lines)
01285 {
01286 lines = display_lines_;
01287 return true;
01288 }
01289
01290 bool
01291 sdet_grid_finder::get_grid_points(vcl_vector<double> &image_x, vcl_vector<double> &image_y)
01292 {
01293 if (!homography_valid_)
01294 return false;
01295
01296
01297
01298
01299 image_x.clear();
01300 image_y.clear();
01301 image_x_.clear();
01302 image_y_.clear();
01303 vgl_h_matrix_2d<double> grid_to_image = homography_.get_inverse();
01304
01305
01306 for (int x = 0; x < n_lines_y_; x++)
01307 {
01308 for (int y = 0; y < n_lines_x_; y++)
01309 {
01310 vgl_homg_point_2d<double> hp(x*spacing_, y*spacing_);
01311 vgl_homg_point_2d<double> thp = grid_to_image(hp);
01312 double imgx = thp.x() / thp.w();
01313 double imgy = thp.y() / thp.w();
01314 image_x_.push_back(imgx);
01315 image_y_.push_back(imgy);
01316 }
01317 }
01318 image_x = image_x_;
01319 image_y = image_y_;
01320 return true;
01321 }
01322
01323 bool
01324 sdet_grid_finder::get_debug_lines(vcl_vector<vsol_line_2d_sptr> & lines)
01325 {
01326 lines.clear();
01327 lines = debug_lines_;
01328 return true;
01329 }
01330
01331 bool
01332 sdet_grid_finder::get_debug_grid_lines(vcl_vector<vsol_line_2d_sptr> & lines)
01333 {
01334 lines.clear();
01335 lines = debug_grid_lines_;
01336 return true;
01337 }
01338
01339 bool
01340 sdet_grid_finder::get_matched_lines(vcl_vector<vsol_line_2d_sptr> & lines)
01341 {
01342 lines = matched_lines_;
01343 return true;
01344 }
01345
01346
01347
01348
01349 bool
01350 sdet_grid_finder::get_mapped_lines(vcl_vector<vsol_line_2d_sptr> & lines)
01351 {
01352 if (!homography_valid_)
01353 return false;
01354 lines.clear();
01355 for (vcl_vector<vsol_line_2d_sptr>::iterator lit = lines_.begin();
01356 lit != lines_.end(); lit++)
01357 {
01358 vsol_line_2d_sptr l = this->transform_line(homography_,*lit);
01359 lines.push_back(l);
01360 }
01361 return true;
01362 }
01363
01364
01365
01366
01367
01368 bool
01369 sdet_grid_finder::get_backprojected_grid(vcl_vector<vsol_line_2d_sptr> & lines)
01370 {
01371 if (!homography_valid_)
01372 return false;
01373
01374 lines.clear();
01375 vgl_h_matrix_2d<double> grid_to_image = homography_.get_inverse();
01376
01377
01378 for (int y = 0; y<n_lines_y_; y++)
01379 {
01380 double xv = y*spacing_, maxy = (n_lines_x_-1)*spacing_;
01381 vgl_homg_point_2d<double> p0(xv,0), p1(xv, maxy);
01382 vgl_homg_point_2d<double> tp0, tp1;
01383 tp0 = grid_to_image(p0); tp1 = grid_to_image(p1);
01384 vsol_point_2d_sptr sp0 = new vsol_point_2d(tp0);
01385 vsol_point_2d_sptr sp1 = new vsol_point_2d(tp1);
01386 vsol_line_2d_sptr lv= new vsol_line_2d(sp0, sp1);
01387 lines.push_back(lv);
01388 }
01389
01390 for (int x = 0; x<n_lines_x_; x++)
01391 {
01392 double yv = x*spacing_, maxx = (n_lines_y_-1)*spacing_;
01393 vgl_homg_point_2d<double> p0(0,yv), p1(maxx, yv);
01394 vgl_homg_point_2d<double> tp0, tp1;
01395 tp0 = grid_to_image(p0); tp1 = grid_to_image(p1);
01396 vsol_point_2d_sptr sp0 = new vsol_point_2d(tp0);
01397 vsol_point_2d_sptr sp1 = new vsol_point_2d(tp1);
01398 vsol_line_2d_sptr lv = new vsol_line_2d(sp0, sp1);
01399 lines.push_back(lv);
01400 }
01401 #ifdef DEBUG
01402
01403 write_image_points(grid_to_image);
01404 #endif
01405
01406 return true;
01407 }
01408
01409
01410
01411 bool sdet_grid_finder::init_output_file(vcl_ofstream & outstream)
01412 {
01413 outstream << (n_lines_x_*n_lines_y_) << '\n';
01414
01415 for (int x = 0; x < n_lines_y_; x++)
01416 {
01417 for (int y = 0; y < n_lines_x_; y++)
01418 {
01419 outstream << x*spacing_<<' '<<y*spacing_<<'\n';
01420 }
01421 }
01422 outstream << "NUM_VIEWS_PLACEHOLDER\n";
01423 return true;
01424 }
01425
01426
01427 bool sdet_grid_finder::write_image_points(vcl_ofstream & outstream)
01428 {
01429 vgl_h_matrix_2d<double> grid_to_image = homography_.get_inverse();
01430
01431
01432 for (int x=0; x<n_lines_y_; x++)
01433 {
01434 for (int y=0; y<n_lines_x_; y++)
01435 {
01436 vgl_homg_point_2d<double> hp(x*spacing_, y*spacing_);
01437 vgl_homg_point_2d<double> thp = grid_to_image(hp);
01438 double image_x = thp.x() / thp.w();
01439 double image_y = thp.y() / thp.w();
01440 outstream << image_x <<' '<<image_y<<'\n';
01441 }
01442 }
01443 outstream << '\n';
01444
01445 return true;
01446 }
01447
01448
01449 bool sdet_grid_finder::transform_grid_points(vnl_matrix_fixed<double,3,3> & K,
01450 vnl_matrix_fixed<double,3,4> & M,
01451 vcl_vector<vsol_point_2d_sptr> & points)
01452 {
01453 vnl_matrix_fixed<double,3,4> grid_to_image_debug = K*M;
01454
01455 for (int x = 0; x<n_lines_x_; x++)
01456 {
01457 for (int y = 0; y<n_lines_y_; y++)
01458 {
01459 vnl_matrix_fixed<double,4,1> p;
01460 p.put(0,0,x*spacing_); p.put(1,0,y*spacing_); p.put(2,0,0); p.put(3,0,1);
01461
01462 vnl_matrix_fixed<double,3,1> tp = grid_to_image_debug * p;
01463
01464 vsol_point_2d_sptr sp = new vsol_point_2d(tp.get(0,0)/tp.get(2,0),
01465 tp.get(1,0)/tp.get(2,0));
01466 points.push_back(sp);
01467 }
01468 }
01469 return true;
01470 }
01471
01472
01473
01474
01475 void sdet_grid_finder::clear()
01476 {
01477 lines_.clear();
01478 vanishing_points_valid_=false;
01479 projective_homography_valid_ = false;
01480 homography_valid_ = false;
01481 }
01482
01483
01484
01485 bool sdet_grid_finder::check_grid_match(vil1_image img)
01486 {
01487 if (!homography_valid_)
01488 return false;
01489
01490 double mean_intensity, intensity_sigma;
01491
01492
01493 double square_max_mins[2][2];
01494
01495 square_max_mins[0][0] = vnl_numeric_traits<double>::maxval;
01496
01497 square_max_mins[0][1] = 0;
01498
01499 square_max_mins[1][0] = vnl_numeric_traits<double>::maxval;
01500
01501 square_max_mins[1][1] = 0;
01502
01503 int category;
01504
01505 for (int i = 0; i < n_lines_x_-1; i++)
01506 {
01507 if (!get_square_pixel_stats(img,0,i,mean_intensity,intensity_sigma))
01508 return false;
01509 category = i%2;
01510 if (mean_intensity < square_max_mins[category][0])
01511 square_max_mins[category][0] = mean_intensity;
01512 if (mean_intensity > square_max_mins[category][1])
01513 square_max_mins[category][1] = mean_intensity;
01514 }
01515
01516 for (int i = 0; i < n_lines_x_-1; i++)
01517 {
01518 if (!get_square_pixel_stats(img,n_lines_y_-2,i,mean_intensity,intensity_sigma))
01519 return false;
01520 category = int(vcl_abs(double((n_lines_y_%2) - (i%2))));
01521 if (mean_intensity < square_max_mins[category][0])
01522 square_max_mins[category][0] = mean_intensity;
01523 if (mean_intensity > square_max_mins[category][1])
01524 square_max_mins[category][1] = mean_intensity;
01525 }
01526
01527 for (int i = 0; i < n_lines_y_-1; i++)
01528 {
01529 if (!get_square_pixel_stats(img,i,0,mean_intensity,intensity_sigma))
01530 return false;
01531 category = (i%2);
01532 if (mean_intensity < square_max_mins[category][0])
01533 square_max_mins[category][0] = mean_intensity;
01534 if (mean_intensity > square_max_mins[category][1])
01535 square_max_mins[category][1] = mean_intensity;
01536 }
01537
01538 for (int i = 0; i < n_lines_y_-1; i++)
01539 {
01540 if (!get_square_pixel_stats(img,i,n_lines_x_-2,mean_intensity,intensity_sigma))
01541 return false;
01542 category = int(vcl_abs(double((n_lines_x_%2) - (i%2))));
01543 if (mean_intensity < square_max_mins[category][0])
01544 square_max_mins[category][0] = mean_intensity;
01545 if (mean_intensity > square_max_mins[category][1])
01546 square_max_mins[category][1] = mean_intensity;
01547 }
01548 vcl_cout << "cat 1: min = "<<square_max_mins[0][0]<<" max = "<<square_max_mins[0][1]<<'\n'
01549 << "cat 2: min = "<<square_max_mins[1][0]<<" max = "<<square_max_mins[1][1]<<'\n';
01550
01551 if ( (square_max_mins[0][0] > square_max_mins[1][1]) ||
01552 (square_max_mins[1][0] > square_max_mins[0][1]) )
01553 {
01554 return true;
01555 }
01556 else
01557 {
01558 vcl_cout << "INVALID GRID MATCH\n";
01559 return false;
01560 }
01561 }
01562
01563
01564
01565 bool sdet_grid_finder::get_square_pixel_stats(vil1_image img,
01566 int x,int y,
01567 double & mean_intensity,
01568 double & )
01569 {
01570 gevd_bufferxy img_buff(img);
01571
01572 vgl_homg_point_2d<double> gul(x*spacing_,y*spacing_);
01573 vgl_homg_point_2d<double> gur((x+1)*spacing_,y*spacing_);
01574 vgl_homg_point_2d<double> glr((x+1)*spacing_,(y+1)*spacing_);
01575 vgl_homg_point_2d<double> gll(x*spacing_,(y+1)*spacing_);
01576 vgl_homg_point_2d<double> ul,ur,lr,ll;
01577
01578 vgl_h_matrix_2d<double> grid_to_image = homography_.get_inverse();
01579
01580 ul = grid_to_image(gul); ul.set(ul.x()/ul.w(), ul.y()/ul.w(),1.0);
01581 ur = grid_to_image(gur); ur.set(ur.x()/ur.w(), ur.y()/ur.w(),1.0);
01582 lr = grid_to_image(glr); lr.set(lr.x()/lr.w(), lr.y()/lr.w(),1.0);
01583 ll = grid_to_image(gll); ll.set(ll.x()/ll.w(), ll.y()/ll.w(),1.0);
01584
01585 #ifdef DEBUG
01586 vcl_cout << "ul "<<ul<<" ur "<<ur<<" lr "<<lr<<" ll "<<ll<<'\n';
01587 #endif
01588
01589 int min_y =
01590 vnl_math_rnd(vnl_math_min(vnl_math_min(vnl_math_min(ul.y(),ur.y()),ll.y()),lr.y())) -1;
01591 int max_y =
01592 vnl_math_rnd(vnl_math_max(vnl_math_max(vnl_math_max(ul.y(),ur.y()),ll.y()),lr.y())) +1;
01593
01594 int n_scan_rows = max_y - min_y + 1;
01595
01596 if (n_scan_rows < 2*n_lines_x_)
01597 {
01598
01599 return false;
01600 }
01601
01602 vnl_matrix<int> scan_rows(n_scan_rows,2);
01603
01604 for (int i = 0; i < n_scan_rows; i++)
01605 {
01606 scan_rows[i][0] = vnl_numeric_traits<int>::maxval;
01607 scan_rows[i][1] = -vnl_numeric_traits<int>::maxval;
01608 }
01609
01610
01611
01612
01613
01614 int start_t = vnl_math_rnd(ul.x()+0.5);
01615 int end_t = vnl_math_rnd(ur.x()-0.5);
01616 double slope = (ur.y() - ul.y())/(ur.x() - ul.x());
01617 double real_pix = ul.y();
01618 int rounded_pix;
01619 int row_idx;
01620 #ifdef DEBUG
01621 vcl_cout << "start_t = "<<start_t<<" end_t= "<<end_t<<" slope = "<<slope<<'\n';
01622 #endif
01623 for (int t = start_t; t <= end_t; t++)
01624 {
01625 rounded_pix = vnl_math_rnd(real_pix);
01626 row_idx = rounded_pix - min_y;
01627 scan_rows[row_idx][0] = vnl_math_min(scan_rows[row_idx][0],t);
01628 scan_rows[row_idx][1] = vnl_math_max(scan_rows[row_idx][1],t);
01629 real_pix += slope;
01630 }
01631
01632
01633 start_t = vnl_math_rnd(ll.x()+0.5);
01634 end_t = vnl_math_rnd(lr.x()-0.5);
01635 slope = (lr.y() - ll.y())/(lr.x() - ll.x());
01636 real_pix = ll.y();
01637 #ifdef DEBUG
01638 vcl_cout << "start_t = "<<start_t<<" end_t= "<<end_t<<" slope = "<<slope<<'\n';
01639 #endif
01640 for (int t = start_t; t <= end_t; t++)
01641 {
01642 rounded_pix = vnl_math_rnd(real_pix);
01643 row_idx = rounded_pix - min_y;
01644 scan_rows[row_idx][0] = vnl_math_min(scan_rows[row_idx][0],t);
01645 scan_rows[row_idx][1] = vnl_math_max(scan_rows[row_idx][1],t);
01646 real_pix += slope;
01647 }
01648
01649
01650 start_t = vnl_math_rnd(ul.y()+0.5);
01651 end_t = vnl_math_rnd(ll.y()-0.5);
01652 slope = (ll.x() - ul.x())/(ll.y() - ul.y());
01653 real_pix = ul.x();
01654 #ifdef DEBUG
01655 vcl_cout << "start_t = "<<start_t<<" end_t= "<<end_t<<" slope = "<<slope<<'\n';
01656 #endif
01657 for (int t = start_t; t <= end_t; t++)
01658 {
01659 rounded_pix = vnl_math_rnd(real_pix);
01660 row_idx = t - min_y;
01661 scan_rows[row_idx][0] = vnl_math_min(scan_rows[row_idx][0],rounded_pix);
01662 scan_rows[row_idx][1] = vnl_math_max(scan_rows[row_idx][1],rounded_pix);
01663 real_pix += slope;
01664 }
01665
01666
01667 start_t = vnl_math_rnd(ur.y()+0.5);
01668 end_t = vnl_math_rnd(lr.y()-0.5);
01669 slope = (lr.x() - ur.x())/(lr.y() - ur.y());
01670 real_pix = ur.x();
01671 #ifdef DEBUG
01672 vcl_cout << "start_t = "<<start_t<<" end_t= "<<end_t<<" slope = "<<slope<<'\n';
01673 #endif
01674 for (int t = start_t; t <= end_t; t++)
01675 {
01676 rounded_pix = vnl_math_rnd(real_pix);
01677 row_idx = t - min_y;
01678 scan_rows[row_idx][0] = vnl_math_min(scan_rows[row_idx][0],rounded_pix);
01679 scan_rows[row_idx][1] = vnl_math_max(scan_rows[row_idx][1],rounded_pix);
01680 real_pix += slope;
01681 }
01682
01683 double intensity_total = 0.0;
01684 int n_pix = 0;
01685 for (int i = 0; i < n_scan_rows; i++)
01686 {
01687 for (int j = scan_rows[i][0]; j <= scan_rows[i][1]; ++j)
01688 {
01689 int xx = j, yy = i + min_y;
01690 if (xx < 0 || xx >= img_buff.GetSizeX())
01691 continue;
01692 if (yy < 0 || yy >= img_buff.GetSizeY())
01693 continue;
01694 intensity_total+= *((unsigned char*)(img_buff.GetElementAddr(xx,yy)));
01695 ++n_pix;
01696 }
01697 }
01698 if (!n_pix)
01699 {
01700 vcl_cout << "grid square contains 0 pixels\n";
01701 return false;
01702 }
01703 mean_intensity = intensity_total / n_pix;
01704 if (verbose_)
01705 vcl_cout << '('<<x<<','<<y<<") mean_intensity = "<<mean_intensity<<'\n';
01706 return true;
01707 }
01708