Fawkes API Fawkes Development Version
firestation.cpp
1/***************************************************************************
2 * firestation.cpp - Firestation
3 *
4 * Created: Wed Oct 10 14:19:30 2007
5 * Copyright 2007-2008 Daniel Beck
6 *
7 ****************************************************************************/
8
9/* This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Library General Public License for more details.
18 *
19 * Read the full text in the LICENSE.GPL file in the doc directory.
20 */
21
22#include "firestation.h"
23
24#include "color_train_widget.h"
25#include "fuse_transfer_widget.h"
26
27#include <fvcams/fileloader.h>
28#include <fvcams/net.h>
29#include <fvcams/shmem.h>
30#include <fvwidgets/fuse_image_list_widget.h>
31#include <gui_utils/avahi_dispatcher.h>
32#include <utils/math/angle.h>
33
34#ifdef HAVE_MIRROR_CALIB
35# include <fvmodels/mirror/mirror_calib.h>
36#endif
37
38#include <arpa/inet.h>
39#include <core/exception.h>
40#include <fvutils/color/conversions.h>
41#include <fvutils/color/yuv.h>
42#include <fvutils/colormap/yuvcm.h>
43#include <fvutils/draw/drawer.h>
44#include <fvutils/ipc/shm_image.h>
45#include <fvutils/scalers/lossy.h>
46#include <fvutils/system/camargp.h>
47#include <fvutils/writers/fvraw.h>
48#include <fvutils/writers/jpeg.h>
49#include <gdkmm/pixbuf.h>
50
51#include <iostream>
52
53using namespace std;
54using namespace fawkes;
55using namespace firevision;
56
57/** @class Firestation "firestation.h"
58 * Control GUI for vision related stuff.
59 * @author Daniel Beck
60 */
61
62/** Constructor.
63 * @param builder Gtk Builder
64 */
65Firestation::Firestation(Glib::RefPtr<Gtk::Builder> builder)
66{
67 // --- main window ------------------------------------------------
68 builder->get_widget("wndMain", m_wnd_main);
69 builder->get_widget("imgImage", m_img_image);
70 builder->get_widget("evtImageEventBox", m_evt_image);
71 builder->get_widget("trvShmImageIds", m_trv_shm_image_ids);
72 builder->get_widget("stbStatus", m_stb_status);
73 builder->get_widget("ckbContTrans", m_ckb_cont_trans);
74 builder->get_widget("spbUpdateTime", m_spb_update_time);
75
76 m_img_image->signal_size_allocate().connect(sigc::mem_fun(*this, &Firestation::resize_image));
77 m_evt_image->signal_button_press_event().connect(sigc::mem_fun(*this, &Firestation::image_click));
78 m_ckb_cont_trans->signal_toggled().connect(
79 sigc::mem_fun(*this, &Firestation::enable_cont_img_trans));
80
81 // ----------------------------------------------------------------
82
83 // --- toolbar widgets --------------------------------------------
84 builder->get_widget("tbtnExit", m_tbtn_exit);
85 builder->get_widget("tbtnCloseCamera", m_tbtn_close_camera);
86 builder->get_widget("tbtnUpdate", m_tbtn_update);
87 builder->get_widget("tbtnSave", m_tbtn_save);
88 builder->get_widget("tbtnOpenFile", m_tbtn_open_file);
89 builder->get_widget("tbtnOpenFolder", m_tbtn_open_folder);
90 builder->get_widget("tbtnOpenShm", m_tbtn_open_shm);
91 builder->get_widget("tbtnOpenFuse", m_tbtn_open_fuse);
92
93 m_tbtn_exit->signal_clicked().connect(sigc::mem_fun(*this, &Firestation::exit));
94 m_tbtn_close_camera->signal_clicked().connect(sigc::mem_fun(*this, &Firestation::close_camera));
95 m_tbtn_update->signal_clicked().connect(sigc::mem_fun(*this, &Firestation::update_image));
96 m_tbtn_save->signal_clicked().connect(sigc::mem_fun(*this, &Firestation::save_image));
97 m_tbtn_open_file->signal_clicked().connect(sigc::mem_fun(*this, &Firestation::open_file));
98 m_tbtn_open_folder->signal_clicked().connect(sigc::mem_fun(*this, &Firestation::open_folder));
99 m_tbtn_open_shm->signal_clicked().connect(sigc::mem_fun(*this, &Firestation::open_shm));
100 m_tbtn_open_fuse->signal_clicked().connect(sigc::mem_fun(*this, &Firestation::open_fuse));
101 // ----------------------------------------------------------------
102
103 // --- dialogs ----------------------------------------------------
104 builder->get_widget("fcdOpenImage", m_fcd_open_image);
105 builder->get_widget("fcdSaveImage", m_fcd_save_image);
106 builder->get_widget("dlgOpenShm", m_dlg_open_shm);
107 builder->get_widget("trvShmImageIds", m_trv_shm_image_ids);
108 builder->get_widget("dlgOpenFuse", m_dlg_open_fuse);
109 builder->get_widget("ckbFuseJpeg", m_ckb_fuse_jpeg);
110 builder->get_widget("trvFuseServices", m_trv_fuse_services);
111
112#if GTK_VERSION_GE(3, 0)
113 Glib::RefPtr<Gtk::FileFilter> filter_jpg = Gtk::FileFilter::create();
114#else
115 Gtk::FileFilter *filter_jpg = Gtk::manage(new Gtk::FileFilter());
116#endif
117 filter_jpg->set_name("JPEG");
118 filter_jpg->add_pattern("*.jpg");
119 filter_jpg->add_pattern("*.jpeg");
120
121#if GTK_VERSION_GE(3, 0)
122 Glib::RefPtr<Gtk::FileFilter> filter_fvraw = Gtk::FileFilter::create();
123#else
124 Gtk::FileFilter *filter_fvraw = Gtk::manage(new Gtk::FileFilter());
125#endif
126 filter_fvraw->set_name("FVRaw");
127 filter_fvraw->add_pattern("*.raw");
128 filter_fvraw->add_pattern("*.fvraw");
129
130#if GTK_VERSION_GE(3, 0)
131 m_fcd_open_image->add_filter(filter_jpg);
132 m_fcd_open_image->add_filter(filter_fvraw);
133
134 m_fcd_save_image->add_filter(filter_jpg);
135 m_fcd_save_image->add_filter(filter_fvraw);
136
137#else
138 m_fcd_open_image->add_filter(*filter_jpg);
139 m_fcd_open_image->add_filter(*filter_fvraw);
140
141 m_fcd_save_image->add_filter(*filter_jpg);
142 m_fcd_save_image->add_filter(*filter_fvraw);
143#endif
144
145 m_shm_list_store = Gtk::ListStore::create(m_shm_columns);
146 m_trv_shm_image_ids->set_model(m_shm_list_store);
147 m_trv_shm_image_ids->append_column("#", m_shm_columns.m_id);
148 m_trv_shm_image_ids->append_column("Name", m_shm_columns.m_name);
149
150 m_fuse_tree_store = Gtk::TreeStore::create(m_fuse_columns);
151 m_trv_fuse_services->set_model(m_fuse_tree_store);
152 // m_trv_fuse_services->append_column("#", m_fuse_columns.m_id);
153 m_trv_fuse_services->append_column("Name", m_fuse_columns.m_name);
154 // ----------------------------------------------------------------
155
156 // --- color train widget -----------------------------------------
157 m_ctw = new ColorTrainWidget(this);
158 builder->get_widget("cmbCtObjectType", m_cmb_ct_type);
159 builder->get_widget("btnCtStart", m_btn_ct_start);
160 builder->get_widget("btnCtSeg", m_btn_ct_seg);
161 builder->get_widget("spbtnCtCmDepth", m_spbtn_depth);
162 builder->get_widget("spbtnCtCmWidth", m_spbtn_width);
163 builder->get_widget("spbtnCtCmHeight", m_spbtn_height);
164
165 m_cmb_ct_type->signal_changed().connect(sigc::mem_fun(*this, &Firestation::ct_object_changed));
166 m_cmb_ct_type->set_active(0);
167
168 m_btn_ct_start->signal_clicked().connect(sigc::mem_fun(*this, &Firestation::ct_start));
169
170 m_ctw->update_image().connect(sigc::mem_fun(*this, &Firestation::draw_image));
171 m_ctw->colormap_updated().connect(sigc::mem_fun(*this, &Firestation::on_colormap_updated));
172
173 Gtk::Button *btn;
174 builder->get_widget("btnCtUnselect", btn);
175 m_ctw->set_reset_selection_btn(btn);
176
177 builder->get_widget("btnCtAdd", btn);
178 m_ctw->set_add_to_colormap_btn(btn);
179
180 builder->get_widget("btnCtReset", btn);
181 m_ctw->set_reset_colormap_btn(btn);
182
183 builder->get_widget("btnCtSaveHistos", btn);
184 m_ctw->set_save_histos_btn(btn);
185
186 builder->get_widget("btnCtLoadHistos", btn);
187 m_ctw->set_load_histos_btn(btn);
188
189 builder->get_widget("btnCtSaveColormap", btn);
190 m_ctw->set_save_colormap_btn(btn);
191
192 builder->get_widget("btnCtLoadColormap", btn);
193 m_ctw->set_load_colormap_btn(btn);
194
195 Gtk::Scale *scl;
196 builder->get_widget("sclCtThreshold", scl);
197 m_ctw->set_threshold_scl(scl);
198
199 builder->get_widget("sclCtMinProb", scl);
200 m_ctw->set_min_prob_scl(scl);
201
202 builder->get_widget("sclCtLayerSelector", scl);
203 m_ctw->set_cm_layer_selector(scl);
204
205 Gtk::Image *img;
206 builder->get_widget("imgCtSegmentation", img);
207 m_ctw->set_segmentation_img(img);
208
209 builder->get_widget("imgCtColormap", img);
210 m_ctw->set_colormap_img(img);
211
212 Gtk::FileChooserDialog *fcd;
213 builder->get_widget("fcdFilechooser", fcd);
214 m_ctw->set_filechooser_dlg(fcd);
215
216 m_btn_ct_seg->signal_toggled().connect(sigc::mem_fun(*this, &Firestation::draw_image));
217 m_ctw->set_cm_selector(m_spbtn_depth, m_spbtn_width, m_spbtn_height);
218 // ----------------------------------------------------------------
219
220 // --- mirror calibration -----------------------------------------
221#ifdef HAVE_MIRROR_CALIB
222 m_calib_tool = new firevision::MirrorCalibTool();
223#endif
224
225#ifndef HAVE_MIRROR_CALIB
226 Gtk::Notebook *nb;
227 Gtk::HBox * box;
228 builder->get_widget("ntbOptions", nb);
229 builder->get_widget("boxMirrorCalib", box);
230 nb->get_tab_label(*box)->set_sensitive(false);
231 box->set_sensitive(false);
232#endif
233
234 builder->get_widget("sclMcLine", m_scl_mc_line);
235 m_scl_mc_line->signal_change_value().connect(
236 sigc::mem_fun(*this, &Firestation::mc_on_line_angle_changed));
237
238 builder->get_widget("btnMcLoadMask", m_btn_mc_load_mask);
239 m_btn_mc_load_mask->signal_clicked().connect(sigc::mem_fun(*this, &Firestation::mc_load_mask));
240
241 //builder->get_widget("btnMcStart", m_btn_mc_start);
242 builder->get_widget("btnCalibLoad", m_btn_mc_load);
243 builder->get_widget("btnCalibSave", m_btn_mc_save);
244 builder->get_widget("entCalibDist", m_ent_mc_dist);
245 builder->get_widget("entCalibOri", m_ent_mc_ori);
246 builder->get_widget("fcdCalibSave", m_fcd_mc_save);
247 builder->get_widget("fcdCalibLoad", m_fcd_mc_load);
248
249 //m_btn_mc_start->signal_clicked().connect( sigc::mem_fun(*this, &Firestation::mc_start) );
250 m_btn_mc_load->signal_clicked().connect(sigc::mem_fun(*this, &Firestation::mc_load));
251 m_btn_mc_save->signal_clicked().connect(sigc::mem_fun(*this, &Firestation::mc_save));
252
253 builder->get_widget("btnMcSetCenter", m_btn_mc_set_center);
254 m_btn_mc_set_center->signal_clicked().connect(sigc::mem_fun(*this, &Firestation::mc_set_center));
255
256 builder->get_widget("btnMcMemorize", m_btn_mc_memorize);
257 m_btn_mc_memorize->signal_clicked().connect(sigc::mem_fun(*this, &Firestation::mc_memorize));
258
259 builder->get_widget("btnMcSimulateClicks", m_btn_mc_simulate_clicks);
260 m_btn_mc_simulate_clicks->signal_clicked().connect(
261 sigc::mem_fun(*this, &Firestation::mc_simulate_clicks));
262
263 builder->get_widget("entCalibDist", m_ent_mc_dist);
264 builder->get_widget("entCalibOri", m_ent_mc_ori);
265
266 // ----------------------------------------------------------------
267 builder->get_widget("fcdMcLoadMask", m_fcd_mc_load_mask);
268 builder->get_widget("fcdCalibSave", m_fcd_mc_save);
269 builder->get_widget("fcdCalibLoad", m_fcd_mc_load);
270 // ----------------------------------------------------------------
271
272 // --- fuse transfer widget ---------------------------------------
273 m_ftw = new FuseTransferWidget();
274
275 Gtk::TreeView *trv;
276 builder->get_widget("trvFuseRemoteLuts", trv);
277 m_ftw->set_remote_lut_list_trv(trv);
278 builder->get_widget("trvFuseLocalLuts", trv);
279 m_ftw->set_local_lut_list_trv(trv);
280 builder->get_widget("imgFuseLocal", img);
281 m_ftw->set_local_img(img);
282 builder->get_widget("imgFuseRemote", img);
283 m_ftw->set_remote_img(img);
284 builder->get_widget("btnFuseUpload", btn);
285 m_ftw->set_upload_btn(btn);
286 builder->get_widget("sclLocalLayerSelector", scl);
287 m_ftw->set_local_layer_selector(scl);
288 builder->get_widget("sclRemoteLayerSelector", scl);
289 m_ftw->set_remote_layer_selector(scl);
290 // ----------------------------------------------------------------
291
292 // --- fuse image list widget -------------------------------------
293 m_filw = new FuseImageListWidget();
294 builder->get_widget("trvFuseImageList", trv);
295 m_filw->set_image_list_trv(trv);
296 Gtk::CheckButton *chk;
297 builder->get_widget("chkFuseImageListUpdate", chk);
298 m_filw->set_auto_update_chk(chk);
299 builder->get_widget("chkFuseCompression", chk);
300 m_filw->set_toggle_compression_chk(chk);
301 m_filw->image_selected().connect(sigc::mem_fun(*this, &Firestation::on_fuse_image_selected));
302 // ----------------------------------------------------------------
303
304 m_yuv_orig_buffer = 0;
305 m_yuv_draw_buffer = 0;
306 m_yuv_scaled_buffer = 0;
307 m_rgb_scaled_buffer = 0;
308
309 m_img_width = 0;
310 m_img_height = 0;
311 m_img_size = 0;
312 m_img_cs = CS_UNKNOWN;
313
314 m_img_writer = 0;
315 m_camera = 0;
316 m_shm_buffer = 0;
317
318 m_img_src = SRC_NONE;
319 m_op_mode = MODE_VIEWER;
320
321 m_cont_img_trans = false;
322
323 mc_line_angle_deg = 0.0;
324
325 m_max_img_width = m_evt_image->get_width();
326 m_max_img_height = m_evt_image->get_height();
327 m_scaled_img_width = m_evt_image->get_width();
328 m_scaled_img_height = m_evt_image->get_height();
329 m_scale_factor = 1.0;
330
331 m_avahi_thread = new AvahiThread();
332 m_avahi_dispatcher = new AvahiDispatcher;
333
334 m_avahi_dispatcher->signal_service_added().connect(
335 sigc::mem_fun(*this, &Firestation::on_service_added));
336 m_avahi_dispatcher->signal_service_removed().connect(
337 sigc::mem_fun(*this, &Firestation::on_service_removed));
338
339 m_avahi_thread->watch_service("_fountain._tcp", m_avahi_dispatcher);
340 m_avahi_thread->start();
341}
342
343/** Destructor. */
345{
346 if (m_yuv_orig_buffer)
347 free(m_yuv_orig_buffer);
348 if (m_yuv_draw_buffer)
349 free(m_yuv_draw_buffer);
350 if (m_yuv_scaled_buffer)
351 free(m_yuv_scaled_buffer);
352 if (m_rgb_scaled_buffer)
353 free(m_rgb_scaled_buffer);
354
355 delete m_camera;
356 delete m_img_writer;
357
358#ifdef HAVE_MIRROR_CALIB
359 delete m_calib_tool;
360#endif
361 delete m_ctw;
362 delete m_ftw;
363 delete m_filw;
364
365 m_avahi_thread->cancel();
366 m_avahi_thread->join();
367 delete m_avahi_thread;
368 delete m_avahi_dispatcher;
369
370 delete m_wnd_main;
371 delete m_fcd_open_image;
372 delete m_fcd_save_image;
373 delete m_dlg_open_shm;
374 delete m_dlg_open_fuse;
375}
376
377/** Returns reference to main window.
378 * @return reference to main window
379 */
380Gtk::Window &
382{
383 return *m_wnd_main;
384}
385
386/** Exit routine. */
387void
388Firestation::exit()
389{
390 if (SRC_NONE != m_img_src) {
391 m_camera->close();
392 }
393
394 m_wnd_main->hide();
395}
396
397void
398Firestation::close_camera()
399{
400 if (SRC_NONE == m_img_src) {
401 return;
402 }
403
404 m_img_src = SRC_NONE;
405
406 m_camera->close();
407 delete m_camera;
408 m_camera = 0;
409
410 m_img_width = 0;
411 m_img_height = 0;
412 m_img_cs = CS_UNKNOWN;
413
414 m_img_size = 0;
415
416 m_img_image->clear();
417 m_img_image->set("gtk-missing-image");
418
419 m_ctw->set_src_buffer(NULL, 0, 0);
420 m_ctw->set_draw_buffer(NULL);
421}
422
423/** Saves the current image. */
424void
425Firestation::save_image()
426{
427 if (m_img_src == SRC_NONE) {
428 return;
429 }
430
431 m_fcd_save_image->set_transient_for(*this);
432
433 int result = m_fcd_save_image->run();
434
435 switch (result) {
436 case (Gtk::RESPONSE_OK): {
437 delete m_img_writer;
438
439 Glib::ustring filter_name = m_fcd_save_image->get_filter()->get_name();
440 if (Glib::ustring("JPEG") == filter_name) {
441 m_img_writer = new JpegWriter();
442 } else if (Glib::ustring("FVRaw") == filter_name) {
443 m_img_writer = new FvRawWriter();
444 } else {
445 cout << "save_file(): unknown file format" << endl;
446 break;
447 }
448
449 std::string filename = m_fcd_save_image->get_filename();
450 m_img_writer->set_filename(filename.c_str());
451 m_img_writer->set_dimensions(m_img_width, m_img_height);
452 m_img_writer->set_buffer(m_img_cs, m_yuv_orig_buffer);
453 m_img_writer->write();
454
455 std::cout << "Save file: " << filename << std::endl;
456 break;
457 }
458
459 case (Gtk::RESPONSE_CANCEL): break;
460
461 default: break;
462 }
463
464 m_fcd_save_image->hide();
465}
466
467/** Reads in a new image for the current image source. */
468void
469Firestation::update_image()
470{
471 if (m_img_src == SRC_NONE) {
472 return;
473 }
474
475 try {
476 m_camera->capture();
477 convert(
478 m_img_cs, YUV422_PLANAR, m_camera->buffer(), m_yuv_orig_buffer, m_img_width, m_img_height);
479 memcpy(m_yuv_draw_buffer,
480 m_yuv_orig_buffer,
481 colorspace_buffer_size(YUV422_PLANAR, m_img_width, m_img_height));
482 m_camera->dispose_buffer();
483
484 draw_image();
485
487 } catch (Exception &e) {
488 e.print_trace();
489 }
490}
491
492bool
493Firestation::call_update_image()
494{
495 if (!m_cont_img_trans) {
496 return false;
497 }
498
499 update_image();
500
501 return true;
502}
503
504void
505Firestation::enable_cont_img_trans()
506{
507 if (m_cont_img_trans) {
508 m_cont_img_trans = false;
509 return;
510 }
511
512 int timeout = (int)rint(m_spb_update_time->get_value());
513 sigc::connection conn =
514 Glib::signal_timeout().connect(sigc::mem_fun(*this, &Firestation::call_update_image), timeout);
515 m_cont_img_trans = true;
516}
517
518/** Reads in an image from a file. */
519void
520Firestation::open_file()
521{
522 m_fcd_open_image->set_action(Gtk::FILE_CHOOSER_ACTION_OPEN);
523 m_fcd_open_image->set_transient_for(*this);
524
525 int result = m_fcd_open_image->run();
526
527 switch (result) {
528 case Gtk::RESPONSE_OK: {
529 pre_open_img_src();
530
531 std::string filename = m_fcd_open_image->get_filename();
532
533 m_camera = new FileLoader(filename.c_str());
534 m_img_src = SRC_FILE;
535 post_open_img_src();
536 break;
537 }
538
539 case Gtk::RESPONSE_CANCEL: {
540 break;
541 }
542
543 default: {
544 break;
545 }
546 }
547
548 m_fcd_open_image->hide();
549}
550
551/** Reads in images from a directory. */
552void
553Firestation::open_folder()
554{
555 m_fcd_open_image->set_action(Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER);
556 m_fcd_open_image->set_transient_for(*this);
557
558 int result = m_fcd_open_image->run();
559
560 switch (result) {
561 case Gtk::RESPONSE_OK: {
562 pre_open_img_src();
563
564 std::string extension;
565 Glib::ustring filter_name = m_fcd_save_image->get_filter()->get_name();
566 if (Glib::ustring("JPEG") == filter_name) {
567 extension = "jpg";
568 } else if (Glib::ustring("FVRaw") == filter_name) {
569 extension = "raw";
570 }
571
572 std::string folder = m_fcd_open_image->get_current_folder();
573 char * as;
574 if (asprintf(&as, "file:file:dir=%s:ext=%s", folder.c_str(), extension.c_str()) != -1) {
575 CameraArgumentParser cap(as);
576 m_camera = new FileLoader(&cap);
577 m_img_src = SRC_FILE;
578 post_open_img_src();
579 free(as);
580 } else {
581 printf("Cannot open folder, asprintf() ran out of memory");
582 }
583
584 break;
585 }
586
587 case Gtk::RESPONSE_CANCEL: {
588 break;
589 }
590
591 default: {
592 break;
593 }
594 }
595
596 m_fcd_open_image->hide();
597}
598
599/** Opens a SHM image. */
600void
601Firestation::open_shm()
602{
605 shmit = SharedMemory::find(FIREVISION_SHM_IMAGE_MAGIC_TOKEN, h);
606
607 if (shmit == SharedMemory::end()) {
608 m_stb_status->push("No SHM images found");
609 return;
610 } else {
611 unsigned int num_buffers = 0;
612 m_shm_list_store->clear();
613
614 while (shmit != SharedMemory::end()) {
615 ++num_buffers;
616 Gtk::TreeModel::Row row = *(m_shm_list_store->append());
617 row[m_shm_columns.m_id] = num_buffers;
619 row[m_shm_columns.m_name] = h->image_id();
620 shmit++;
621 }
622 }
623
624 m_dlg_open_shm->set_transient_for(*this);
625
626 int result = m_dlg_open_shm->run();
627
628 switch (result) {
629 case Gtk::RESPONSE_OK: {
630 delete m_shm_buffer;
631
632 Gtk::TreeModel::Path path;
633 Gtk::TreeViewColumn *column;
634 m_trv_shm_image_ids->get_cursor(path, column);
635
636 Gtk::TreeModel::iterator iter = m_shm_list_store->get_iter(path);
637
638 if (iter) {
639 Gtk::TreeModel::Row row = *iter;
640 if (row) {
641 Glib::ustring name = row[m_shm_columns.m_name];
642 pre_open_img_src();
643
644 try {
645 m_camera = new SharedMemoryCamera(name.c_str());
646 } catch (Exception &e) {
647 e.print_trace();
648 }
649
650 m_img_src = SRC_SHM;
651
652 post_open_img_src();
653 }
654 } else {
655 std::cout << "invalid iter" << std::endl;
656 }
657
658 break;
659 }
660
661 case Gtk::RESPONSE_CANCEL: break;
662
663 default: break;
664 }
665
666 m_dlg_open_shm->hide();
667}
668
669/** Connects to a FUSE server. */
670void
671Firestation::open_fuse()
672{
673 Gtk::TreeModel::Children children = m_fuse_tree_store->children();
674 if (0 == children.size()) {
675 m_stb_status->push("No FUSE services found");
676 return;
677 }
678
679 m_trv_fuse_services->expand_all();
680 m_dlg_open_fuse->set_transient_for(*this);
681
682 int result = m_dlg_open_fuse->run();
683
684 switch (result) {
685 case Gtk::RESPONSE_OK: {
686 Gtk::TreeModel::Path path;
687 Gtk::TreeViewColumn *column;
688 m_trv_fuse_services->get_cursor(path, column);
689
690 Gtk::TreeModel::iterator iter = m_fuse_tree_store->get_iter(path);
691
692 if (iter) {
693 Gtk::TreeModel::Row row = *iter;
694 if (row) {
695 Glib::ustring hostname = row[m_fuse_columns.m_service_hostname];
696 unsigned short int port = row[m_fuse_columns.m_service_port];
697 Glib::ustring image_id = row[m_fuse_columns.m_image_id];
698 bool jpeg = m_ckb_fuse_jpeg->get_active();
699
700 pre_open_img_src();
701
702 try {
703 m_camera = new NetworkCamera(hostname.c_str(), port, image_id.c_str(), jpeg);
704 m_img_src = SRC_FUSE;
705 post_open_img_src();
706 } catch (Exception &e) {
707 m_img_src = SRC_NONE;
708 e.print_trace();
709 }
710 }
711 } else {
712 std::cout << "invalid iter" << std::endl;
713 }
714
715 break;
716 }
717
718 case Gtk::RESPONSE_CANCEL: break;
719
720 default: break;
721 }
722
723 m_dlg_open_fuse->hide();
724}
725
726void
727Firestation::pre_open_img_src()
728{
729 if (SRC_NONE != m_img_src) {
730 m_camera->stop();
731 m_camera->close();
732
733 delete m_camera;
734 m_camera = 0;
735
736 m_img_src = SRC_NONE;
737 }
738}
739
740/** Stuff that is executed after an image source has been selected. */
741void
742Firestation::post_open_img_src()
743{
744 if (m_img_src == SRC_NONE) {
745 return;
746 }
747
748 try {
749 m_camera->open();
750 m_camera->start();
751 m_camera->capture();
752 m_img_width = m_camera->pixel_width();
753 m_img_height = m_camera->pixel_height();
754 m_img_cs = m_camera->colorspace();
755
756 m_img_size = colorspace_buffer_size(m_img_cs, m_img_width, m_img_height);
757
758 m_yuv_orig_buffer = malloc_buffer(YUV422_PLANAR, m_img_width, m_img_height);
759 m_yuv_draw_buffer = malloc_buffer(YUV422_PLANAR, m_img_width, m_img_height);
760
761 convert(
762 m_img_cs, YUV422_PLANAR, m_camera->buffer(), m_yuv_orig_buffer, m_img_width, m_img_height);
763 memcpy(m_yuv_draw_buffer,
764 m_yuv_orig_buffer,
765 colorspace_buffer_size(YUV422_PLANAR, m_img_width, m_img_height));
766
767 m_camera->dispose_buffer();
768
769 m_tbtn_update->set_sensitive(true);
770 m_tbtn_save->set_sensitive(true);
771
772 draw_image();
773
774 m_ctw->set_src_buffer(m_yuv_orig_buffer, m_img_width, m_img_height);
775 m_ctw->set_draw_buffer(m_yuv_draw_buffer);
777
778 mc_draw_line();
779 } catch (Exception &e) {
780 e.print_trace();
781 printf("Opening camera failed.\n");
782 }
783}
784
785void
786Firestation::on_fuse_image_selected()
787{
788 string host_name;
789 unsigned short port;
790 string image_id;
791 bool compression;
792
793 m_filw->get_selected_image(host_name, port, image_id, compression);
794
795 pre_open_img_src();
796
797 try {
798 m_camera = new NetworkCamera(host_name.c_str(), port, image_id.c_str(), compression);
799 m_img_src = SRC_FUSE;
800 } catch (Exception &e) {
801 m_img_src = SRC_NONE;
802 e.print_trace();
803 }
804
805 post_open_img_src();
806}
807
808void
809Firestation::on_colormap_updated()
810{
811 m_ftw->set_current_colormap(m_ctw->get_colormap());
812}
813
814/** Draws the image. */
815void
816Firestation::draw_image()
817{
818 if (m_img_src == SRC_NONE) {
819 return;
820 }
821
822 LossyScaler scaler;
823 scaler.set_original_buffer(m_yuv_draw_buffer);
824 scaler.set_original_dimensions(m_img_width, m_img_height);
825 scaler.set_scaled_dimensions(m_max_img_width, m_max_img_height);
826
827 unsigned int scaled_width = scaler.needed_scaled_width();
828 unsigned int scaled_height = scaler.needed_scaled_height();
829
830 if (scaled_width != m_scaled_img_width || scaled_height != m_scaled_img_height) {
831 m_scaled_img_width = scaled_width;
832 m_scaled_img_height = scaled_height;
833 m_scale_factor = scaler.get_scale_factor();
834 }
835
836 if (m_rgb_scaled_buffer)
837 free(m_rgb_scaled_buffer);
838 if (m_yuv_scaled_buffer)
839 free(m_yuv_scaled_buffer);
840 m_yuv_scaled_buffer = malloc_buffer(YUV422_PLANAR, m_scaled_img_width, m_scaled_img_height);
841 scaler.set_scaled_buffer(m_yuv_scaled_buffer);
842 scaler.scale();
843
844 if (m_btn_ct_seg->get_active()) {
845 unsigned int sld_img_size = m_scaled_img_width * m_scaled_img_height;
846 unsigned char u_seg = 255 / (unsigned int)pow(2, m_spbtn_width->get_value());
847 unsigned char v_seg = 255 / (unsigned int)pow(2, m_spbtn_height->get_value());
848 unsigned int u = 0;
849 for (u = sld_img_size; u < sld_img_size + sld_img_size / 2; ++u) {
850 m_yuv_scaled_buffer[u] = (m_yuv_scaled_buffer[u] / u_seg) * u_seg;
851 }
852
853 for (; u < 2 * sld_img_size; ++u) {
854 m_yuv_scaled_buffer[u] = (m_yuv_scaled_buffer[u] / v_seg) * v_seg;
855 }
856 }
857
858 if (m_img_src == SRC_SHM) {
859 SharedMemoryCamera *shm_camera = dynamic_cast<SharedMemoryCamera *>(m_camera);
860 if (shm_camera->shared_memory_image_buffer()->circle_found()) {
861 Drawer drawer;
862 drawer.set_buffer(m_yuv_scaled_buffer, m_scaled_img_width, m_scaled_img_height);
863 drawer.set_color(YUV_t::white());
864 unsigned int roi_x =
865 (unsigned int)rint(shm_camera->shared_memory_image_buffer()->roi_x() * m_scale_factor);
866 unsigned int roi_y =
867 (unsigned int)rint(shm_camera->shared_memory_image_buffer()->roi_y() * m_scale_factor);
868 unsigned int roi_width =
869 (unsigned int)rint(shm_camera->shared_memory_image_buffer()->roi_width() * m_scale_factor);
870 unsigned int roi_height =
871 (unsigned int)rint(shm_camera->shared_memory_image_buffer()->roi_height() * m_scale_factor);
872 drawer.draw_rectangle(roi_x, roi_y, roi_width, roi_height);
873 }
874 }
875
876 m_rgb_scaled_buffer =
877 (unsigned char *)malloc(colorspace_buffer_size(RGB, m_scaled_img_width, m_scaled_img_height));
878
879 convert(YUV422_PLANAR,
880 RGB,
881 m_yuv_scaled_buffer,
882 m_rgb_scaled_buffer,
883 m_scaled_img_width,
884 m_scaled_img_height);
885
886 Glib::RefPtr<Gdk::Pixbuf> image = Gdk::Pixbuf::create_from_data(m_rgb_scaled_buffer,
887 Gdk::COLORSPACE_RGB,
888 false,
889 8,
890 m_scaled_img_width,
891 m_scaled_img_height,
892 3 * m_scaled_img_width);
893
894 m_img_image->set(image);
895}
896
897/** Signal handler that is called whenever the window size is changed.
898 * @param allocation a Gtk allocation
899 */
900void
901Firestation::resize_image(Gtk::Allocation &allocation)
902{
903 unsigned int new_width = (unsigned int)allocation.get_width();
904 unsigned int new_height = (unsigned int)allocation.get_height();
905
906 if (new_width != m_max_img_width || new_height != m_max_img_height) {
907 m_max_img_width = new_width;
908 m_max_img_height = new_height;
909 draw_image();
910 }
911}
912
913/** Handles mouse clicks in the image area.
914 * @param event a Gtk event
915 * @return true if signal was handled
916 */
917bool
918Firestation::image_click(GdkEventButton *event)
919{
920 unsigned int offset_x;
921 unsigned int offset_y;
922
923 offset_x = (m_max_img_width - m_scaled_img_width) / 2;
924 offset_y = (m_max_img_height - m_scaled_img_height) / 2;
925
926 offset_x = offset_x > m_max_img_width ? 0 : offset_x;
927 offset_y = offset_y > m_max_img_height ? 0 : offset_y;
928
929 unsigned int image_x;
930 unsigned int image_y;
931
932 if (event != NULL) {
933 image_x = (unsigned int)rint((event->x - offset_x) / m_scale_factor);
934 image_y = (unsigned int)rint((event->y - offset_y) / m_scale_factor);
935 } else {
936 image_x = 0;
937 image_y = 0;
938 }
939
940 if (image_x > m_img_width || image_y > m_img_height) {
941 return true;
942 }
943
944 switch (m_op_mode) {
945 case MODE_VIEWER:
946 if (m_img_src != SRC_NONE) {
947 unsigned char y;
948 unsigned char u;
949 unsigned char v;
950 YUV422_PLANAR_YUV(m_yuv_orig_buffer, m_img_width, m_img_height, image_x, image_y, y, u, v);
951 printf("Y=%u U=%u Y=%u @ (%u, %u)\n",
952 (unsigned int)y,
953 (unsigned int)u,
954 (unsigned int)v,
955 image_x,
956 image_y);
957 }
958 break;
959
960 case MODE_COLOR_TRAIN:
961 m_ctw->click(image_x, image_y, event->button);
962 draw_image();
963 break;
964
965 case MODE_MIRROR_CALIB: {
966#ifdef HAVE_MIRROR_CALIB
967 if (m_btn_mc_set_center->get_active()) {
968 m_calib_tool->set_center(image_x, image_y);
969 m_btn_mc_set_center->set_active(false);
970 mc_draw_line();
971 printf("Setting center to %u, %u\n", image_x, image_y);
972 } else {
973 printf("Using center to %d, %d\n", m_calib_tool->center_x(), m_calib_tool->center_y());
974 m_calib_tool->next_step();
975 const unsigned char *last_yuv = m_calib_tool->get_last_yuv_buffer();
976 memcpy(m_yuv_draw_buffer, last_yuv, m_img_size);
977 memcpy(m_yuv_orig_buffer, last_yuv, m_img_size);
978 m_calib_tool->draw_mark_lines(m_yuv_draw_buffer);
979 draw_image();
980 m_stb_status->push(m_calib_tool->get_state_description());
981 }
982#else
983 printf("IPP and OpenCV not installed; mirror calibration does not work.\n");
984#endif
985 break;
986 }
987
988 case MODE_MIRROR_CALIB_EVAL: {
989#ifdef HAVE_MIRROR_CALIB
990 float dist;
991 float phi;
992 m_calib_tool->eval(image_x, image_y, &dist, &phi);
993 phi = normalize_mirror_rad(phi);
994 printf("(%u, %u) = POLAR(%.2f deg, %.2f meters)\n", image_x, image_y, rad2deg(phi), dist);
995 //printf("Distance: %2f\t Phi: %2f\n", dist, phi);
996#else
997 printf("IPP and OpenCV not installed; mirror calibration does not work.\n");
998#endif
999 break;
1000 }
1001
1002 default: break;
1003 }
1004
1005 return true;
1006}
1007
1008/** Starts the color training. */
1009void
1010Firestation::ct_start()
1011{
1012 if (m_op_mode == MODE_COLOR_TRAIN) {
1013 m_op_mode = MODE_VIEWER;
1014 m_stb_status->push("Leaving color training mode");
1015 } else {
1016 if (m_img_src != SRC_NONE) {
1017 m_ctw->set_fg_object(ct_get_fg_object());
1018
1019 m_op_mode = MODE_COLOR_TRAIN;
1020
1021 m_stb_status->push("Entering color training mode");
1022 }
1023 }
1024}
1025
1026hint_t
1027Firestation::ct_get_fg_object()
1028{
1029 int active = m_cmb_ct_type->get_active_row_number();
1030 switch (active) {
1031 case 0: //Ball
1032 return H_BALL;
1033
1034 case 1: //Field
1035 return H_FIELD;
1036
1037 case 2: //Lines
1038 return H_LINE;
1039
1040 case 3: //Robot (Team A or all)
1041 return H_ROBOT;
1042
1043 case 4: //Robot (Team B)
1044 return H_ROBOT_OPP;
1045
1046 case 5: //Goal (yellow)
1047 return H_GOAL_YELLOW;
1048
1049 case 6: //Goal (sky-blue)
1050 return H_GOAL_BLUE;
1051
1052 case 7: //Background
1053 return H_UNKNOWN;
1054
1055 default: printf("ct_get_fg_object(): UNKNOWN\n"); return H_UNKNOWN;
1056 }
1057}
1058
1059void
1060Firestation::ct_object_changed()
1061{
1062 hint_t object = ct_get_fg_object();
1063 m_ctw->set_fg_object(object);
1064}
1065
1066void
1067Firestation::mc_draw_line()
1068{
1069 if (m_img_src != SRC_NONE) {
1070#ifdef HAVE_MIRROR_CALIB
1071 memcpy(m_yuv_draw_buffer, m_yuv_orig_buffer, m_img_size);
1072 MirrorCalibTool::draw_line(m_yuv_draw_buffer,
1073 mc_line_angle_deg,
1074 m_calib_tool->center_x(),
1075 m_calib_tool->center_y(),
1076 m_img_width,
1077 m_img_height);
1078 draw_image();
1079#else
1080 printf("IPP and OpenCV not installed; mirror calibration does not work.\n");
1081#endif
1082 }
1083}
1084
1085bool
1086Firestation::mc_on_line_angle_changed(Gtk::ScrollType scroll, double value)
1087{
1088 mc_line_angle_deg = -1.0f * value;
1089 mc_line_angle_deg = rad2deg(normalize_mirror_rad(deg2rad(mc_line_angle_deg)));
1090 // Why -1.0f * value?
1091 // We want to display angles from the robot's real-world perspective.
1092 // We want to calculate with angles from the (mirrored!) image's perspective.
1093 // So when the user chooses 90 degrees, he wants to look to the left from the
1094 // robots perspective. But due to the mirroring, that's the right side in the
1095 // image, so we take -90 degrees.
1096 mc_draw_line();
1097 return true;
1098}
1099
1100void
1101Firestation::mc_load_mask()
1102{
1103 m_fcd_mc_load_mask->set_transient_for(*this);
1104
1105#if GTK_VERSION_GE(3, 0)
1106 Glib::RefPtr<Gtk::FileFilter> filter_mirror = Gtk::FileFilter::create();
1107#else
1108 Gtk::FileFilter *filter_mirror = Gtk::manage(new Gtk::FileFilter());
1109#endif
1110 filter_mirror->set_name("Robot Mask");
1111 filter_mirror->add_pattern("*.pnm");
1112#if GTK_VERSION_GE(3, 0)
1113 m_fcd_mc_load_mask->add_filter(filter_mirror);
1114#else
1115 m_fcd_mc_load_mask->add_filter(*filter_mirror);
1116#endif
1117
1118 int result = m_fcd_mc_load_mask->run();
1119
1120 switch (result) {
1121 case Gtk::RESPONSE_OK: {
1122#ifdef HAVE_MIRROR_CALIB
1123 std::string filename = m_fcd_mc_load_mask->get_filename();
1124 m_calib_tool->load_mask(filename.c_str());
1125 //m_op_mode = MODE_MIRROR_CALIB_EVAL;
1126#else
1127 printf("IPP and OpenCV not installed; mirror calibration does not work.\n");
1128#endif
1129 break;
1130 }
1131 case Gtk::RESPONSE_CANCEL: break;
1132 default: break;
1133 }
1134
1135 m_fcd_mc_load_mask->hide();
1136}
1137
1138/** Enters MODE_MIRROR_CALIB mode which waits for a click to mark the
1139 * preliminary center of the image. */
1140void
1141Firestation::mc_set_center()
1142{
1143 m_op_mode = MODE_MIRROR_CALIB;
1144}
1145
1146/** Start the mirror calibration process. */
1147void
1148Firestation::mc_memorize()
1149{
1150 /* if (m_op_mode == MODE_MIRROR_CALIB)
1151 {
1152 m_op_mode = MODE_VIEWER;
1153 m_stb_status->push("Leaving mirror calibration mode");
1154 }
1155 else */
1156 if (m_img_src != SRC_NONE) {
1157#ifdef HAVE_MIRROR_CALIB
1158 double ori = mc_line_angle_deg;
1159 std::cout << "Starting calibration for ori = " << ori << std::endl;
1160 m_calib_tool->push_back(m_yuv_orig_buffer, m_img_size, m_img_width, m_img_height, deg2rad(ori));
1161 m_op_mode = MODE_MIRROR_CALIB;
1162 std::cout << "Initialization for ori = " << ori << " completed" << std::endl;
1163
1164 mc_line_angle_deg -= 120.0;
1165 mc_line_angle_deg = rad2deg(normalize_mirror_rad(deg2rad(mc_line_angle_deg)));
1166 m_scl_mc_line->set_value(-1.0f * mc_line_angle_deg);
1167 // Why -1.0f * mc_line_angle_deg?
1168 // We want to display angles from the robot's real-world perspective.
1169 // We want to calculate with angles from the (mirrored!) image's perspective.
1170 // So when the user chooses 90 degrees, he wants to look to the left from the
1171 // robots perspective. But due to the mirroring, that's the right side in the
1172 // image, so we take -90 degrees.
1173 mc_draw_line();
1174#else
1175 printf("IPP and OpenCV not installed; mirror calibration does not work.\n");
1176#endif
1177 }
1178}
1179
1180/** Start the mirror calibration process. */
1181void
1182Firestation::mc_simulate_clicks()
1183{
1184 for (int i = 1; i <= 3; ++i) {
1185 image_click(NULL); // SHARPENING
1186 for (int j = 1; j <= 8; ++j) {
1187 image_click(NULL);
1188 } // EDGE_DETECTION
1189 for (int j = 1; j <= 2 * 8; ++j) {
1190 image_click(NULL);
1191 } // COMBINATION
1192 image_click(NULL); // PRE_MARKING
1193 image_click(NULL); // FINAL_MARKING
1194 }
1195}
1196
1197/** Load mirror calibration data from a file. */
1198void
1199Firestation::mc_load()
1200{
1201 m_fcd_mc_load->set_transient_for(*this);
1202
1203#if GTK_VERSION_GE(3, 0)
1204 Glib::RefPtr<Gtk::FileFilter> filter_mirror = Gtk::FileFilter::create();
1205#else
1206 Gtk::FileFilter *filter_mirror = Gtk::manage(new Gtk::FileFilter());
1207#endif
1208 filter_mirror->set_name("Mirror Calibration");
1209 filter_mirror->add_pattern("*.mirror");
1210 filter_mirror->add_pattern("*.bulb");
1211#if GTK_VERSION_GE(3, 0)
1212 m_fcd_mc_load->add_filter(filter_mirror);
1213#else
1214 m_fcd_mc_load->add_filter(*filter_mirror);
1215#endif
1216
1217 int result = m_fcd_mc_load->run();
1218
1219 switch (result) {
1220 case Gtk::RESPONSE_OK: {
1221#ifdef HAVE_MIRROR_CALIB
1222 std::string filename = m_fcd_mc_load->get_filename();
1223 m_calib_tool->load(filename.c_str());
1224 m_op_mode = MODE_MIRROR_CALIB_EVAL;
1225#else
1226 printf("IPP and OpenCV not installed; mirror calibration does not work.\n");
1227#endif
1228 break;
1229 }
1230 case Gtk::RESPONSE_CANCEL: break;
1231 default: break;
1232 }
1233
1234 m_fcd_mc_load->hide();
1235}
1236
1237/** Save calibration data to a file. */
1238void
1239Firestation::mc_save()
1240{
1241 m_fcd_mc_save->set_transient_for(*this);
1242
1243 int result = m_fcd_mc_save->run();
1244
1245 switch (result) {
1246 case (Gtk::RESPONSE_OK): {
1247#ifdef HAVE_MIRROR_CALIB
1248 std::string filename = m_fcd_mc_save->get_filename();
1249
1250 m_calib_tool->save(filename.c_str());
1251#else
1252 printf("IPP and OpenCV not installed; mirror calibration does not work.\n");
1253#endif
1254 break;
1255 }
1256
1257 case (Gtk::RESPONSE_CANCEL): break;
1258
1259 default: break;
1260 }
1261
1262 m_fcd_mc_save->hide();
1263}
1264
1265void
1266Firestation::on_service_added(NetworkService *service)
1267{
1268 const char * host = service->host();
1269 const char * name = service->name();
1270 const char * type = service->type();
1271 const char * domain = service->domain();
1272 unsigned short int port = service->port();
1273
1274 std::vector<FUSE_imageinfo_t> image_list;
1275 NetworkCamera cam(host, port);
1276 try {
1277 cam.open();
1278 cam.start();
1279 image_list = cam.image_list();
1280 } catch (Exception &e) {
1281 e.append("Could not open camera on %s:%d", host, port);
1282 e.print_trace();
1283 return;
1284 }
1285 cam.close();
1286
1287#ifdef DEBUG_PRINT
1288 printf("%zu images available on host %s.\n", image_list.size(), host);
1289#endif /* DEBUG_PRINT */
1290
1291 std::vector<FUSE_imageinfo_t>::iterator fit;
1292
1293 Gtk::TreeModel::Children children = m_fuse_tree_store->children();
1294 Gtk::TreeModel::Row row = *(m_fuse_tree_store->append());
1295 row[m_fuse_columns.m_id] = children.size();
1296 row[m_fuse_columns.m_name] = Glib::ustring(name);
1297 row[m_fuse_columns.m_service_name] = Glib::ustring(name);
1298 row[m_fuse_columns.m_service_type] = Glib::ustring(type);
1299 row[m_fuse_columns.m_service_domain] = Glib::ustring(domain);
1300 row[m_fuse_columns.m_service_hostname] = Glib::ustring(host);
1301 row[m_fuse_columns.m_service_port] = port;
1302
1303 for (fit = image_list.begin(); fit != image_list.end(); ++fit) {
1304 Gtk::TreeModel::Row childrow = *(m_fuse_tree_store->append(row.children()));
1305 childrow[m_fuse_columns.m_name] = Glib::ustring(fit->image_id);
1306 childrow[m_fuse_columns.m_service_name] = Glib::ustring(name);
1307 childrow[m_fuse_columns.m_service_type] = Glib::ustring(type);
1308 childrow[m_fuse_columns.m_service_domain] = Glib::ustring(domain);
1309 childrow[m_fuse_columns.m_service_hostname] = Glib::ustring(host);
1310 childrow[m_fuse_columns.m_service_port] = port;
1311 childrow[m_fuse_columns.m_image_id] = Glib::ustring(fit->image_id);
1312 childrow[m_fuse_columns.m_image_width] = fit->width;
1313 childrow[m_fuse_columns.m_image_height] = fit->height;
1314 childrow[m_fuse_columns.m_image_colorspace] =
1315 Glib::ustring(colorspace_to_string((colorspace_t)fit->colorspace));
1316 }
1317
1318 m_ftw->add_fountain_service(name, host, port);
1319 m_filw->add_fountain_service(name, host, port);
1320}
1321
1322void
1323Firestation::on_service_removed(NetworkService *service)
1324{
1325 const char *name = service->name();
1326 const char *type = service->type();
1327 const char *domain = service->domain();
1328
1329 Gtk::TreeModel::iterator rit = m_fuse_tree_store->children().begin();
1330 while (rit != m_fuse_tree_store->children().end()) {
1331 Glib::ustring n = (*rit)[m_fuse_columns.m_service_name];
1332 Glib::ustring t = (*rit)[m_fuse_columns.m_service_type];
1333 Glib::ustring d = (*rit)[m_fuse_columns.m_service_domain];
1334
1335 if (strcmp(n.c_str(), name) == 0 && strcmp(t.c_str(), type) == 0
1336 && strcmp(d.c_str(), domain) == 0) {
1337 rit = m_fuse_tree_store->erase(rit);
1338 } else {
1339 ++rit;
1340 }
1341 }
1342
1343 m_ftw->remove_fountain_service(name);
1344 m_filw->remove_fountain_service(name);
1345}
This widget implements the complete color training process.
void draw_segmentation_result()
Render the result of segmenting the image in the source buffer considering the current colormap into ...
void set_cm_layer_selector(Gtk::Scale *scl)
Set the widget to choose the layer of the colormap to display.
void set_draw_buffer(unsigned char *buffer)
Set the buffer to draw the selection into.
void set_filechooser_dlg(Gtk::FileChooserDialog *dlg)
Set the filechooser dialog to be used by this widget.
void click(unsigned int x, unsigned int y, unsigned int button=MOUSE_BUTTON_LEFT)
The user clicked into the image.
Glib::Dispatcher & update_image()
Access the signal that is emitted whenever a redraw of the image is necessary.
void set_colormap_img(Gtk::Image *img)
Set the image to render the colormap into.
void set_save_histos_btn(Gtk::Button *btn)
Set the buffon to open a dialog to save histograms.
void set_save_colormap_btn(Gtk::Button *btn)
Set the buffon to open a dialog to save a colormap.
void set_reset_selection_btn(Gtk::Button *btn)
Set the button to reset the selection.
void set_segmentation_img(Gtk::Image *img)
Set the image to render the segmented image into.
void set_min_prob_scl(Gtk::Scale *scl)
Set the scale to control the minimum probability.
void set_threshold_scl(Gtk::Scale *scl)
Set the scale to control the selection threshold.
void set_src_buffer(unsigned char *buffer, unsigned int img_width, unsigned int img_height)
Set the buffer containing the image data.
void set_load_histos_btn(Gtk::Button *btn)
Set the buffon to open a dialog to load histograms.
void set_fg_object(firevision::hint_t fg_object)
Set the current foreground object.
firevision::YuvColormap * get_colormap() const
Get the current colormap.
void set_load_colormap_btn(Gtk::Button *btn)
Set the buffon to open a dialog to load a colormap.
void set_cm_selector(Gtk::SpinButton *depth, Gtk::SpinButton *width=0, Gtk::SpinButton *height=0)
Set the widget to adjust the depth of the colormap.
void set_reset_colormap_btn(Gtk::Button *btn)
Set the button to reset the colormap.
Glib::Dispatcher & colormap_updated()
Access the signal that is emitted whenever the colormap has changed.
void set_add_to_colormap_btn(Gtk::Button *btn)
Set the button to trigger the generation of the colormap.
virtual ~Firestation()
Destructor.
Firestation(Glib::RefPtr< Gtk::Builder > builder)
Constructor.
Definition: firestation.cpp:65
Gtk::Window & get_window() const
Returns reference to main window.
This class implements the logic for a GUI that allows to transfer LUTs via FUSE.
void set_remote_lut_list_trv(Gtk::TreeView *lut_list)
Set the TreeView for the list of remote LUTs.
void set_local_layer_selector(Gtk::Scale *scl)
Assign a Scale to switch between the layers of the loal colormap.
void set_current_colormap(firevision::YuvColormap *colormap)
Set the current colormap.
void add_fountain_service(const char *name, const char *host_name, uint16_t port)
Tell the widget that a new FUSE service has been discovered.
void set_remote_img(Gtk::Image *img_remote)
Set the Image to display the remote LUT.
void set_local_img(Gtk::Image *img_local)
Set the Image to display the local LUT.
void remove_fountain_service(const char *name)
Tell the widget that a service is not available any more.
void set_upload_btn(Gtk::Button *btn_upload)
Set the button to trigger the LUT upload.
void set_remote_layer_selector(Gtk::Scale *scl)
Assign a Scale to switch between the layers of the remote colormap.
void set_local_lut_list_trv(Gtk::TreeView *lut_list)
Set the TreeView for the list of local LUTs.
sigc::signal< void, NetworkService * > signal_service_removed()
Get "service remove" signal.
sigc::signal< void, NetworkService * > signal_service_added()
Get "service added" signal.
Avahi main thread.
Definition: avahi_thread.h:55
void watch_service(const char *service_type, ServiceBrowseHandler *h)
Add a result handler.
Base class for exceptions in Fawkes.
Definition: exception.h:36
void print_trace() noexcept
Prints trace to stderr.
Definition: exception.cpp:601
void append(const char *format,...) noexcept
Append messages to the message list.
Definition: exception.cpp:333
Representation of a service announced or found via service discovery (i.e.
Definition: service.h:38
const char * type() const
Get type of service.
Definition: service.cpp:383
unsigned short int port() const
Get port of service.
Definition: service.cpp:410
const char * name() const
Get name of service.
Definition: service.cpp:349
const char * host() const
Get host of service.
Definition: service.cpp:401
const char * domain() const
Get domain of service.
Definition: service.cpp:392
Shared Memory iterator.
Definition: shm.h:119
void start(bool wait=true)
Call this method to start the thread.
Definition: thread.cpp:499
void join()
Join the thread.
Definition: thread.cpp:597
void cancel()
Cancel a thread.
Definition: thread.cpp:646
Camera argument parser.
Definition: camargp.h:36
virtual void stop()=0
Stop image transfer from the camera.
virtual void close()=0
Close camera.
virtual unsigned int pixel_height()=0
Height of image in pixels.
virtual void dispose_buffer()=0
Dispose current buffer.
virtual unsigned int pixel_width()=0
Width of image in pixels.
virtual void open()=0
Open the camera.
virtual void capture()=0
Capture an image.
virtual colorspace_t colorspace()=0
Colorspace of returned image.
virtual unsigned char * buffer()=0
Get access to current image buffer.
virtual void start()=0
Start image transfer from the camera.
Draw to an image.
Definition: drawer.h:32
void set_color(unsigned char y, unsigned char u, unsigned char v)
Set drawing color.
Definition: drawer.cpp:71
void draw_rectangle(unsigned int x, unsigned int y, unsigned int w, unsigned int h)
Draw rectangle.
Definition: drawer.cpp:199
void set_buffer(unsigned char *buffer, unsigned int width, unsigned int height)
Set the buffer to draw to.
Definition: drawer.cpp:58
Load images from files.
Definition: fileloader.h:38
This widget displays all available Fuse images in a tree view.
bool get_selected_image(std::string &host_name, unsigned short &port, std::string &image_id, bool &compression)
Get the host name, port, and image id of the selected image.
void set_image_list_trv(Gtk::TreeView *trv)
Assign the TreeView widget to hold the list of images.
void add_fountain_service(const char *name, const char *host_name, uint32_t port)
Call this method when new Fountain services are discovered.
Glib::Dispatcher & image_selected()
Access the Dispatcher that is signalled when a new image is selected in the list of images.
void set_auto_update_chk(Gtk::CheckButton *chk)
Assign the CheckButton that enables/disables the auto update function.
void set_toggle_compression_chk(Gtk::CheckButton *chk)
Assign the CheckButton to toggle the compression.
void remove_fountain_service(const char *name)
Call this method when a Fountain service vanishes.
FvRaw Writer implementation.
Definition: fvraw.h:32
JPEG file writer.
Definition: jpeg.h:34
Lossy image scaler.
Definition: lossy.h:33
virtual void scale()
Scale image.
Definition: lossy.cpp:139
virtual unsigned int needed_scaled_height()
Minimum needed height of scaled image depending on factor and original image height.
Definition: lossy.cpp:127
virtual void set_scaled_dimensions(unsigned int width, unsigned int height)
Set dimenins of scaled image buffer.
Definition: lossy.cpp:83
virtual void set_original_dimensions(unsigned int width, unsigned int height)
Set original image dimensions.
Definition: lossy.cpp:76
virtual float get_scale_factor()
Returns the scale factor.
Definition: lossy.cpp:133
virtual unsigned int needed_scaled_width()
Minimum needed width of scaled image depending on factor and original image width.
Definition: lossy.cpp:121
virtual void set_original_buffer(unsigned char *buffer)
Set original image buffer.
Definition: lossy.cpp:109
virtual void set_scaled_buffer(unsigned char *buffer)
Set scaled image buffer.
Definition: lossy.cpp:115
This class encapsulates the routines necessary for interactive mirror calibration.
Definition: mirror_calib.h:43
Network camera.
Definition: net.h:41
Shared memory camera.
Definition: shmem.h:36
SharedMemoryImageBuffer * shared_memory_image_buffer()
Get the shared memory image buffer.
Definition: shmem.cpp:225
Shared memory image buffer header.
Definition: shm_image.h:67
const char * image_id() const
Get image number.
Definition: shm_image.cpp:838
unsigned int roi_x() const
Get ROI X.
Definition: shm_image.cpp:264
unsigned int roi_width() const
Get ROI width.
Definition: shm_image.cpp:282
unsigned int roi_height() const
Get ROI height.
Definition: shm_image.cpp:291
unsigned int roi_y() const
Get ROI Y.
Definition: shm_image.cpp:273
bool circle_found() const
Check if circle was found .
Definition: shm_image.cpp:457
virtual void set_dimensions(unsigned int width, unsigned int height)
Set dimensions of image in pixels.
Definition: writer.cpp:128
virtual void write()=0
Write to file.
virtual void set_filename(const char *filename)
Set filename.
Definition: writer.cpp:102
virtual void set_buffer(colorspace_t cspace, unsigned char *buffer)
Set image buffer.
Definition: writer.cpp:139
Fawkes library namespace.
float deg2rad(float deg)
Convert an angle given in degrees to radians.
Definition: angle.h:36
float normalize_mirror_rad(float angle_rad)
Normalize angle in radian between -PI (inclusive) and PI (exclusive).
Definition: angle.h:72
float rad2deg(float rad)
Convert an angle given in radians to degrees.
Definition: angle.h:46