00001
00002 #include "bmvv_cal_manager.h"
00003
00004
00005
00006
00007 #include <vcl_iostream.h>
00008 #include <vil/vil_image_view.h>
00009 #include <vil/vil_load.h>
00010 #include <vil/vil_save.h>
00011 #include <vil/vil_math.h>
00012 #include <vil/vil_new.h>
00013 #include <vnl/vnl_matrix_fixed.h>
00014 #include <vgl/vgl_vector_3d.h>
00015 #include <vgl/vgl_homg_point_2d.h>
00016 #include <vgl/vgl_homg_point_3d.h>
00017 #include <vgl/algo/vgl_h_matrix_2d.h>
00018 #include <vgl/algo/vgl_p_matrix.h>
00019 #include <vgui/vgui.h>
00020 #include <vgui/vgui_key.h>
00021 #include <vgui/vgui_style.h>
00022 #include <vgui/vgui_macro.h>
00023 #include <vgui/vgui_dialog.h>
00024 #include <vgui/vgui_image_tableau.h>
00025 #include <vgui/vgui_viewer2D_tableau.h>
00026 #include <vgui/vgui_shell_tableau.h>
00027 #include <vgui/vgui_range_map_params.h>
00028 #include <vgui/vgui_projection_inspector.h>
00029 #include <bgui/bgui_image_tableau.h>
00030 #include <bgui/bgui_range_adjuster_tableau.h>
00031 #include <bgui/bgui_vsol_soview2D.h>
00032 #include <bgui/bgui_vtol2D_tableau.h>
00033 #include <bgui/bgui_picker_tableau.h>
00034 #include <brip/brip_vil_float_ops.h>
00035 #include <brct/brct_algos.h>
00036 #include <vsol/vsol_point_2d.h>
00037 #include <vsol/vsol_point_3d.h>
00038 #include <vsol/vsol_polygon_2d.h>
00039 #include <vsol/vsol_polygon_3d.h>
00040 #include <vpgl/vpgl_proj_camera.h>
00041 #include <vpgl/algo/vpgl_camera_compute.h>
00042 #include <vpgl/algo/vpgl_optimize_camera.h>
00043 #include <vcl_cassert.h>
00044
00045
00046 bmvv_cal_manager *bmvv_cal_manager::instance_ = 0;
00047
00048
00049
00050
00051 bmvv_cal_manager *bmvv_cal_manager::instance()
00052 {
00053 if (!instance_)
00054 {
00055 instance_ = new bmvv_cal_manager();
00056 instance_->init();
00057 }
00058 return bmvv_cal_manager::instance_;
00059 }
00060
00061
00062
00063
00064 bmvv_cal_manager::
00065 bmvv_cal_manager() : vgui_wrapper_tableau(), cam_(vgl_p_matrix<double>()),
00066 prev_cam_(vgl_p_matrix<double>())
00067 {
00068 corrs_.resize(0);
00069 corrs_valid_.resize(0);
00070 proj_image_pts_.resize(0);
00071 corr_sovs_.resize(0);
00072 }
00073
00074 bmvv_cal_manager::~bmvv_cal_manager()
00075 {
00076 delete instance_;
00077 }
00078
00079
00080
00081
00082
00083 void bmvv_cal_manager::init()
00084 {
00085 itab_ = bgui_image_tableau_new();
00086 btab_ = bgui_vtol2D_tableau_new(itab_);
00087 ptab_ = bgui_picker_tableau_new(btab_);
00088 vgui_viewer2D_tableau_sptr vtab = vgui_viewer2D_tableau_new(ptab_);
00089 vgui_shell_tableau_sptr shell = vgui_shell_tableau_new(vtab);
00090 this->add_child(shell);
00091 height_ = 0.0;
00092 }
00093
00094
00095
00096
00097
00098
00099
00100 bool bmvv_cal_manager::handle(const vgui_event &e)
00101 {
00102 vgui_projection_inspector proj;
00103 if (e.type == vgui_KEY_PRESS)
00104 {
00105 if (btab_)
00106 if (e.key == 'u')
00107 {
00108 btab_->deselect_all();
00109 return true;
00110 }
00111 }
00112 return this->child.handle(e);
00113 }
00114
00115
00116
00117
00118 void bmvv_cal_manager::quit()
00119 {
00120 vgui::quit();
00121 }
00122
00123
00124
00125
00126 void bmvv_cal_manager::load_image_file(vcl_string image_filename, bool )
00127 {
00128
00129 img_ = vil_load_image_resource(image_filename.c_str());
00130 if (!img_)
00131 {
00132 vcl_cout << "Null image resource - couldn't load from "
00133 << image_filename << '\n';
00134 return;
00135 }
00136 vgui_range_map_params_sptr rmps = range_params(img_);
00137 if (itab_)
00138 {
00139 itab_->set_image_resource(img_, rmps);
00140 return;
00141 }
00142 vcl_cout << "In bmvv_cal_manager::load_image_file() - null tableau\n";
00143 }
00144
00145 void bmvv_cal_manager::add_image(vil_image_resource_sptr const& image,
00146 vgui_range_map_params_sptr rmps,
00147 bool greyscale)
00148 {
00149 if (greyscale)
00150 {
00151 #if 0// do nothing right now
00152 vil1_memory_image_of<unsigned char> temp1 =
00153 brip_vil1_float_ops::convert_to_grey(image);
00154 img_ = temp1;
00155 #endif
00156 }
00157 else
00158 img_ = image;
00159
00160 if (itab_)
00161 {
00162 itab_->set_image_resource(img_, rmps);
00163 itab_->post_redraw();
00164 return;
00165 }
00166 vcl_cout << "In bmvv_cal_manager::load_image() - null tableau\n";
00167 }
00168
00169
00170
00171
00172 void bmvv_cal_manager::load_image()
00173 {
00174 static bool greyscale = false;
00175 vgui_dialog load_image_dlg("Load Image");
00176 static vcl_string image_filename = "";
00177 static vcl_string ext = "*.*";
00178 load_image_dlg.file("Image Filename:", ext, image_filename);
00179 load_image_dlg.checkbox("greyscale ", greyscale);
00180 if (!load_image_dlg.ask())
00181 return;
00182 vil_image_resource_sptr temp = vil_load_image_resource(image_filename.c_str());
00183 vgui_range_map_params_sptr rmps = range_params(temp);
00184 this->add_image(temp, rmps, greyscale);
00185 }
00186
00187 void bmvv_cal_manager::save_image()
00188 {
00189 vgui_dialog file_dialog("Save Image");
00190 static vcl_string image_file;
00191 static vcl_string ext = "tif";
00192 static vcl_string type = "tiff";
00193 static bool byte = false;
00194 file_dialog.file("Image Filename:", ext, image_file);
00195 file_dialog.field("Image Format: ", type);
00196 file_dialog.checkbox("Convert to byte image", byte);
00197 if (!file_dialog.ask())
00198 return;
00199 vil_image_resource_sptr img = itab_->get_image_resource();
00200 if (!img)
00201 {
00202 vcl_cerr << "Null image in bmvv_cal_manager::save_image\n";
00203 return;
00204 }
00205 vil_image_resource_sptr save_image = img;
00206 if (byte)
00207 {
00208 vil_image_view<unsigned char> byte_view = brip_vil_float_ops::convert_to_byte(img);
00209 save_image = vil_new_image_resource_of_view(byte_view);
00210 }
00211 if (!vil_save_image_resource(save_image, image_file.c_str(), type.c_str() ))
00212 vcl_cerr << "bmvv_cal_manager::save_image operation failed\n";
00213 }
00214
00215 void bmvv_cal_manager::adjust_contrast()
00216 {
00217 if (!itab_)
00218 return;
00219 bgui_range_adjuster_tableau_sptr h= bgui_range_adjuster_tableau_new(itab_);
00220 h->set_hardware(true);
00221 h->update();
00222 vgui_viewer2D_tableau_sptr v = vgui_viewer2D_tableau_new(h);
00223 vgui_shell_tableau_sptr s = vgui_shell_tableau_new(v);
00224
00225 vgui_dialog contrast("Histogram Range Adjuster");
00226 contrast.inline_tableau(s, 280, 200);
00227 if (!contrast.ask())
00228 return;
00229 }
00230
00231
00232
00233
00234 void bmvv_cal_manager::clear_display()
00235 {
00236 if (btab_)
00237 btab_->clear_all();
00238 else
00239 vcl_cout << "In bmvv_cal_manager::clear_display() - null tableau\n";
00240 }
00241
00242
00243
00244
00245 void bmvv_cal_manager::clear_selected()
00246 {
00247 if (btab_)
00248 btab_->clear_all();
00249 }
00250
00251 void bmvv_cal_manager::draw_corr_point(const float x, const float y)
00252 {
00253 if (!btab_)
00254 return;
00255 btab_->set_point_radius(5.0f);
00256 btab_->set_foreground(0.0f, 1.0f, 0.0f);
00257 btab_->add_point(x, y);
00258 btab_->post_redraw();
00259 }
00260
00261
00262
00263 vgui_range_map_params_sptr bmvv_cal_manager::
00264 range_params(vil_image_resource_sptr const& image)
00265 {
00266 float gamma = 1.0;
00267 bool invert = false;
00268 bool gl_map = false;
00269 bool cache = true;
00270 unsigned min = 0, max = 255;
00271 if (image->pixel_format()==VIL_PIXEL_FORMAT_BYTE)
00272 {
00273 vil_image_view<unsigned char> temp = image->get_view();
00274 unsigned char vmin=0, vmax=255;
00275 vil_math_value_range<unsigned char>(temp, vmin, vmax);
00276 min = static_cast<unsigned>(vmin);
00277 max = static_cast<unsigned>(vmax);
00278 return new vgui_range_map_params(min, max, gamma, invert,
00279 gl_map, cache);
00280 }
00281 if (image->pixel_format()==VIL_PIXEL_FORMAT_UINT_16)
00282 {
00283 vil_image_view<unsigned short> temp = image->get_view();
00284 unsigned short vmin=0, vmax=60000;
00285 vil_math_value_range<unsigned short>(temp, vmin, vmax);
00286 min = static_cast<unsigned>(vmin);
00287 max = static_cast<unsigned>(vmax);
00288 gl_map = true;
00289 return new vgui_range_map_params(min, max, gamma, invert,
00290 gl_map, cache);
00291 }
00292 vcl_cout << "Image pixel format not handled\n";
00293 return new vgui_range_map_params(0, 255, gamma, invert,
00294 gl_map, cache);
00295 }
00296
00297 void bmvv_cal_manager::set_range_params()
00298 {
00299 if (!itab_||!itab_->get_image_resource())
00300 return;
00301 static double min = 0.0, max = 255;
00302 static float gamma = 1.0;
00303 static bool invert = false;
00304 static bool gl_map = false;
00305 static bool cache = false;
00306 vgui_dialog range_dlg("Set Range Map Params");
00307 range_dlg.field("Range min:", min);
00308 range_dlg.field("Range max:", max);
00309 range_dlg.field("Gamma:", gamma);
00310 range_dlg.checkbox("Invert:", invert);
00311 range_dlg.checkbox("Use GL Mapping", gl_map);
00312 range_dlg.checkbox("Cache Pixels", cache);
00313 if (!range_dlg.ask())
00314 return;
00315 vil_image_resource_sptr img = itab_->get_image_resource();
00316 unsigned n_components = img->nplanes();
00317 vgui_range_map_params_sptr rmps;
00318 if (n_components == 1)
00319 rmps= new vgui_range_map_params(min, max, gamma, invert,
00320 gl_map, cache);
00321 else if (n_components == 3)
00322 rmps = new vgui_range_map_params(min, max, min, max, min, max,
00323 gamma, gamma, gamma, invert,
00324 gl_map, cache);
00325 else
00326 rmps = 0;
00327 itab_->set_mapping(rmps);
00328 }
00329
00330 void bmvv_cal_manager::load_image_and_camera()
00331 {
00332 static bool greyscale = false;
00333 static vcl_string cam_file = "";
00334 static vcl_string cam_ext = "*.cam";
00335 static vcl_string image_file = "";
00336 static vcl_string ext = "*.*";
00337 vgui_dialog image_cam_dlg("Read Image and Cam");
00338 image_cam_dlg.file("Image Filename:", ext, image_file);
00339 image_cam_dlg.file("Camera File", cam_ext, cam_file);
00340 image_cam_dlg.checkbox("greyscale ", greyscale);
00341 if (!image_cam_dlg.ask())
00342 return;
00343 vil_image_resource_sptr temp = vil_load_image_resource(image_file.c_str());
00344 vgui_range_map_params_sptr rmps = range_params(temp);
00345 this->add_image(temp, rmps, greyscale);
00346 vcl_ifstream cam_istr(cam_file.c_str());
00347 cam_istr >> cam_;
00348 vcl_cout << "Read Camera " << cam_ << '\n';
00349 this->project_world();
00350 }
00351
00352 void bmvv_cal_manager::load_corrs()
00353 {
00354 vgui_dialog corr_dlg("Load Correspondences");
00355 static vcl_string corr_file = "";
00356 static vcl_string corr_ext = "*.cm";
00357 corr_dlg.file("Correspondence File", corr_ext, corr_file);
00358 if (!corr_dlg.ask())
00359 return;
00360 vcl_ifstream corr_istr(corr_file.c_str());
00361 this->clear_correspondences();
00362 world_.clear();
00363 world_.resize(0);
00364 if (!brct_algos::read_target_corrs(corr_istr, corrs_valid_, corrs_, world_))
00365 {
00366 vcl_cout << "Failed to read correspondences\n";
00367 return ;
00368 }
00369 if (!btab_)
00370 return;
00371 btab_->clear_all();
00372 this->project_world();
00373
00374 }
00375
00376 void bmvv_cal_manager::save_corrs()
00377 {
00378 vgui_dialog corr_dlg("Save Correspondences");
00379 static vcl_string corr_file = "";
00380 static vcl_string corr_ext = "*.cm";
00381 corr_dlg.file("Correspondence File", corr_ext, corr_file);
00382 if (!corr_dlg.ask())
00383 return;
00384 vcl_ofstream corr_ostr(corr_file.c_str());
00385 if (!brct_algos::write_corrs(corr_ostr, corrs_valid_, corrs_, world_))
00386 {
00387 vcl_cout << "Failed to write correspondences\n";
00388 return ;
00389 }
00390 }
00391
00392 void bmvv_cal_manager::save_camera()
00393 {
00394 vgui_dialog cam_dlg("Save Camera");
00395 static vcl_string cam_file = "";
00396 static vcl_string cam_ext = "*.cam";
00397 static bool target = false;
00398 cam_dlg.file("Camera File", cam_ext, cam_file);
00399 cam_dlg.checkbox("Target?", target);
00400 if (!cam_dlg.ask())
00401 return;
00402 vcl_ofstream cam_ostr(cam_file.c_str());
00403 if (!cam_ostr)
00404 {
00405 vcl_cout << "Bad camera file\n";
00406 return;
00407 }
00408 if (!target) {
00409 cam_ostr << cam_;
00410 cam_ostr.close();
00411 return;
00412 }
00413 brct_algos::write_target_camera(cam_ostr, cam_.get_matrix());
00414 }
00415
00416 void bmvv_cal_manager::set_identity_camera()
00417 {
00418 vnl_matrix_fixed<double,3,4> M;
00419 M[0][0] = 1.0; M[0][1] = 0.0; M[0][2] = 0.0; M[0][3] = 0.0;
00420 M[1][0] = 0.0; M[1][1] = 1.0; M[1][2] = 0.0; M[1][3] = 0.0;
00421 M[2][0] = 0.0; M[2][1] = 0.0; M[2][2] = 0.0; M[2][3] = 1.0;
00422 cam_ = vgl_p_matrix<double>(M);
00423 }
00424
00425 void bmvv_cal_manager::load_world()
00426 {
00427 vgui_dialog world_dlg("Load World Points3D");
00428 static vcl_string world_file = "";
00429 static vcl_string world_ext = "*.wd";
00430 world_dlg.file("World Point File", world_ext, world_file);
00431 if (!world_dlg.ask())
00432 return;
00433 vcl_ifstream world_istr(world_file.c_str());
00434 this->clear_correspondences();
00435 this->clear_world();
00436 if (!brct_algos::read_world(world_istr, world_, polys_, indexed_face_set_))
00437 {
00438 vcl_cout << "Failed to read world\n";
00439 return ;
00440 }
00441
00442 if (!btab_)
00443 return;
00444 btab_->clear();
00445
00446 int n = world_.size();
00447 corrs_.resize(n, vgl_point_2d<double>(0,0));
00448 corr_sovs_.resize(n, (vgui_soview2D_point*)0);
00449 corrs_valid_.resize(n, false);
00450 this->project_world();
00451 }
00452
00453 void bmvv_cal_manager::save_world()
00454 {
00455 vgui_dialog world_dlg("Save World");
00456 static vcl_string world_file = "";
00457 static vcl_string world_ext = "*.wd";
00458 world_dlg.file("World File", world_ext, world_file);
00459 if (!world_dlg.ask())
00460 return;
00461 vcl_ofstream world_ostr(world_file.c_str());
00462 brct_algos::write_world(world_ostr, world_, indexed_face_set_);
00463 }
00464
00465 void bmvv_cal_manager::save_world_ply2()
00466 {
00467 vgui_dialog world_dlg("Save World Ply2");
00468 static vcl_string world_file = "";
00469 static vcl_string world_ext = "*.ply2";
00470 world_dlg.file("Ply2 File", world_ext, world_file);
00471 if (!world_dlg.ask())
00472 return;
00473 vcl_ofstream world_ostr(world_file.c_str());
00474 brct_algos::write_world_ply2(world_ostr, world_, indexed_face_set_);
00475 }
00476
00477 bool bmvv_cal_manager::draw_correspondences()
00478 {
00479 if (!btab_)
00480 return false;
00481 btab_->set_point_radius(5.0f);
00482 btab_->set_foreground(0.0f, 1.0f, 1.0f);
00483 unsigned i = 0;
00484 for (vcl_vector<vgl_point_2d<double> >::iterator pit = corrs_.begin();
00485 pit != corrs_.end(); ++pit, ++i)
00486 if (corrs_valid_[i])
00487 corr_sovs_.push_back(btab_->add_point(float((*pit).x()), float((*pit).y())));
00488 else
00489 corr_sovs_.push_back((vgui_soview2D_point*)0);
00490 btab_->post_redraw();
00491 return true;
00492 }
00493
00494 void bmvv_cal_manager::read_world_ply2()
00495 {
00496 vgui_dialog world_dlg("Read World Ply2");
00497 static vcl_string world_file = "";
00498 static vcl_string world_ext = "*.ply2";
00499 world_dlg.file("Ply2 File", world_ext, world_file);
00500 if (!world_dlg.ask())
00501 return;
00502 vcl_ifstream world_istr(world_file.c_str());
00503 brct_algos::read_world_ply2(world_istr, world_, polys_, indexed_face_set_);
00504 this->project_world();
00505 }
00506
00507 void bmvv_cal_manager::clear_correspondences()
00508 {
00509 if (!btab_)
00510 return;
00511 btab_->clear_all();
00512 corrs_.clear();
00513 corr_sovs_.clear();
00514 corrs_valid_.clear();
00515 corrs_.resize(0);
00516 corrs_valid_.resize(0);
00517 corr_sovs_.resize(0);
00518 }
00519
00520 bool bmvv_cal_manager::draw_projected_world_points()
00521 {
00522 if (!btab_)
00523 return false;
00524 int i = 0;
00525 point_3d_map_.clear();
00526 btab_->set_point_radius(5.0f);
00527 btab_->set_foreground(1.0f, 1.0f, 0.2f);
00528 for (vcl_vector<vgl_point_2d<double> >::iterator pit = proj_image_pts_.begin();
00529 pit != proj_image_pts_.end(); pit++, ++i)
00530 {
00531 vgui_soview2D_point* sov = btab_->add_point(float((*pit).x()), float((*pit).y()));
00532 int id = sov->get_id();
00533 point_3d_map_[id]=i;
00534 }
00535 btab_->post_redraw();
00536 return true;
00537 }
00538
00539
00540 int bmvv_cal_manager::get_selected_proj_world_pt(vgl_point_2d<double>& pt)
00541 {
00542 if (!btab_)
00543 return -1;
00544 vcl_vector<unsigned> ids = btab_->get_selected();
00545
00546 int n = ids.size();
00547 if (!n)
00548 {
00549 vcl_cout << "Nothing selected\n";
00550 return -1;
00551 }
00552 unsigned int i = point_3d_map_[ids[n-1]];
00553 if (i<proj_image_pts_.size())
00554 {
00555 pt = proj_image_pts_[i];
00556 return i;
00557 }
00558 vcl_cout << "Bogus correspondence\n";
00559 return -1;
00560 }
00561
00562 void bmvv_cal_manager::pick_correspondence()
00563 {
00564 if (!world_.size())
00565 {
00566 vcl_cout << "Can't pick correspondence - null 3D world\n";
00567 return;
00568 }
00569 vgl_point_2d<double> pt;
00570 int id = this->get_selected_proj_world_pt(pt);
00571 if (id<0)
00572 return;
00573 vcl_cout << "Projected world point " << pt << '\n';
00574 if (!ptab_)
00575 {
00576 vcl_cout << "Can't pick correspondence - null picker tableau\n";
00577 return;
00578 }
00579 ptab_->set_color(0.0f, 1.0f, 1.0f);
00580 ptab_->set_line_width(3.0f);
00581 float x, y;
00582 ptab_->anchored_pick_point(float(pt.x()), float(pt.y()), &x, &y);
00583 corrs_[id].set(x, y);
00584 corrs_valid_[id]=true;
00585 ptab_->set_color();
00586 ptab_->set_line_width();
00587
00588 if (!btab_)
00589 return;
00590 btab_->set_foreground(0.0f, 1.0f, 1.0f);
00591 btab_->set_point_radius(5.0);
00592 if (!corr_sovs_[id])
00593 corr_sovs_[id]=btab_->add_point(x, y);
00594 else {
00595 corr_sovs_[id]->x = x;
00596 corr_sovs_[id]->y = y;
00597 }
00598 btab_->post_redraw();
00599 }
00600
00601 void bmvv_cal_manager::remove_correspondence()
00602 {
00603 if (!world_.size())
00604 {
00605 vcl_cout << "Can't remove correspondence - null 3D world\n";
00606 return;
00607 }
00608 vgl_point_2d<double> pt;
00609 int id = this->get_selected_proj_world_pt(pt);
00610 if (id<0)
00611 return;
00612 corrs_[id].set(0, 0);
00613 corrs_valid_[id]=false;
00614 corr_sovs_[id]=(vgui_soview2D_point*)0;
00615 if (!btab_)
00616 {
00617 vcl_cout << "Correspondence removal aborted in progress- null btab\n";
00618 return;
00619 }
00620 this->project_world();
00621
00622 }
00623
00624 void bmvv_cal_manager::pick_vertical()
00625 {
00626 ptab_->set_color(0.0f, 1.0f, 0.0f);
00627 ptab_->set_line_width(3.0f);
00628 float x1, y1,x2, y2;
00629 ptab_->pick_line(&x1, &y1, &x2, &y2);
00630 vgl_point_2d<double> p1(x1, y1), p2(x2,y2);
00631 vgl_line_segment_2d<double> vertical(p1, p2);
00632 verticals_.push_back(vertical);
00633 ptab_->set_color();
00634 ptab_->set_line_width();
00635 if (!btab_)
00636 return;
00637 btab_->set_foreground(0.0f, 1.0f, 0.0f);
00638 btab_->add_line(x1,y1,x2,y2);
00639 btab_->post_redraw();
00640 }
00641
00642 void bmvv_cal_manager::project_world()
00643 {
00644 if (!btab_)
00645 {
00646 vcl_cout << "Can't project world - null btab\n";
00647 return;
00648 }
00649 btab_->clear_all();
00650 brct_algos::project(world_, cam_, proj_image_pts_);
00651 this->draw_projected_world_points();
00652 this->draw_polygons_3d(false, 0.0f, 1.0f, 0.0f);
00653 this->draw_correspondences();
00654 }
00655
00656 namespace
00657 {
00658
00659
00660 void flip_camera(vpgl_perspective_camera<double> &camera,
00661 const vcl_vector< vgl_homg_point_3d<double> >& world_hpts)
00662 {
00663 vgl_vector_3d<double> centroid(0.0, 0.0, 0.0);
00664 unsigned int num_behind = 0;
00665 for (unsigned i = 0; i<world_hpts.size(); ++i){
00666 if (camera.is_behind_camera(world_hpts[i])){
00667 vgl_point_3d<double> p(world_hpts[i]);
00668 centroid += vgl_vector_3d<double>(p.x(),p.y(),p.z());
00669 ++num_behind;
00670 }
00671 }
00672 centroid /= num_behind;
00673
00674 vgl_point_3d<double> C = camera.get_camera_center();
00675 vcl_cout << "initial center: "<< C<<vcl_endl;
00676 C += 2*(vgl_point_3d<double>(centroid.x(),centroid.y(),centroid.z())-C);
00677 camera.set_camera_center(C);
00678 vcl_cout << "new center: " <<C<<vcl_endl;
00679 }
00680
00681 };
00682
00683 void bmvv_cal_manager::solve_camera()
00684 {
00685 static bool planar = false;
00686 static bool deg_planar = false;
00687 static bool optimize = true;
00688 static bool restore = false;
00689 vgui_dialog read_homg_dlg("Solve Camera");
00690 read_homg_dlg.checkbox("Planar Camera Only? ", planar);
00691 read_homg_dlg.checkbox("Mostly Planar Camera? ", deg_planar);
00692 read_homg_dlg.checkbox("Optimize? ", optimize);
00693 read_homg_dlg.checkbox("Restore Previous Camera? ", restore);
00694 if (!read_homg_dlg.ask())
00695 return;
00696 if (restore)
00697 {
00698 cam_=prev_cam_;
00699 return;
00700 }
00701
00702 if (planar || deg_planar)
00703 {
00704 vcl_vector<double> image_y;
00705 vcl_vector< vgl_point_2d<double> > zero_Z_image_corr;
00706 vcl_vector< vgl_point_3d<double> > zero_Z_pts;
00707 vcl_vector< vgl_point_3d<double> > non_zero_Z_pts;
00708 unsigned int n = world_.size();
00709 for (unsigned i = 0; i<n; i++)
00710 {
00711 if (!corrs_valid_[i])
00712 continue;
00713 if (vcl_fabs(world_[i].z()) < 0.01)
00714 {
00715 zero_Z_pts.push_back(world_[i]);
00716 zero_Z_image_corr.push_back(corrs_[i]);
00717 }
00718 else
00719 {
00720 image_y.push_back(corrs_[i].y());
00721 non_zero_Z_pts.push_back(world_[i]);
00722 }
00723 }
00724 vgl_h_matrix_2d<double> H;
00725 if (!brct_algos::homography(zero_Z_pts, zero_Z_image_corr, H, optimize))
00726 {
00727 vcl_cout << "Linear SVD solve for homography failed\n";
00728 return;
00729 }
00730
00731 prev_cam_ = cam_;
00732 if (!planar)
00733 cam_= brct_algos::p_from_h(H,image_y, non_zero_Z_pts);
00734 else
00735 cam_= brct_algos::p_from_h(H);
00736 }
00737 else
00738 {
00739 vcl_vector< vgl_homg_point_2d<double> > image_hpts;
00740 vcl_vector< vgl_homg_point_3d<double> > world_hpts;
00741 unsigned int n = world_.size();
00742 for (unsigned i = 0; i<n; i++)
00743 {
00744 if (!corrs_valid_[i])
00745 continue;
00746 image_hpts.push_back(vgl_homg_point_2d<double>(corrs_[i]));
00747 world_hpts.push_back(vgl_homg_point_3d<double>(world_[i]));
00748 }
00749 vpgl_proj_camera<double> camera;
00750 vpgl_proj_camera_compute::compute(image_hpts,world_hpts,camera);
00751 prev_cam_ = cam_;
00752 cam_ = vgl_p_matrix<double>(camera.get_matrix());
00753
00754 vpgl_perspective_camera<double> p_camera;
00755 if (optimize && vpgl_perspective_decomposition(camera.get_matrix(),p_camera)){
00756 vcl_vector< vgl_point_2d<double> > image_pts;
00757 unsigned int num_behind = 0;
00758 for (unsigned i = 0; i<image_hpts.size(); i++){
00759 if (p_camera.is_behind_camera(world_hpts[i]))
00760 ++num_behind;
00761 image_pts.push_back(image_hpts[i]);
00762 }
00763 if (num_behind > world_hpts.size()/2){
00764 vcl_cout << "Majority of points behind camera, flipping" << vcl_endl;
00765 flip_camera(p_camera, world_hpts);
00766 }
00767 p_camera = vpgl_optimize_camera::opt_orient_pos_cal(p_camera, world_hpts, image_pts);
00768 cam_ = vgl_p_matrix<double>(p_camera.get_matrix());
00769 }
00770 }
00771
00772 if (!btab_)
00773 return;
00774 btab_->clear_all();
00775 this->project_world();
00776
00777 }
00778
00779
00780 void bmvv_cal_manager::
00781 draw_vsol_points(const int cam, vcl_vector<vsol_point_2d_sptr> const & points,
00782 bool clear, const float r, const float g, const float b)
00783 {
00784 if (!btab_)
00785 {
00786 vcl_cout << "In bmvv_cal_manager::draw_vsol_points(..) -"
00787 << " null btol tableau for pane " << cam << vcl_endl;
00788 return;
00789 }
00790 if (clear)
00791 btab_->clear_all();
00792 vgui_style_sptr style = vgui_style::new_style(r, g, b, 3, 0);
00793 for (vcl_vector<vsol_point_2d_sptr>::const_iterator pit = points.begin();
00794 pit != points.end(); pit++)
00795 btab_->add_vsol_point_2d(*pit, style);
00796 }
00797
00798 void bmvv_cal_manager::
00799 draw_vsol_point(const int cam, vsol_point_2d_sptr const & point,
00800 bool clear, const float r, const float g, const float b)
00801 {
00802 if (!btab_)
00803 {
00804 vcl_cout << "In bmvv_cal_manager::draw_vsol_point(..) -"
00805 << " null btol tableau for pane " << cam << vcl_endl;
00806 return;
00807 }
00808 if (clear)
00809 btab_->clear_all();
00810 vgui_style_sptr style = vgui_style::new_style(r, g, b, 3, 0);
00811 btab_->add_vsol_point_2d(point,style);
00812 }
00813
00814
00815 void bmvv_cal_manager::compute_ransac_homography()
00816 {
00817 vgui_dialog read_homg_dlg("Read Correspondence File");
00818 static vcl_string corr_filename = "";
00819 static vcl_string corr_ext = "*.cm";
00820 static vcl_string cam_filename = "";
00821 static vcl_string cam_ext = "*.cam";
00822 static bool show_projected_points = true;
00823 static bool optimize = true;
00824 vcl_vector<vcl_string> choices;
00825 static int choice=0;
00826 choices.push_back("Linear SVD");
00827 choices.push_back("RANSAC");
00828 choices.push_back("MUSE");
00829 read_homg_dlg.file("TargetJr correspondence file", corr_ext, corr_filename);
00830 read_homg_dlg.file("TargetJr camera file", cam_ext, cam_filename);
00831 read_homg_dlg.checkbox("Show Projected Points ",show_projected_points);
00832 read_homg_dlg.choice("Homography Algo.", choices, choice);
00833 read_homg_dlg.checkbox("Optimize? ", optimize);
00834 if (!read_homg_dlg.ask())
00835 return;
00836 if (corr_filename == ""||cam_filename == "")
00837 {
00838 vcl_cout << "Need a file name\n";
00839 return;
00840 }
00841
00842 this->clear_display();
00843 vcl_ifstream istr(corr_filename.c_str());
00844 vcl_ofstream ostr(cam_filename.c_str());
00845 vcl_string target_file = cam_filename + "-target";
00846 vcl_ofstream ostr_tar(target_file.c_str());
00847 vcl_vector<bool> valid;
00848 vcl_vector<vgl_point_2d<double> > image_points;
00849 vcl_vector<vgl_point_3d<double> > world_points;
00850 if (!brct_algos::read_target_corrs(istr, valid, image_points, world_points))
00851 {
00852 vcl_cout << "Failed to read correspondences\n";
00853 return;
00854 }
00855 bool show = show_projected_points;
00856
00857 vgl_h_matrix_2d<double> H;
00858 switch (choice)
00859 {
00860 case 0:
00861 if (!brct_algos::homography(world_points, image_points, H, optimize))
00862 show = false;
00863 break;
00864 case 1:
00865 if (!brct_algos::homography_ransac(world_points, image_points, H, optimize))
00866 show = false;
00867 break;
00868 case 2:
00869 if (!brct_algos::homography_muse(world_points, image_points, H, optimize))
00870 show = false;
00871 break;
00872 default:
00873 assert(!"choice should be one of 0, 1, or 2");
00874 }
00875 vcl_vector<vgl_point_2d<double> > proj_image_points;
00876 vgl_p_matrix<double> P = brct_algos::p_from_h(H);
00877 brct_algos::project(world_points, P, proj_image_points);
00878
00879 if (!btab_)
00880 return;
00881 vgui_style_sptr r_style = vgui_style::new_style(1.0, 0.0, 0.0, 5, 0);
00882 vgui_style_sptr g_style = vgui_style::new_style(0.0, 1.0, 0.0, 5, 0);
00883 for (unsigned int i = 0; i<world_points.size(); i++)
00884 {
00885 vgl_point_2d<double> ip = image_points[i];
00886 vgl_point_2d<double> pip = proj_image_points[i];
00887 vsol_point_2d_sptr vip = new vsol_point_2d(ip.x(),ip.y());
00888 vsol_point_2d_sptr vpip = new vsol_point_2d(pip.x(),pip.y());
00889 vcl_cout << ip << " == " << pip << vcl_endl;
00890 btab_->add_vsol_point_2d(vip,r_style);
00891 if (show) btab_->add_vsol_point_2d(vpip,g_style);
00892 }
00893 btab_->post_redraw();
00894
00895
00896 ostr << P;
00897
00898 brct_algos::write_target_camera(ostr_tar, P.get_matrix());
00899 }
00900
00901
00902 void bmvv_cal_manager::map_image_to_world()
00903 {
00904 vil_image_resource_sptr img = itab_->get_image_resource();
00905 if (!img)
00906 return;
00907 vil_image_resource_sptr world_image =
00908 brct_algos::map_image_to_world(img, cam_);
00909 if (world_image)
00910 {
00911 vgui_range_map_params_sptr rmps = range_params(world_image);
00912 this->add_image(world_image, rmps);
00913 }
00914 }
00915
00916 void bmvv_cal_manager::save_constraints()
00917 {
00918 vgui_dialog cnst_dlg("Save Constraints");
00919 static vcl_string con_file = "";
00920 static vcl_string con_ext = "*.con";
00921 cnst_dlg.file("Constraint File", con_ext, con_file);
00922 if (!cnst_dlg.ask())
00923 return;
00924 vcl_ofstream con_ostr(con_file.c_str());
00925 if (!con_ostr)
00926 {
00927 vcl_cout << "Bad constraint file\n";
00928 return;
00929 }
00930 if (!brct_algos::save_constraint_file(corrs_, corrs_valid_, world_, verticals_, con_ostr))
00931 {
00932 vcl_cout << "Couldn't save constraints\n";
00933 return;
00934 }
00935 }
00936
00937
00938
00939 void bmvv_cal_manager::add_poly_vertices_to_world_pts(vsol_polygon_3d_sptr const& poly)
00940 {
00941 unsigned nv = poly->size();
00942 vcl_vector<unsigned> vert_indices(nv);
00943 for (unsigned i = 0; i<nv; ++i)
00944 {
00945 vsol_point_3d_sptr v3d = poly->vertex(i);
00946 vgl_point_3d<double> p(v3d->x(), v3d->y(), v3d->z());
00947 world_.push_back(p);
00948 vert_indices[i]=world_.size()-1;
00949 }
00950 indexed_face_set_.push_back(vert_indices);
00951 }
00952
00953
00954 void bmvv_cal_manager::confirm_polygon()
00955 {
00956 if (!new_poly_)
00957 return;
00958 add_poly_vertices_to_world_pts(new_poly_);
00959 polys_.push_back(new_poly_);
00960 this->project_world();
00961 }
00962
00963 void bmvv_cal_manager::pick_polygon()
00964 {
00965 vsol_polygon_2d_sptr poly;
00966 ptab_->pick_polygon(poly);
00967 new_poly_ = brct_algos::back_project(poly, cam_, height_);
00968 this->draw_vsol_polygon_3d(new_poly_, false, 1.0f, 0.0f, 1.0f);
00969 btab_->post_redraw();
00970 }
00971
00972 void bmvv_cal_manager::draw_vsol_polygon_3d(vsol_polygon_3d_sptr const & poly,
00973 bool clear,
00974 const float r,
00975 const float g,
00976 const float b)
00977 {
00978 if (!btab_)
00979 {
00980 vcl_cerr << "In bmvv_cal_manager::draw_vsol_polygon() - null btol tableau\n";
00981 return;
00982 }
00983 if (clear)
00984 btab_->clear_all();
00985 vsol_polygon_2d_sptr poly_2d = brct_algos::project(poly,cam_);
00986 vgui_style_sptr style = vgui_style::new_style(r, g, b, 1, 3);
00987 bgui_vsol_soview2D_polygon* sov = btab_->add_vsol_polygon_2d(poly_2d,style);
00988 sov->set_selectable(false);
00989 }
00990
00991 void bmvv_cal_manager::draw_polygons_3d(bool clear,
00992 const float r,
00993 const float g,
00994 const float b)
00995 {
00996 if (clear)
00997 btab_->clear_all();
00998 for (vcl_vector<vsol_polygon_3d_sptr>::iterator pit = polys_.begin();
00999 pit != polys_.end(); ++pit)
01000 this->draw_vsol_polygon_3d(*pit, false, r, g, b);
01001 }
01002
01003
01004 void bmvv_cal_manager::create_box()
01005 {
01006
01007 vsol_polygon_2d_sptr poly;
01008 ptab_->pick_polygon(poly);
01009 if (!poly||poly->size()!=3)
01010 {
01011 vcl_cout << "bad box corner pick\n";
01012 return;
01013 }
01014 vsol_polygon_3d_sptr top = brct_algos::back_project(poly, cam_, height_);
01015 vsol_point_3d_sptr p0=top->vertex(0), p1=top->vertex(1), p2=top->vertex(2);
01016 vgl_point_3d<double> c0(p0->x(), p0->y(), p0->z());
01017 vgl_point_3d<double> c1(p1->x(), p1->y(), p1->z());
01018 vgl_point_3d<double> c2(p2->x(), p2->y(), p2->z());
01019
01020 vcl_vector<vgl_point_3d<double> > points;
01021 vcl_vector<vsol_polygon_3d_sptr> polys;
01022 vcl_vector<vcl_vector<unsigned> > indexed_face_set;
01023 brct_algos::box_3d(c0, c1, c2, points, polys, indexed_face_set);
01024
01025 unsigned vi0 = world_.size();
01026 for (vcl_vector<vgl_point_3d<double> >::iterator pt = points.begin();
01027 pt != points.end(); ++pt)
01028 world_.push_back(*pt);
01029
01030 for (vcl_vector<vsol_polygon_3d_sptr>::iterator pl = polys.begin();
01031 pl != polys.end(); ++pl)
01032 polys_.push_back(*pl);
01033
01034 for (vcl_vector<vcl_vector<unsigned> >::iterator ifs=indexed_face_set.begin();
01035 ifs != indexed_face_set.end(); ++ifs)
01036 {
01037 vcl_vector<unsigned> vi = *ifs;
01038 vcl_vector<unsigned> index(4);
01039 for (unsigned i = 0; i<4; ++i)
01040 index[i] = vi[i]+vi0;
01041 indexed_face_set_.push_back(index);
01042 }
01043 this->project_world();
01044 }
01045
01046
01047 void bmvv_cal_manager::ply2_to_vrml()
01048 {
01049 static float r = 0.0, g = 0.8f, b = 0.2f;
01050 vgui_dialog trans_dlg("Ply2 to VRML2.0");
01051 static vcl_string ply2_file = "";
01052 static vcl_string ply2_ext = "*.ply2";
01053 trans_dlg.file("Ply2 File", ply2_ext, ply2_file);
01054 static vcl_string vrml_file = "";
01055 static vcl_string vrml_ext = "*.wrl";
01056 trans_dlg.file("VRML File", vrml_ext, vrml_file);
01057 trans_dlg.field("r ", r);
01058 trans_dlg.field("g ", g);
01059 trans_dlg.field("b ", b);
01060 if (!trans_dlg.ask())
01061 return;
01062 vcl_ifstream istr(ply2_file.c_str());
01063 vcl_ofstream ostr(vrml_file.c_str());
01064 if (!brct_algos::translate_ply2_to_vrml(istr, ostr, r, g, b))
01065 vcl_cout << "Convert Ply to VRML Failed\n";
01066 }
01067
01068
01069 void bmvv_cal_manager::set_height()
01070 {
01071 static double height = 0.0;
01072 vgui_dialog box_dlg("Create Plane Z");
01073 box_dlg.field("Plane Z", height);
01074 if (!box_dlg.ask())
01075 return;
01076 height_ = height;
01077 }
01078
01079 void bmvv_cal_manager::clear_world()
01080 {
01081 world_.clear();
01082 world_.resize(0);
01083 polys_.clear();
01084 polys_.resize(0);
01085 indexed_face_set_.clear();
01086 indexed_face_set_.resize(0);
01087 this->project_world();
01088 }