00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "firestation.h"
00024 #include "mirror_calib.h"
00025 #include "color_train_widget.h"
00026 #include "fuse_transfer_widget.h"
00027
00028 #include <fvwidgets/fuse_image_list_widget.h>
00029 #include <gui_utils/avahi_dispatcher.h>
00030
00031 #include <cams/fileloader.h>
00032 #include <cams/shmem.h>
00033 #include <cams/net.h>
00034
00035 #include <fvutils/ipc/shm_image.h>
00036 #include <fvutils/color/conversions.h>
00037 #include <fvutils/color/yuv.h>
00038 #include <fvutils/colormap/yuvcm.h>
00039 #include <fvutils/scalers/lossy.h>
00040 #include <fvutils/system/camargp.h>
00041 #include <fvutils/writers/jpeg.h>
00042 #include <fvutils/writers/fvraw.h>
00043 #include <fvutils/draw/drawer.h>
00044
00045 #include <core/exception.h>
00046
00047 #include <gdkmm/pixbuf.h>
00048
00049 #include <arpa/inet.h>
00050
00051 #include <iostream>
00052
00053 using namespace std;
00054 using namespace fawkes;
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 Firestation::Firestation(Glib::RefPtr<Gnome::Glade::Xml> ref_xml)
00065 {
00066
00067 m_wnd_main = dynamic_cast<Gtk::Window*>( get_widget(ref_xml, "wndMain") );
00068
00069 m_img_image = dynamic_cast<Gtk::Image*>( get_widget(ref_xml, "imgImage") );
00070 m_img_image->signal_size_allocate().connect( sigc::mem_fun(*this, &Firestation::resize_image) );
00071
00072 m_evt_image = dynamic_cast<Gtk::EventBox*>( get_widget(ref_xml, "evtImageEventBox") );
00073 m_evt_image->signal_button_press_event().connect( sigc::mem_fun(*this, &Firestation::image_click) );
00074
00075 m_trv_shm_image_ids = dynamic_cast<Gtk::TreeView*>( get_widget(ref_xml, "trvShmImageIds") );
00076
00077 m_stb_status = dynamic_cast<Gtk::Statusbar*>( get_widget(ref_xml, "stbStatus") );
00078
00079 m_ckb_cont_trans = dynamic_cast<Gtk::CheckButton*>( get_widget(ref_xml, "ckbContTrans") );
00080 m_ckb_cont_trans->signal_toggled().connect( sigc::mem_fun(*this, &Firestation::enable_cont_img_trans) );
00081
00082 m_spb_update_time = dynamic_cast<Gtk::SpinButton*>( get_widget(ref_xml, "spbUpdateTime") );
00083
00084
00085
00086
00087 m_tbtn_exit = dynamic_cast<Gtk::ToolButton*>( get_widget(ref_xml, "tbtnExit") );
00088 m_tbtn_exit->signal_clicked().connect( sigc::mem_fun(*this, &Firestation::exit) );
00089
00090 m_tbtn_close_camera = dynamic_cast<Gtk::ToolButton*>( get_widget(ref_xml, "tbtnCloseCamera") );
00091 m_tbtn_close_camera->signal_clicked().connect( sigc::mem_fun(*this, &Firestation::close_camera) );
00092
00093 m_tbtn_update = dynamic_cast<Gtk::ToolButton*>( get_widget(ref_xml, "tbtnUpdate") );
00094 m_tbtn_update->signal_clicked().connect( sigc::mem_fun(*this, &Firestation::update_image) );
00095
00096 m_tbtn_save = dynamic_cast<Gtk::ToolButton*>( get_widget(ref_xml, "tbtnSave") );
00097 m_tbtn_save->signal_clicked().connect( sigc::mem_fun(*this, &Firestation::save_image) );
00098
00099 m_tbtn_open_file = dynamic_cast<Gtk::ToolButton*>( get_widget(ref_xml, "tbtnOpenFile") );
00100 m_tbtn_open_file->signal_clicked().connect( sigc::mem_fun(*this, &Firestation::open_file) );
00101
00102 m_tbtn_open_folder = dynamic_cast<Gtk::ToolButton*>( get_widget(ref_xml, "tbtnOpenFolder") );
00103 m_tbtn_open_folder->signal_clicked().connect( sigc::mem_fun(*this, &Firestation::open_folder) );
00104
00105 m_tbtn_open_shm = dynamic_cast<Gtk::ToolButton*>( get_widget(ref_xml, "tbtnOpenShm") );
00106 m_tbtn_open_shm->signal_clicked().connect( sigc::mem_fun(*this, &Firestation::open_shm) );
00107
00108 m_tbtn_open_fuse = dynamic_cast<Gtk::ToolButton*>( get_widget(ref_xml, "tbtnOpenFuse") );
00109 m_tbtn_open_fuse->signal_clicked().connect( sigc::mem_fun(*this, &Firestation::open_fuse) );
00110
00111
00112
00113
00114 ref_xml->get_widget("fcdOpenImage", m_fcd_open_image);
00115 if ( !m_fcd_open_image )
00116 {
00117 throw std::runtime_error("Couldn't find fcdOpenImage.");
00118 }
00119
00120 Gtk::FileFilter* filter_jpg = new Gtk::FileFilter();
00121 filter_jpg->set_name("JPEG");
00122 filter_jpg->add_pattern("*.jpg");
00123 filter_jpg->add_pattern("*.jpeg");
00124 m_fcd_open_image->add_filter(*filter_jpg);
00125
00126 Gtk::FileFilter* filter_fvraw = new Gtk::FileFilter();
00127 filter_fvraw->set_name("FVRaw");
00128 filter_fvraw->add_pattern("*.raw");
00129 filter_fvraw->add_pattern("*.fvraw");
00130 m_fcd_open_image->add_filter(*filter_fvraw);
00131
00132 ref_xml->get_widget("fcdSaveImage", m_fcd_save_image);
00133 if ( !m_fcd_save_image )
00134 {
00135 throw std::runtime_error("Couldn't find fcdSaveImage.");
00136 }
00137 m_fcd_save_image->add_filter(*filter_jpg);
00138 m_fcd_save_image->add_filter(*filter_fvraw);
00139
00140 ref_xml->get_widget("dlgOpenShm", m_dlg_open_shm);
00141 if (!m_dlg_open_shm)
00142 {
00143 throw std::runtime_error("Couldn't find dlgOpenShm.");
00144 }
00145
00146 ref_xml->get_widget("trvShmImageIds", m_trv_shm_image_ids);
00147 if ( !m_trv_shm_image_ids )
00148 {
00149 throw std::runtime_error("Couldn't find trvShmImageIds.");
00150 }
00151 m_shm_list_store = Gtk::ListStore::create(m_shm_columns);
00152 m_trv_shm_image_ids->set_model(m_shm_list_store);
00153 m_trv_shm_image_ids->append_column("#", m_shm_columns.m_id);
00154 m_trv_shm_image_ids->append_column("Name", m_shm_columns.m_name);
00155
00156
00157 ref_xml->get_widget("dlgOpenFuse", m_dlg_open_fuse);
00158 if (!m_dlg_open_fuse)
00159 {
00160 throw std::runtime_error("Couldn't find dlgOpenFuse.");
00161 }
00162
00163 ref_xml->get_widget("ckbFuseJpeg", m_ckb_fuse_jpeg);
00164 if (! m_ckb_fuse_jpeg )
00165 {
00166 throw std::runtime_error("Couldn't find ckbFuseJpeg.");
00167 }
00168
00169 ref_xml->get_widget("trvFuseServices", m_trv_fuse_services);
00170 if ( !m_trv_fuse_services )
00171 {
00172 throw std::runtime_error("Couldn't find trvFuseServices.");
00173 }
00174 m_fuse_tree_store = Gtk::TreeStore::create(m_fuse_columns);
00175 m_trv_fuse_services->set_model(m_fuse_tree_store);
00176
00177 m_trv_fuse_services->append_column("Name", m_fuse_columns.m_name);
00178
00179
00180
00181
00182 m_ctw = new ColorTrainWidget(this);
00183 m_cmb_ct_type = dynamic_cast<Gtk::ComboBox*>( get_widget(ref_xml, "cmbCtObjectType") );
00184 m_cmb_ct_type->signal_changed().connect(sigc::mem_fun(*this, &Firestation::ct_object_changed));
00185 m_cmb_ct_type->set_active(0);
00186
00187 m_btn_ct_start = dynamic_cast<Gtk::ToggleButton*>( get_widget(ref_xml, "btnCtStart") );
00188 m_btn_ct_start->signal_clicked().connect( sigc::mem_fun(*this, &Firestation::ct_start) );
00189
00190 m_ctw->update_image().connect( sigc::mem_fun(*this, &Firestation::draw_image) );
00191 m_ctw->colormap_updated().connect( sigc::mem_fun(*this, &Firestation::on_colormap_updated) );
00192
00193 Gtk::Button* btn;
00194 btn = dynamic_cast<Gtk::Button*>( get_widget(ref_xml, "btnCtUnselect") );
00195 m_ctw->set_reset_selection_btn(btn);
00196
00197 btn = dynamic_cast<Gtk::Button*>( get_widget(ref_xml, "btnCtAdd") );
00198 m_ctw->set_add_to_colormap_btn(btn);
00199
00200 btn = dynamic_cast<Gtk::Button*>( get_widget(ref_xml, "btnCtReset") );
00201 m_ctw->set_reset_colormap_btn(btn);
00202
00203 btn = dynamic_cast<Gtk::Button*>( get_widget(ref_xml, "btnCtSaveHistos") );
00204 m_ctw->set_save_histos_btn(btn);
00205
00206 btn = dynamic_cast<Gtk::Button*>( get_widget(ref_xml, "btnCtLoadHistos") );
00207 m_ctw->set_load_histos_btn(btn);
00208
00209 btn = dynamic_cast<Gtk::Button*>( get_widget(ref_xml, "btnCtSaveColormap") );
00210 m_ctw->set_save_colormap_btn(btn);
00211
00212 btn = dynamic_cast<Gtk::Button*>( get_widget(ref_xml, "btnCtLoadColormap") );
00213 m_ctw->set_load_colormap_btn(btn);
00214
00215 Gtk::Scale* scl;
00216 scl = dynamic_cast<Gtk::Scale*>( get_widget(ref_xml, "sclCtThreshold") );
00217 m_ctw->set_threshold_scl(scl);
00218
00219 scl = dynamic_cast<Gtk::Scale*>( get_widget(ref_xml, "sclCtMinProb") );
00220 m_ctw->set_min_prob_scl(scl);
00221
00222 scl = dynamic_cast<Gtk::Scale*>( get_widget(ref_xml, "sclCtLayerSelector") );
00223 m_ctw->set_cm_layer_selector(scl);
00224
00225 Gtk::Image* img;
00226 img = dynamic_cast<Gtk::Image*>( get_widget(ref_xml, "imgCtSegmentation") );
00227 m_ctw->set_segmentation_img(img);
00228
00229 img = dynamic_cast<Gtk::Image*>( get_widget(ref_xml, "imgCtColormap") );
00230 m_ctw->set_colormap_img(img);
00231
00232 Gtk::FileChooserDialog* fcd;
00233 fcd = dynamic_cast<Gtk::FileChooserDialog*>( get_widget(ref_xml, "fcdFilechooser") );
00234 m_ctw->set_filechooser_dlg(fcd);
00235
00236
00237 m_btn_ct_seg = dynamic_cast<Gtk::ToggleButton*>( get_widget(ref_xml, "btnCtSeg") );
00238 m_btn_ct_seg->signal_toggled().connect( sigc::mem_fun(*this, &Firestation::draw_image) );
00239 m_spbtn_depth = dynamic_cast<Gtk::SpinButton*>( get_widget(ref_xml, "spbtnCtCmDepth") );
00240 m_spbtn_width = dynamic_cast<Gtk::SpinButton*>( get_widget(ref_xml, "spbtnCtCmWidth") );
00241 m_spbtn_height = dynamic_cast<Gtk::SpinButton*>( get_widget(ref_xml, "spbtnCtCmHeight") );
00242 m_ctw->set_cm_selector(m_spbtn_depth, m_spbtn_width, m_spbtn_height);
00243
00244
00245
00246
00247 m_calib_tool = new MirrorCalibTool();
00248
00249 #ifndef HAVE_BULB_CREATOR
00250 Gtk::Notebook *nb = dynamic_cast<Gtk::Notebook*>( get_widget(ref_xml, "ntbOptions") );
00251 Gtk::HBox *box = dynamic_cast<Gtk::HBox*>( get_widget(ref_xml, "boxMirrorCalib") );
00252 nb->get_tab_label(*box)->set_sensitive(false);
00253 box->set_sensitive(false);
00254 #endif
00255
00256 m_btn_mc_start = dynamic_cast<Gtk::Button*>( get_widget(ref_xml, "btnMcStart") );
00257 m_btn_mc_start->signal_clicked().connect( sigc::mem_fun(*this, &Firestation::mc_start) );
00258
00259 m_btn_mc_load = dynamic_cast<Gtk::Button*>( get_widget(ref_xml, "btnCalibLoad") );
00260 m_btn_mc_load->signal_clicked().connect( sigc::mem_fun(*this, &Firestation::mc_load) );
00261
00262 m_btn_mc_save = dynamic_cast<Gtk::Button*>( get_widget(ref_xml, "btnCalibSave") );
00263 m_btn_mc_save->signal_clicked().connect( sigc::mem_fun(*this, &Firestation::mc_save) );
00264
00265 m_ent_mc_dist = dynamic_cast<Gtk::Entry*>( get_widget(ref_xml, "entCalibDist") );
00266 m_ent_mc_ori = dynamic_cast<Gtk::Entry*>( get_widget(ref_xml, "entCalibOri") );
00267
00268 m_fcd_mc_save = dynamic_cast<Gtk::FileChooserDialog*>( get_widget(ref_xml, "fcdCalibSave") );
00269 m_fcd_mc_load = dynamic_cast<Gtk::FileChooserDialog*>( get_widget(ref_xml, "fcdCalibLoad") );
00270
00271
00272
00273
00274 m_ftw = new FuseTransferWidget();
00275
00276 Gtk::TreeView* trv = dynamic_cast<Gtk::TreeView*>( get_widget(ref_xml, "trvFuseRemoteLuts") );
00277 m_ftw->set_remote_lut_list_trv(trv);
00278 trv = dynamic_cast<Gtk::TreeView*>( get_widget(ref_xml, "trvFuseLocalLuts") );
00279 m_ftw->set_local_lut_list_trv(trv);
00280 img = dynamic_cast<Gtk::Image*>( get_widget(ref_xml, "imgFuseLocal") );
00281 m_ftw->set_local_img(img);
00282 img = dynamic_cast<Gtk::Image*>( get_widget(ref_xml, "imgFuseRemote") );
00283 m_ftw->set_remote_img(img);
00284 btn = dynamic_cast<Gtk::Button*>( get_widget(ref_xml, "btnFuseUpload") );
00285 m_ftw->set_upload_btn(btn);
00286 scl = dynamic_cast<Gtk::Scale*>( get_widget(ref_xml, "sclLocalLayerSelector") );
00287 m_ftw->set_local_layer_selector(scl);
00288 scl = dynamic_cast<Gtk::Scale*>( get_widget(ref_xml, "sclRemoteLayerSelector") );
00289 m_ftw->set_remote_layer_selector(scl);
00290
00291
00292
00293
00294 m_filw = new FuseImageListWidget();
00295 trv = dynamic_cast<Gtk::TreeView*>( get_widget(ref_xml, "trvFuseImageList") );
00296 m_filw->set_image_list_trv(trv);
00297 Gtk::CheckButton* chk = dynamic_cast<Gtk::CheckButton*>( get_widget(ref_xml, "chkFuseImageListUpdate") );
00298 m_filw->set_auto_update_chk(chk);
00299 chk = dynamic_cast<Gtk::CheckButton*>( get_widget(ref_xml, "chkFuseCompression") );
00300 m_filw->set_toggle_compression_chk(chk);
00301 m_filw->image_selected().connect( sigc::mem_fun(*this, &Firestation::on_fuse_image_selected) );
00302
00303
00304 m_yuv_orig_buffer = 0;
00305 m_yuv_draw_buffer = 0;
00306 m_yuv_scaled_buffer = 0;
00307 m_rgb_scaled_buffer = 0;
00308
00309 m_img_width = 0;
00310 m_img_height = 0;
00311 m_img_size = 0;
00312 m_img_cs = CS_UNKNOWN;
00313
00314 m_img_writer = 0;
00315 m_camera = 0;
00316 m_shm_buffer = 0;
00317
00318 m_img_src = SRC_NONE;
00319 m_op_mode = MODE_VIEWER;
00320
00321 m_cont_img_trans = false;
00322
00323 m_max_img_width = m_evt_image->get_width();
00324 m_max_img_height = m_evt_image->get_height();
00325 m_scaled_img_width = m_evt_image->get_width();
00326 m_scaled_img_height = m_evt_image->get_height();
00327 m_scale_factor = 1.0;
00328
00329 m_avahi_thread = new AvahiThread();
00330 m_avahi_dispatcher = new AvahiDispatcher;
00331
00332 m_avahi_dispatcher->signal_service_added().connect( sigc::mem_fun( *this, &Firestation::on_service_added ) );
00333 m_avahi_dispatcher->signal_service_removed().connect( sigc::mem_fun( *this, &Firestation::on_service_removed ) );
00334
00335 m_avahi_thread->watch_service("_fountain._tcp", m_avahi_dispatcher);
00336 m_avahi_thread->start();
00337 }
00338
00339
00340 Firestation::~Firestation()
00341 {
00342 free(m_yuv_orig_buffer);
00343 free(m_yuv_draw_buffer);
00344 free(m_yuv_scaled_buffer);
00345 free(m_rgb_scaled_buffer);
00346
00347 delete m_camera;
00348 delete m_img_writer;
00349
00350 delete m_calib_tool;
00351 delete m_ctw;
00352 delete m_ftw;
00353 delete m_filw;
00354
00355 delete m_avahi_thread;
00356 delete m_avahi_dispatcher;
00357
00358 delete m_wnd_main;
00359 delete m_fcd_open_image;
00360 delete m_fcd_save_image;
00361 delete m_dlg_open_shm;
00362 delete m_dlg_open_fuse;
00363 }
00364
00365 Gtk::Widget*
00366 Firestation::get_widget(Glib::RefPtr<Gnome::Glade::Xml> ref_xml,
00367 const char* widget_name) const
00368 {
00369 Gtk::Widget* widget;
00370 ref_xml->get_widget(widget_name, widget);
00371 if ( !widget )
00372 {
00373 std::string err_str = "Couldn't find widget ";
00374 err_str += std::string(widget_name);
00375 err_str += ".";
00376 throw runtime_error(err_str);
00377 }
00378
00379 return widget;
00380 }
00381
00382
00383
00384
00385 Gtk::Window&
00386 Firestation::get_window() const
00387 {
00388 return *m_wnd_main;
00389 }
00390
00391
00392 void
00393 Firestation::exit()
00394 {
00395 m_avahi_thread->cancel();
00396 m_avahi_thread->join();
00397
00398 if (SRC_NONE != m_img_src)
00399 { m_camera->close(); }
00400
00401 m_wnd_main->hide();
00402 }
00403
00404 void
00405 Firestation::close_camera()
00406 {
00407 if (SRC_NONE == m_img_src)
00408 { return; }
00409
00410 m_img_src = SRC_NONE;
00411
00412 m_camera->close();
00413 delete m_camera;
00414 m_camera = 0;
00415
00416 m_img_width = 0;
00417 m_img_height = 0;
00418 m_img_cs = CS_UNKNOWN;
00419
00420 m_img_size = 0;
00421
00422 free(m_yuv_orig_buffer);
00423 free(m_yuv_draw_buffer);
00424
00425 m_yuv_orig_buffer = 0;
00426 m_yuv_draw_buffer = 0;
00427
00428 m_img_image->clear();
00429 m_img_image->set("gtk-missing-image");
00430
00431 m_ctw->set_src_buffer(NULL, 0, 0);
00432 m_ctw->set_draw_buffer(NULL);
00433 }
00434
00435
00436 void
00437 Firestation::save_image()
00438 {
00439 if (m_img_src == SRC_NONE)
00440 { return; }
00441
00442 m_fcd_save_image->set_transient_for(*this);
00443
00444 int result = m_fcd_save_image->run();
00445
00446 switch(result)
00447 {
00448 case(Gtk::RESPONSE_OK):
00449 {
00450 delete m_img_writer;
00451
00452 Glib::ustring filter_name = m_fcd_save_image->get_filter()->get_name();
00453 if ( Glib::ustring("JPEG") == filter_name )
00454 {
00455 m_img_writer = new JpegWriter();
00456 }
00457 else if( Glib::ustring("FVRaw") == filter_name )
00458 {
00459 m_img_writer = new FvRawWriter();
00460 }
00461 else
00462 {
00463 cout << "save_file(): unknown file format" << endl;
00464 break;
00465 }
00466
00467 std::string filename = m_fcd_save_image->get_filename();
00468 m_img_writer->set_filename( filename.c_str() );
00469 m_img_writer->set_dimensions(m_img_width, m_img_height);
00470 m_img_writer->set_buffer(m_img_cs, m_yuv_orig_buffer);
00471 m_img_writer->write();
00472
00473 std::cout << "Save file: " << filename << std::endl;
00474 break;
00475 }
00476
00477 case(Gtk::RESPONSE_CANCEL):
00478 break;
00479
00480 default:
00481 break;
00482 }
00483
00484 m_fcd_save_image->hide();
00485 }
00486
00487
00488 void
00489 Firestation::update_image()
00490 {
00491 if (m_img_src == SRC_NONE)
00492 { return; }
00493
00494 try
00495 {
00496 m_camera->capture();
00497 memcpy(m_yuv_orig_buffer, m_camera->buffer(), m_img_size);
00498 memcpy(m_yuv_draw_buffer, m_camera->buffer(), m_img_size);
00499 m_camera->dispose_buffer();
00500
00501 draw_image();
00502
00503 m_ctw->draw_segmentation_result();
00504 }
00505 catch (Exception& e)
00506 {
00507 e.print_trace();
00508 }
00509 }
00510
00511 bool
00512 Firestation::call_update_image()
00513 {
00514 if ( !m_cont_img_trans )
00515 { return false; }
00516
00517 update_image();
00518
00519 return true;
00520 }
00521
00522 void
00523 Firestation::enable_cont_img_trans()
00524 {
00525 if (m_cont_img_trans)
00526 {
00527 m_cont_img_trans = false;
00528 return;
00529 }
00530
00531 int timeout = (int) rint( m_spb_update_time->get_value() );
00532 sigc::connection conn = Glib::signal_timeout().connect( sigc::mem_fun(*this, &Firestation::call_update_image), timeout);
00533 m_cont_img_trans = true;
00534 }
00535
00536
00537 void
00538 Firestation::open_file()
00539 {
00540 m_fcd_open_image->set_action(Gtk::FILE_CHOOSER_ACTION_OPEN);
00541 m_fcd_open_image->set_transient_for(*this);
00542
00543 int result = m_fcd_open_image->run();
00544
00545 switch(result)
00546 {
00547 case Gtk::RESPONSE_OK:
00548 {
00549 pre_open_img_src();
00550
00551 std::string filename = m_fcd_open_image->get_filename();
00552
00553 m_camera = new FileLoader( filename.c_str() );
00554 m_img_src = SRC_FILE;
00555 post_open_img_src();
00556
00557 break;
00558 }
00559
00560 case Gtk::RESPONSE_CANCEL:
00561 {
00562 break;
00563 }
00564
00565 default:
00566 {
00567 break;
00568 }
00569 }
00570
00571 m_fcd_open_image->hide();
00572 }
00573
00574
00575 void
00576 Firestation::open_folder()
00577 {
00578 m_fcd_open_image->set_action(Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER);
00579 m_fcd_open_image->set_transient_for(*this);
00580
00581 int result = m_fcd_open_image->run();
00582
00583 switch(result)
00584 {
00585 case Gtk::RESPONSE_OK:
00586 {
00587 pre_open_img_src();
00588
00589 std::string extension;
00590 Glib::ustring filter_name = m_fcd_save_image->get_filter()->get_name();
00591 if ( Glib::ustring("JPEG") == filter_name )
00592 { extension = "jpg"; }
00593 else if ( Glib::ustring("FVRaw") == filter_name )
00594 { extension = "raw"; }
00595
00596 std::string folder = m_fcd_open_image->get_current_folder();
00597 char* as;
00598 if (asprintf(&as, "file:file:dir=%s:ext=%s", folder.c_str(), extension.c_str()) != -1) {
00599 CameraArgumentParser cap(as);
00600 m_camera = new FileLoader( &cap );
00601 m_img_src = SRC_FILE;
00602 post_open_img_src();
00603 free(as);
00604 } else {
00605 printf("Cannot open folder, asprintf() ran out of memory");
00606 }
00607
00608 break;
00609 }
00610
00611 case Gtk::RESPONSE_CANCEL:
00612 {
00613 break;
00614 }
00615
00616 default:
00617 {
00618 break;
00619 }
00620 }
00621
00622 m_fcd_open_image->hide();
00623 }
00624
00625
00626 void
00627 Firestation::open_shm()
00628 {
00629 unsigned int num_buffers = 0;
00630 SharedMemory::SharedMemoryIterator shmit;
00631 SharedMemoryImageBufferHeader* h = new SharedMemoryImageBufferHeader;
00632 shmit = SharedMemory::find(FIREVISION_SHM_IMAGE_MAGIC_TOKEN, h);
00633
00634 if (shmit == SharedMemory::end())
00635 {
00636 m_stb_status->push("No SHM images found");
00637 return;
00638 }
00639 else
00640 {
00641 m_shm_list_store->clear();
00642
00643 while ( shmit != SharedMemory::end() )
00644 {
00645 ++num_buffers;
00646 Gtk::TreeModel::Row row = *(m_shm_list_store->append());
00647 row[m_shm_columns.m_id] = num_buffers;
00648 const SharedMemoryImageBufferHeader* h = (SharedMemoryImageBufferHeader*)*shmit;
00649 row[m_shm_columns.m_name] = h->image_id();
00650 shmit++;
00651 }
00652 }
00653
00654 m_dlg_open_shm->set_transient_for(*this);
00655
00656 int result = m_dlg_open_shm->run();
00657
00658 switch(result)
00659 {
00660 case Gtk::RESPONSE_OK:
00661 {
00662 delete m_shm_buffer;
00663
00664 Gtk::TreeModel::Path path;
00665 Gtk::TreeViewColumn* column;
00666 m_trv_shm_image_ids->get_cursor(path, column);
00667
00668 Gtk::TreeModel::iterator iter = m_shm_list_store->get_iter(path);
00669
00670 if (iter)
00671 {
00672 Gtk::TreeModel::Row row = *iter;
00673 if (row)
00674 {
00675 Glib::ustring name = row[m_shm_columns.m_name];
00676 pre_open_img_src();
00677
00678 try
00679 {
00680 m_camera = new SharedMemoryCamera( name.c_str() );
00681 }
00682 catch (Exception& e)
00683 {
00684 e.print_trace();
00685 }
00686
00687 m_img_src = SRC_SHM;
00688
00689 post_open_img_src();
00690 }
00691 }
00692 else
00693 {
00694 std::cout << "invalid iter" << std::endl;
00695 }
00696
00697 break;
00698 }
00699
00700 case Gtk::RESPONSE_CANCEL:
00701 break;
00702
00703 default:
00704 break;
00705 }
00706
00707 m_dlg_open_shm->hide();
00708 }
00709
00710
00711 void
00712 Firestation::open_fuse()
00713 {
00714 Gtk::TreeModel::Children children = m_fuse_tree_store->children();
00715 if ( 0 == children.size() )
00716 {
00717 m_stb_status->push("No FUSE services found");
00718 return;
00719 }
00720
00721 m_trv_fuse_services->expand_all();
00722 m_dlg_open_fuse->set_transient_for(*this);
00723
00724 int result = m_dlg_open_fuse->run();
00725
00726 switch(result)
00727 {
00728 case Gtk::RESPONSE_OK:
00729 {
00730 Gtk::TreeModel::Path path;
00731 Gtk::TreeViewColumn* column;
00732 m_trv_fuse_services->get_cursor(path, column);
00733
00734 Gtk::TreeModel::iterator iter = m_fuse_tree_store->get_iter(path);
00735
00736 if (iter)
00737 {
00738 Gtk::TreeModel::Row row = *iter;
00739 if (row)
00740 {
00741 Glib::ustring hostname = row[m_fuse_columns.m_service_hostname];
00742 unsigned short int port = row[m_fuse_columns.m_service_port];
00743 Glib::ustring image_id = row[m_fuse_columns.m_image_id];
00744 bool jpeg = m_ckb_fuse_jpeg->get_active();
00745
00746 pre_open_img_src();
00747
00748 try
00749 {
00750 m_camera = new NetworkCamera(hostname.c_str(), port, image_id.c_str(), jpeg);
00751 m_img_src = SRC_FUSE;
00752 post_open_img_src();
00753 }
00754 catch (Exception& e)
00755 {
00756 m_img_src = SRC_NONE;
00757 e.print_trace();
00758 }
00759 }
00760 }
00761 else
00762 {
00763 std::cout << "invalid iter" << std::endl;
00764 }
00765
00766 break;
00767 }
00768
00769 case Gtk::RESPONSE_CANCEL:
00770 break;
00771
00772 default:
00773 break;
00774 }
00775
00776 m_dlg_open_fuse->hide();
00777 }
00778
00779 void
00780 Firestation::pre_open_img_src()
00781 {
00782 if (SRC_NONE != m_img_src)
00783 {
00784 m_camera->stop();
00785 m_camera->close();
00786
00787 delete m_camera;
00788 m_camera = 0;
00789
00790 m_img_src = SRC_NONE;
00791 }
00792 }
00793
00794
00795 void
00796 Firestation::post_open_img_src()
00797 {
00798 if (m_img_src == SRC_NONE) { return; }
00799
00800 try
00801 {
00802 m_camera->open();
00803 m_camera->start();
00804 m_camera->capture();
00805 m_img_width = m_camera->pixel_width();
00806 m_img_height = m_camera->pixel_height();
00807 m_img_cs = m_camera->colorspace();
00808
00809 m_img_size = colorspace_buffer_size( m_img_cs,
00810 m_img_width,
00811 m_img_height );
00812
00813 free(m_yuv_orig_buffer);
00814 free(m_yuv_draw_buffer);
00815
00816 m_yuv_orig_buffer = (unsigned char*) malloc(m_img_size);
00817 m_yuv_draw_buffer = (unsigned char*) malloc(m_img_size);
00818 memcpy(m_yuv_orig_buffer, m_camera->buffer(), m_img_size);
00819 memcpy(m_yuv_draw_buffer, m_camera->buffer(), m_img_size);
00820
00821 m_camera->dispose_buffer();
00822
00823 m_tbtn_update->set_sensitive(true);
00824 m_tbtn_save->set_sensitive(true);
00825
00826 draw_image();
00827
00828 m_ctw->set_src_buffer(m_yuv_orig_buffer, m_img_width, m_img_height);
00829 m_ctw->set_draw_buffer(m_yuv_draw_buffer);
00830 m_ctw->draw_segmentation_result();
00831 }
00832 catch (Exception& e)
00833 {
00834 e.print_trace();
00835 printf("Opening camera failed.\n");
00836 }
00837
00838 }
00839
00840 void
00841 Firestation::on_fuse_image_selected()
00842 {
00843 string host_name;
00844 unsigned short port;
00845 string image_id;
00846 bool compression;
00847
00848 m_filw->get_selected_image(host_name, port, image_id, compression);
00849
00850 pre_open_img_src();
00851
00852 try
00853 {
00854 m_camera = new NetworkCamera( host_name.c_str(), port, image_id.c_str(), compression );
00855 m_img_src = SRC_FUSE;
00856 }
00857 catch (Exception& e)
00858 {
00859 m_img_src = SRC_NONE;
00860 e.print_trace();
00861 }
00862
00863 post_open_img_src();
00864 }
00865
00866 void
00867 Firestation::on_colormap_updated()
00868 {
00869 m_ftw->set_current_colormap( m_ctw->get_colormap() );
00870 }
00871
00872
00873 void
00874 Firestation::draw_image()
00875 {
00876 if ( m_img_src == SRC_NONE ) { return; }
00877
00878 LossyScaler scaler;
00879 scaler.set_original_buffer( m_yuv_draw_buffer );
00880 scaler.set_original_dimensions(m_img_width, m_img_height);
00881 scaler.set_scaled_dimensions(m_max_img_width, m_max_img_height);
00882
00883 unsigned int scaled_width = scaler.needed_scaled_width();
00884 unsigned int scaled_height = scaler.needed_scaled_height();
00885
00886 if (scaled_width != m_scaled_img_width || scaled_height != m_scaled_img_height)
00887 {
00888 m_scaled_img_width = scaled_width;
00889 m_scaled_img_height = scaled_height;
00890 m_scale_factor = scaler.get_scale_factor();
00891 }
00892
00893 free(m_rgb_scaled_buffer);
00894 free(m_yuv_scaled_buffer);
00895 m_yuv_scaled_buffer = (unsigned char*) malloc( colorspace_buffer_size( m_img_cs,
00896 m_scaled_img_width,
00897 m_scaled_img_height ) );
00898 scaler.set_scaled_buffer(m_yuv_scaled_buffer);
00899 scaler.scale();
00900
00901 if (m_btn_ct_seg->get_active()) {
00902 unsigned int sld_img_size = m_scaled_img_width * m_scaled_img_height;
00903 unsigned char u_seg = 255 / (unsigned int)pow(2, m_spbtn_width->get_value());
00904 unsigned char v_seg = 255 / (unsigned int)pow(2, m_spbtn_height->get_value());
00905 unsigned int u = 0;
00906 for (u = sld_img_size; u < sld_img_size + sld_img_size / 2; ++u) {
00907 m_yuv_scaled_buffer[u] = (m_yuv_scaled_buffer[u] / u_seg) * u_seg;
00908 }
00909
00910 for (; u < 2 * sld_img_size; ++u) {
00911 m_yuv_scaled_buffer[u] = (m_yuv_scaled_buffer[u] / v_seg) * v_seg;
00912 }
00913 }
00914
00915 if ( m_img_src == SRC_SHM )
00916 {
00917 SharedMemoryCamera* shm_camera = dynamic_cast<SharedMemoryCamera*>(m_camera);
00918 if ( shm_camera->shared_memory_image_buffer()->circle_found() )
00919 {
00920 Drawer drawer;
00921 drawer.set_buffer(m_yuv_scaled_buffer, m_scaled_img_width, m_scaled_img_height);
00922 drawer.set_color(YUV_t::white());
00923 unsigned int roi_x = (unsigned int) rint( shm_camera->shared_memory_image_buffer()->roi_x() * m_scale_factor );
00924 unsigned int roi_y = (unsigned int) rint( shm_camera->shared_memory_image_buffer()->roi_y() * m_scale_factor );
00925 unsigned int roi_width = (unsigned int) rint( shm_camera->shared_memory_image_buffer()->roi_width() * m_scale_factor );
00926 unsigned int roi_height = (unsigned int) rint( shm_camera->shared_memory_image_buffer()->roi_height() * m_scale_factor );
00927 drawer.draw_rectangle( roi_x, roi_y, roi_width, roi_height );
00928 }
00929 }
00930
00931 m_rgb_scaled_buffer = (unsigned char*) malloc( colorspace_buffer_size( RGB,
00932 m_scaled_img_width,
00933 m_scaled_img_height ) );
00934
00935 convert( m_img_cs, RGB,
00936 m_yuv_scaled_buffer, m_rgb_scaled_buffer,
00937 m_scaled_img_width, m_scaled_img_height );
00938
00939 Glib::RefPtr<Gdk::Pixbuf> image = Gdk::Pixbuf::create_from_data( m_rgb_scaled_buffer,
00940 Gdk::COLORSPACE_RGB,
00941 false,
00942 8,
00943 m_scaled_img_width,
00944 m_scaled_img_height,
00945 3 * m_scaled_img_width );
00946
00947 m_img_image->set(image);
00948 }
00949
00950
00951
00952
00953 void
00954 Firestation::resize_image(Gtk::Allocation& allocation)
00955 {
00956 unsigned int new_width = (unsigned int) allocation.get_width();
00957 unsigned int new_height = (unsigned int) allocation.get_height();
00958
00959 if (new_width != m_max_img_width || new_height != m_max_img_height)
00960 {
00961 m_max_img_width = new_width;
00962 m_max_img_height = new_height;
00963 draw_image();
00964 }
00965 }
00966
00967
00968
00969
00970
00971 bool
00972 Firestation::image_click(GdkEventButton* event)
00973 {
00974 unsigned int offset_x;
00975 unsigned int offset_y;
00976
00977 offset_x = (m_max_img_width - m_scaled_img_width) / 2;
00978 offset_y = (m_max_img_height - m_scaled_img_height) / 2;
00979
00980 offset_x = offset_x > m_max_img_width ? 0 : offset_x;
00981 offset_y = offset_y > m_max_img_height ? 0 : offset_y;
00982
00983 unsigned int image_x;
00984 unsigned int image_y;
00985
00986 image_x = (unsigned int)rint( (event->x - offset_x) / m_scale_factor);
00987 image_y = (unsigned int)rint( (event->y - offset_y) / m_scale_factor);
00988
00989 if ( image_x < 0 || image_x > m_img_width ||
00990 image_y < 0 || image_y > m_img_height )
00991 { return true; }
00992
00993 switch (m_op_mode)
00994 {
00995 case MODE_VIEWER:
00996 if (m_img_src != SRC_NONE)
00997 {
00998 switch( m_img_cs )
00999 {
01000 case YUV422_PLANAR:
01001 register unsigned char y;
01002 register unsigned char u;
01003 register unsigned char v;
01004 YUV422_PLANAR_YUV( m_yuv_orig_buffer,
01005 m_img_width,
01006 m_img_height,
01007 image_x,
01008 image_y,
01009 y, u, v );
01010 cout << "Y: " << (unsigned int)y
01011 << " U: " << (unsigned int)u
01012 << " V: " << (unsigned int)v << endl;
01013 break;
01014 default:
01015 cout << "Unhandled colorspace" << endl;
01016 }
01017 }
01018 break;
01019
01020 case MODE_COLOR_TRAIN:
01021 m_ctw->click(image_x, image_y, event->button);
01022 draw_image();
01023 break;
01024
01025 case MODE_MIRROR_CALIB:
01026 {
01027 m_calib_tool->step(image_x, image_y);
01028
01029 bool show;
01030 float next_dist;
01031 float next_ori;
01032 show = m_calib_tool->get_next(&next_dist, &next_ori);
01033
01034 if (show)
01035 {
01036 char* next_dist_char = (char*) malloc(10);
01037 char* next_ori_char = (char*) malloc(10);
01038
01039 sprintf(next_dist_char, "%2f", next_dist);
01040 sprintf(next_ori_char, "%2f", next_ori);
01041 m_ent_mc_dist->set_text(Glib::ustring(next_dist_char));
01042 m_ent_mc_ori->set_text(Glib::ustring(next_ori_char));
01043
01044 free(next_dist_char);
01045 free(next_ori_char);
01046 }
01047 else
01048 {
01049 m_ent_mc_dist->set_text("");
01050 m_ent_mc_ori->set_text("");
01051 }
01052
01053 break;
01054 }
01055
01056 case MODE_MIRROR_CALIB_EVAL:
01057 {
01058 float dist;
01059 float phi;
01060 m_calib_tool->eval(image_x, image_y, &dist, &phi);
01061 printf("Distance: %2f\t Phi: %2f\n", dist, phi);
01062 break;
01063 }
01064
01065 default:
01066 break;
01067 }
01068
01069 return true;
01070 }
01071
01072
01073 void
01074 Firestation::ct_start()
01075 {
01076 if (m_op_mode == MODE_COLOR_TRAIN)
01077 {
01078 m_op_mode = MODE_VIEWER;
01079 m_stb_status->push("Leaving color training mode");
01080 }
01081 else
01082 {
01083 if (m_img_src != SRC_NONE)
01084 {
01085 m_ctw->set_fg_object( ct_get_fg_object() );
01086
01087 m_op_mode = MODE_COLOR_TRAIN;
01088
01089 m_stb_status->push("Entering color training mode");
01090 }
01091 }
01092 }
01093
01094 hint_t
01095 Firestation::ct_get_fg_object()
01096 {
01097 int active = m_cmb_ct_type->get_active_row_number();
01098 switch(active)
01099 {
01100 case 0:
01101 return H_BALL;
01102
01103 case 1:
01104 return H_FIELD;
01105
01106 case 2:
01107 return H_LINE;
01108
01109 case 3:
01110 return H_ROBOT;
01111
01112 case 4:
01113 return H_ROBOT_OPP;
01114
01115 case 5:
01116 return H_GOAL_YELLOW;
01117
01118 case 6:
01119 return H_GOAL_BLUE;
01120
01121 case 7:
01122 return H_UNKNOWN;
01123
01124 default:
01125 printf("ct_get_fg_object(): UNKNOWN\n");
01126 return H_UNKNOWN;
01127 }
01128 }
01129
01130 void
01131 Firestation::ct_object_changed()
01132 {
01133 hint_t object = ct_get_fg_object();
01134 m_ctw->set_fg_object(object);
01135 }
01136
01137
01138 void
01139 Firestation::mc_start()
01140 {
01141 if (m_op_mode == MODE_MIRROR_CALIB)
01142 {
01143 m_op_mode = MODE_VIEWER;
01144 m_stb_status->push("Leaving mirror calibration mode");
01145 }
01146 else
01147 {
01148 if (m_img_src != SRC_NONE)
01149 {
01150 m_calib_tool->set_img_dimensions(m_img_width, m_img_height);
01151 m_calib_tool->start();
01152
01153 m_op_mode = MODE_MIRROR_CALIB;
01154
01155 bool show;
01156 float next_dist;
01157 float next_ori;
01158 show = m_calib_tool->get_next(&next_dist, &next_ori);
01159
01160 if (show)
01161 {
01162 char* next_dist_char = (char*) malloc(10);
01163 char* next_ori_char = (char*) malloc(10);
01164
01165 sprintf(next_dist_char, "%2f", next_dist);
01166 sprintf(next_ori_char, "%2f", next_ori);
01167 m_ent_mc_dist->set_text(Glib::ustring(next_dist_char));
01168 m_ent_mc_ori->set_text(Glib::ustring(next_ori_char));
01169
01170 free(next_dist_char);
01171 free(next_ori_char);
01172 }
01173 else
01174 {
01175 m_ent_mc_dist->set_text("");
01176 m_ent_mc_ori->set_text("");
01177 }
01178
01179 m_stb_status->push("Entering mirror calibration mode");
01180 }
01181 }
01182 }
01183
01184
01185 void
01186 Firestation::mc_load()
01187 {
01188 m_fcd_mc_load->set_transient_for(*this);
01189
01190 Gtk::FileFilter filter_mirror;
01191 filter_mirror.set_name("Mirror Calibration");
01192 filter_mirror.add_pattern("*.mirror");
01193 filter_mirror.add_pattern("*.bulb");
01194 m_fcd_mc_load->add_filter(filter_mirror);
01195
01196 int result = m_fcd_mc_load->run();
01197
01198 switch(result)
01199 {
01200 case Gtk::RESPONSE_OK:
01201 {
01202 std::string filename = m_fcd_mc_load->get_filename();
01203 m_calib_tool->load( filename.c_str() );
01204 m_op_mode = MODE_MIRROR_CALIB_EVAL;
01205 break;
01206 }
01207 case Gtk::RESPONSE_CANCEL:
01208 break;
01209 default:
01210 break;
01211 }
01212
01213 m_fcd_mc_load->hide();
01214 }
01215
01216
01217 void
01218 Firestation::mc_save()
01219 {
01220 m_fcd_mc_save->set_transient_for(*this);
01221
01222 int result = m_fcd_mc_save->run();
01223
01224 switch(result)
01225 {
01226 case(Gtk::RESPONSE_OK):
01227 {
01228 std::string filename = m_fcd_mc_save->get_filename();
01229
01230 m_calib_tool->save( filename.c_str() );
01231 break;
01232 }
01233
01234 case(Gtk::RESPONSE_CANCEL):
01235 break;
01236
01237 default:
01238 break;
01239 }
01240
01241 m_fcd_mc_save->hide();
01242
01243 }
01244
01245 void
01246 Firestation::on_service_added( NetworkService* service )
01247 {
01248 const char* host = service->host();
01249 const char* name = service->name();
01250 const char* type = service->type();
01251 const char* domain = service->domain();
01252 unsigned short int port = service->port();
01253
01254 std::vector<FUSE_imageinfo_t> image_list;
01255 NetworkCamera cam(host, port);
01256 try
01257 {
01258 cam.open();
01259 cam.start();
01260 image_list = cam.image_list();
01261 }
01262 catch (Exception& e)
01263 {
01264 e.append("Could not open camera on %s:%d", host, port);
01265 e.print_trace();
01266 return;
01267 }
01268 cam.close();
01269
01270 #ifdef DEBUG_PRINT
01271 printf("%zu images available on host %s.\n", image_list.size(), host);
01272 #endif
01273
01274 std::vector<FUSE_imageinfo_t>::iterator fit;
01275
01276 Gtk::TreeModel::Children children = m_fuse_tree_store->children();
01277 Gtk::TreeModel::Row row = *(m_fuse_tree_store->append());
01278 row[m_fuse_columns.m_id] = children.size();
01279 row[m_fuse_columns.m_name] = Glib::ustring(name);
01280 row[m_fuse_columns.m_service_name] = Glib::ustring(name);
01281 row[m_fuse_columns.m_service_type] = Glib::ustring(type);
01282 row[m_fuse_columns.m_service_domain] = Glib::ustring(domain);
01283 row[m_fuse_columns.m_service_hostname] = Glib::ustring(host);
01284 row[m_fuse_columns.m_service_port] = port;
01285
01286 for (fit = image_list.begin(); fit != image_list.end(); ++fit)
01287 {
01288 Gtk::TreeModel::Row childrow = *(m_fuse_tree_store->append(row.children()));
01289 childrow[m_fuse_columns.m_name] = Glib::ustring(fit->image_id);
01290 childrow[m_fuse_columns.m_service_name] = Glib::ustring(name);
01291 childrow[m_fuse_columns.m_service_type] = Glib::ustring(type);
01292 childrow[m_fuse_columns.m_service_domain] = Glib::ustring(domain);
01293 childrow[m_fuse_columns.m_service_hostname] = Glib::ustring(host);
01294 childrow[m_fuse_columns.m_service_port] = port;
01295 childrow[m_fuse_columns.m_image_id] = Glib::ustring(fit->image_id);
01296 childrow[m_fuse_columns.m_image_width] = fit->width;
01297 childrow[m_fuse_columns.m_image_height] = fit->height;
01298 childrow[m_fuse_columns.m_image_colorspace] = Glib::ustring( colorspace_to_string((colorspace_t) fit->colorspace) );
01299 }
01300
01301 m_ftw->add_fountain_service(name, host, port);
01302 m_filw->add_fountain_service(name, host, port);
01303 }
01304
01305 void
01306 Firestation::on_service_removed( NetworkService* service )
01307 {
01308 const char* name = service->name();
01309 const char* type = service->type();
01310 const char* domain = service->domain();
01311
01312 Gtk::TreeModel::Children children = m_fuse_tree_store->children();
01313 Gtk::TreeModel::iterator rit;
01314 for (rit = children.begin(); rit != children.end(); ++rit)
01315 {
01316 Glib::ustring n = (*rit)[m_fuse_columns.m_service_name];
01317 Glib::ustring t = (*rit)[m_fuse_columns.m_service_type];
01318 Glib::ustring d = (*rit)[m_fuse_columns.m_service_domain];
01319
01320 if ( strcmp( n.c_str(), name) == 0 &&
01321 strcmp( t.c_str(), type) == 0 &&
01322 strcmp( d.c_str(), domain) == 0 )
01323 {
01324 m_fuse_tree_store->erase(rit);
01325 }
01326 }
01327
01328 m_ftw->remove_fountain_service(name);
01329 m_filw->remove_fountain_service(name);
01330 }