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