00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <tools/firestation/color_train_widget.h>
00024 #include <tools/firestation/colormap_viewer_widget.h>
00025 #include <fvutils/color/yuv.h>
00026 #include <fvutils/color/zauberstab.h>
00027 #include <fvutils/color/colorspaces.h>
00028 #include <fvutils/color/conversions.h>
00029 #include <fvutils/draw/drawer.h>
00030 #include <fvutils/scalers/lossy.h>
00031 #include <fvutils/colormap/bayes/bayes_generator.h>
00032 #include <fvutils/colormap/yuvcm.h>
00033 #include <fvutils/colormap/cmfile.h>
00034
00035 #include <fvutils/writers/jpeg.h>
00036
00037 #include <fvutils/color/color_object_map.h>
00038
00039 #include <core/exceptions/software.h>
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 ColorTrainWidget::ColorTrainWidget(Gtk::Window* parent)
00051 {
00052 m_generator = 0;
00053 m_zauberstab = new Zauberstab();
00054 m_cvw = new ColormapViewerWidget();
00055
00056 m_src_buffer = 0;
00057 m_draw_buffer = 0;
00058
00059 m_wnd_parent = parent;
00060 m_btn_reset_selection = 0;
00061 m_btn_add_to_colormap = 0;
00062 m_btn_reset_colormap = 0;
00063 m_btn_load_histos = 0;
00064 m_btn_save_histos = 0;
00065 m_btn_load_colormap = 0;
00066 m_btn_save_colormap = 0;
00067 m_spbtn_cm_depth = 0;
00068 m_spbtn_cm_width = 0;
00069 m_spbtn_cm_height = 0;
00070 m_img_segmentation = 0;
00071 m_scl_threshold = 0;
00072 m_scl_min_prob = 0;
00073 m_fcd_filechooser = 0;
00074 }
00075
00076
00077 ColorTrainWidget::~ColorTrainWidget()
00078 {
00079 delete m_cvw;
00080 delete m_generator;
00081 delete m_zauberstab;
00082 }
00083
00084
00085
00086
00087 void
00088 ColorTrainWidget::set_fg_object(hint_t object)
00089 {
00090 m_fg_object = object;
00091 }
00092
00093
00094
00095
00096
00097
00098 void
00099 ColorTrainWidget::set_src_buffer(unsigned char* yuv422_buffer,
00100 unsigned int img_width, unsigned int img_height)
00101 {
00102 m_img_width = img_width;
00103 m_img_height = img_height;
00104 m_src_buffer = yuv422_buffer;
00105 m_img_cs = YUV422_PLANAR;
00106 m_img_size = colorspace_buffer_size( m_img_cs, m_img_width, m_img_height );
00107
00108 if (yuv422_buffer)
00109 {
00110 m_zauberstab->deleteRegion();
00111 m_zauberstab->setBuffer(m_src_buffer, m_img_width, m_img_height);
00112 m_zauberstab->setThreshold(10);
00113 }
00114 else
00115 {
00116 m_img_segmentation->clear();
00117 m_img_segmentation->set("gtk-missing-image");
00118 }
00119 }
00120
00121
00122
00123
00124
00125
00126 void
00127 ColorTrainWidget::set_draw_buffer(unsigned char* buffer)
00128 {
00129 m_draw_buffer = buffer;
00130 }
00131
00132
00133
00134
00135
00136
00137 void
00138 ColorTrainWidget::click(unsigned int x, unsigned int y, unsigned int button)
00139 {
00140 if (m_src_buffer == 0 || m_draw_buffer == 0)
00141 { return; }
00142
00143 if ( m_zauberstab->isEmptyRegion() )
00144 {
00145 if (button == MOUSE_BUTTON_LEFT)
00146 {
00147 m_zauberstab->findRegion(x, y);
00148 }
00149 }
00150 else
00151 {
00152 if (button == MOUSE_BUTTON_LEFT)
00153 {
00154 m_zauberstab->addRegion(x, y);
00155 }
00156
00157 if (button == MOUSE_BUTTON_RIGHT)
00158 {
00159 m_zauberstab->deleteRegion(x, y);
00160 }
00161 }
00162
00163 memcpy(m_draw_buffer, m_src_buffer, m_img_size);
00164
00165 ZRegion *region = m_zauberstab->getRegion();
00166 Drawer *d = new Drawer();
00167 d->set_buffer( m_draw_buffer, m_img_width, m_img_height );
00168
00169 for (unsigned int s = 0; s < region->slices->size(); s++)
00170 {
00171 d->draw_rectangle_inverted( region->slices->at(s)->leftX,
00172 region->slices->at(s)->y,
00173 region->slices->at(s)->rightX - region->slices->at(s)->leftX,
00174 1 );
00175 }
00176
00177 delete d;
00178
00179 m_signal_update_image();
00180 }
00181
00182
00183 void
00184 ColorTrainWidget::reset_selection()
00185 {
00186 if (m_zauberstab)
00187 { m_zauberstab->deleteRegion(); }
00188
00189 if( m_src_buffer && m_draw_buffer )
00190 { memcpy(m_draw_buffer, m_src_buffer, m_img_size); }
00191
00192 m_signal_update_image();
00193 }
00194
00195
00196
00197
00198 void
00199 ColorTrainWidget::set_reset_selection_btn(Gtk::Button* btn)
00200 {
00201 m_btn_reset_selection = btn;
00202 m_btn_reset_selection->signal_clicked().connect( sigc::mem_fun(*this, &ColorTrainWidget::reset_selection) );
00203 }
00204
00205
00206
00207
00208 void
00209 ColorTrainWidget::set_add_to_colormap_btn(Gtk::Button* btn)
00210 {
00211 m_btn_add_to_colormap = btn;
00212 m_btn_add_to_colormap->signal_clicked().connect( sigc::mem_fun(*this, &ColorTrainWidget::add_to_colormap) );
00213 }
00214
00215
00216
00217
00218 void
00219 ColorTrainWidget::set_reset_colormap_btn(Gtk::Button* btn)
00220 {
00221 m_btn_reset_colormap = btn;
00222 m_btn_reset_colormap->signal_clicked().connect( sigc::mem_fun(*this, &ColorTrainWidget::reset_colormap) );
00223 }
00224
00225
00226
00227
00228 void
00229 ColorTrainWidget::set_load_histos_btn(Gtk::Button* btn)
00230 {
00231 m_btn_load_histos = btn;
00232 m_btn_load_histos->signal_clicked().connect( sigc::mem_fun(*this, &ColorTrainWidget::load_histograms) );
00233 }
00234
00235
00236
00237
00238 void
00239 ColorTrainWidget::set_save_histos_btn(Gtk::Button* btn)
00240 {
00241 m_btn_save_histos = btn;
00242 m_btn_save_histos->signal_clicked().connect( sigc::mem_fun(*this, &ColorTrainWidget::save_histograms) );
00243 }
00244
00245
00246
00247
00248 void
00249 ColorTrainWidget::set_load_colormap_btn(Gtk::Button* btn)
00250 {
00251 m_btn_load_colormap = btn;
00252 m_btn_load_colormap->signal_clicked().connect( sigc::mem_fun(*this, &ColorTrainWidget::load_colormap) );
00253 }
00254
00255
00256
00257
00258 void
00259 ColorTrainWidget::set_save_colormap_btn(Gtk::Button* btn)
00260 {
00261 m_btn_save_colormap = btn;
00262 m_btn_save_colormap->signal_clicked().connect( sigc::mem_fun(*this, &ColorTrainWidget::save_colormap) );
00263 }
00264
00265
00266
00267
00268 void
00269 ColorTrainWidget::set_colormap_img(Gtk::Image* img)
00270 {
00271 m_cvw->set_colormap_img(img);
00272 }
00273
00274
00275
00276
00277 void
00278 ColorTrainWidget::set_segmentation_img(Gtk::Image* img)
00279 {
00280 m_img_segmentation = img;
00281 m_seg_img_max_width = m_img_segmentation->get_width();
00282 m_seg_img_max_height = m_img_segmentation->get_height();
00283 m_img_segmentation->signal_size_allocate().connect( sigc::mem_fun( *this, &ColorTrainWidget::resize_seg_image) );
00284 }
00285
00286 void
00287 ColorTrainWidget::resize_seg_image(Gtk::Allocation& allocation)
00288 {
00289 unsigned int new_width = (unsigned int) allocation.get_width();
00290 unsigned int new_height = (unsigned int) allocation.get_height();
00291
00292 if (new_width != m_seg_img_max_width || new_height != m_seg_img_max_height)
00293 {
00294 m_seg_img_max_width = new_width;
00295 m_seg_img_max_height = new_height;
00296 draw_segmentation_result();
00297 }
00298 }
00299
00300
00301
00302
00303 void
00304 ColorTrainWidget::set_threshold_scl(Gtk::Scale* scl)
00305 {
00306 m_scl_threshold = scl;
00307 m_scl_threshold->signal_change_value().connect( sigc::mem_fun(*this, &ColorTrainWidget::set_threshold) );
00308 }
00309
00310
00311
00312
00313 void
00314 ColorTrainWidget::set_min_prob_scl(Gtk::Scale* scl)
00315 {
00316 m_scl_min_prob = scl;
00317 m_scl_min_prob->signal_change_value().connect( sigc::mem_fun(*this, &ColorTrainWidget::set_min_prob) );
00318 }
00319
00320
00321
00322
00323 void
00324 ColorTrainWidget::set_filechooser_dlg(Gtk::FileChooserDialog* dlg)
00325 {
00326 m_fcd_filechooser = dlg;
00327 }
00328
00329
00330
00331
00332 void
00333 ColorTrainWidget::set_cm_layer_selector(Gtk::Scale* scl)
00334 {
00335 m_cvw->set_layer_selector(scl);
00336 }
00337
00338
00339
00340
00341
00342
00343 void
00344 ColorTrainWidget::set_cm_selector(Gtk::SpinButton* depth, Gtk::SpinButton* width, Gtk::SpinButton* height)
00345 {
00346 m_spbtn_cm_depth = depth;
00347 m_spbtn_cm_width = width;
00348 m_spbtn_cm_height = height;
00349 }
00350
00351
00352
00353
00354 Glib::Dispatcher&
00355 ColorTrainWidget::update_image()
00356 {
00357 return m_signal_update_image;
00358 }
00359
00360
00361
00362
00363 Glib::Dispatcher&
00364 ColorTrainWidget::colormap_updated()
00365 {
00366 return m_signal_colormap_updated;
00367 }
00368
00369
00370 void
00371 ColorTrainWidget::load_histograms()
00372 {
00373 if ( !m_fcd_filechooser )
00374 { return; }
00375
00376 m_fcd_filechooser->set_title("Load histograms");
00377 m_fcd_filechooser->set_action(Gtk::FILE_CHOOSER_ACTION_OPEN);
00378
00379 m_fcd_filechooser->set_transient_for(*m_wnd_parent);
00380
00381 int result = m_fcd_filechooser->run();
00382
00383 switch(result)
00384 {
00385 case (Gtk::RESPONSE_OK):
00386 {
00387 std::string filename = m_fcd_filechooser->get_filename();
00388 if (!m_generator)
00389 { m_generator = new BayesColormapGenerator(); }
00390 m_generator->load_histograms( filename.c_str() );
00391 m_generator->calc();
00392 m_signal_colormap_updated();
00393
00394 YuvColormap *cur = m_generator->get_current();
00395 if (m_spbtn_cm_depth) m_spbtn_cm_depth->set_value(log(cur->depth()) / log(2));
00396 if (m_spbtn_cm_width) m_spbtn_cm_width->set_value(log(cur->width()) / log(2));
00397 if (m_spbtn_cm_height) m_spbtn_cm_height->set_value(log(cur->height()) / log(2));
00398
00399 m_cvw->set_colormap(cur);
00400 m_cvw->draw();
00401 draw_segmentation_result();
00402 break;
00403 }
00404
00405 case (Gtk::RESPONSE_CANCEL):
00406 break;
00407
00408 default:
00409 break;
00410 }
00411
00412 m_fcd_filechooser->hide();
00413 }
00414
00415
00416 void
00417 ColorTrainWidget::save_histograms()
00418 {
00419 if ( !m_fcd_filechooser )
00420 { return; }
00421
00422 m_fcd_filechooser->set_title("Save histograms");
00423 m_fcd_filechooser->set_action(Gtk::FILE_CHOOSER_ACTION_SAVE);
00424
00425 m_fcd_filechooser->set_transient_for(*m_wnd_parent);
00426
00427 int result = m_fcd_filechooser->run();
00428
00429 switch(result)
00430 {
00431 case (Gtk::RESPONSE_OK):
00432 {
00433 std::string filename = m_fcd_filechooser->get_filename();
00434 m_generator->save_histograms( filename.c_str() );
00435 break;
00436 }
00437
00438 case (Gtk::RESPONSE_CANCEL):
00439 break;
00440
00441 default:
00442 break;
00443 }
00444
00445 m_fcd_filechooser->hide();
00446 }
00447
00448
00449 void
00450 ColorTrainWidget::add_to_colormap()
00451 {
00452 if ( !m_src_buffer )
00453 { return; }
00454
00455 unsigned int cm_depth;
00456 if (m_spbtn_cm_depth)
00457 { cm_depth = (unsigned int) rint( pow(2.0, m_spbtn_cm_depth->get_value()) ); }
00458 else
00459 { cm_depth = 1; }
00460
00461 unsigned int cm_width;
00462 if (m_spbtn_cm_width)
00463 { cm_width = (unsigned int) rint( pow(2.0, m_spbtn_cm_width->get_value()) ); }
00464 else
00465 { cm_width = 256; }
00466
00467 unsigned int cm_height;
00468 if (m_spbtn_cm_height)
00469 { cm_height = (unsigned int) rint( pow(2.0, m_spbtn_cm_height->get_value()) ); }
00470 else
00471 { cm_height = 256; }
00472
00473 if ( !m_generator
00474 || cm_depth != m_generator->get_current()->depth()
00475 || cm_width != m_generator->get_current()->width()
00476 || cm_height != m_generator->get_current()->height())
00477 {
00478 delete m_generator;
00479 m_generator = new BayesColormapGenerator(cm_depth, H_UNKNOWN, cm_width, cm_height);
00480 m_cvw->set_colormap( m_generator->get_current() );
00481 }
00482
00483 if (m_fg_object == H_UNKNOWN)
00484 {
00485 printf("CTW::add_to_colormap(): no fg object set\n");
00486 return;
00487 }
00488
00489 m_generator->set_fg_object(m_fg_object);
00490 m_generator->reset_undo();
00491 m_generator->set_buffer(m_src_buffer, m_img_width, m_img_height);
00492 m_generator->set_selection( m_zauberstab->getSelection() );
00493 m_generator->consider();
00494 m_generator->calc();
00495 m_signal_colormap_updated();
00496
00497
00498 m_cvw->draw(-1);
00499
00500
00501 draw_segmentation_result();
00502 }
00503
00504
00505 void
00506 ColorTrainWidget::reset_colormap()
00507 {
00508 Gtk::MessageDialog dialog(*m_wnd_parent, "Are you sure you want to reset the colormap?",
00509 false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_OK_CANCEL);
00510
00511 int result = dialog.run();
00512
00513 if (result != Gtk::RESPONSE_OK) return;
00514
00515 if (m_generator)
00516 {
00517 m_generator->reset();
00518 m_signal_colormap_updated();
00519
00520 if (m_cvw)
00521 { m_cvw->draw(); }
00522
00523 draw_segmentation_result();
00524 }
00525 }
00526
00527
00528 void
00529 ColorTrainWidget::load_colormap()
00530 {
00531 if ( !m_fcd_filechooser )
00532 { return; }
00533
00534 m_fcd_filechooser->set_title("Load colormap colormap");
00535 m_fcd_filechooser->set_action(Gtk::FILE_CHOOSER_ACTION_OPEN);
00536
00537 m_fcd_filechooser->set_transient_for(*m_wnd_parent);
00538
00539 int result = m_fcd_filechooser->run();
00540
00541 switch(result)
00542 {
00543 case (Gtk::RESPONSE_OK):
00544 {
00545 delete m_generator;
00546
00547 std::string filename = m_fcd_filechooser->get_filename();
00548 ColormapFile cmf;
00549 cmf.read(filename.c_str());
00550 Colormap *tcm = cmf.get_colormap();
00551 YuvColormap *tycm = dynamic_cast<YuvColormap *>(tcm);
00552 if ( ! tycm ) {
00553 delete tcm;
00554 throw fawkes::TypeMismatchException("File does not contain a YUV colormap");
00555 }
00556 unsigned int cm_depth = tcm->depth();
00557 unsigned int cm_width = tcm->width();
00558 unsigned int cm_height = tcm->height();
00559 m_generator = new BayesColormapGenerator(cm_depth, H_UNKNOWN, cm_width, cm_height);
00560 YuvColormap *current = m_generator->get_current();
00561 *current = *tycm;
00562 delete tcm;
00563
00564 if (m_spbtn_cm_depth) m_spbtn_cm_depth->set_value(log(cm_depth) / log(2));
00565 if (m_spbtn_cm_width) m_spbtn_cm_width->set_value(log(cm_width) / log(2));
00566 if (m_spbtn_cm_height) m_spbtn_cm_height->set_value(log(cm_height) / log(2));
00567
00568 m_signal_colormap_updated();
00569 m_cvw->set_colormap( m_generator->get_current() );
00570 m_cvw->draw();
00571 draw_segmentation_result();
00572 break;
00573 }
00574
00575 case (Gtk::RESPONSE_CANCEL):
00576 break;
00577
00578 default:
00579 break;
00580 }
00581
00582 m_fcd_filechooser->hide();
00583 }
00584
00585
00586 void
00587 ColorTrainWidget::save_colormap()
00588 {
00589 if ( !m_fcd_filechooser )
00590 { return; }
00591
00592 m_fcd_filechooser->set_title("Save colormap colormap");
00593 m_fcd_filechooser->set_action(Gtk::FILE_CHOOSER_ACTION_SAVE);
00594
00595 m_fcd_filechooser->set_transient_for(*m_wnd_parent);
00596
00597 int result = m_fcd_filechooser->run();
00598
00599 switch(result)
00600 {
00601 case(Gtk::RESPONSE_OK):
00602 {
00603 std::string filename = m_fcd_filechooser->get_filename();
00604 YuvColormap *current = m_generator->get_current();
00605 ColormapFile cmf(current->depth(), current->width(), current->height());
00606 cmf.add_colormap(current);
00607 cmf.write( filename.c_str() );
00608 break;
00609 }
00610
00611 case(Gtk::RESPONSE_CANCEL):
00612 break;
00613
00614 default:
00615 break;
00616 }
00617
00618 m_fcd_filechooser->hide();
00619 }
00620
00621
00622
00623
00624 YuvColormap *
00625 ColorTrainWidget::get_colormap() const
00626 {
00627 if ( !m_generator )
00628 { return 0; }
00629
00630 return m_generator->get_current();
00631 }
00632
00633 bool
00634 ColorTrainWidget::set_threshold(Gtk::ScrollType scroll, double value)
00635 {
00636 unsigned int threshold = (unsigned int) rint(value);
00637 m_zauberstab->setThreshold(threshold);
00638
00639 return true;
00640 }
00641
00642 bool
00643 ColorTrainWidget::set_min_prob(Gtk::ScrollType scroll, double value)
00644 {
00645 if ( !m_generator )
00646 { return true; }
00647
00648 m_generator->set_min_probability(value);
00649
00650 return true;
00651 }
00652
00653 void
00654 ColorTrainWidget::reset_gui()
00655 {
00656 m_scl_min_prob->set_value(0.0);
00657 }
00658
00659
00660
00661
00662 void
00663 ColorTrainWidget::draw_segmentation_result()
00664 {
00665 if ( !m_src_buffer || !m_img_segmentation || !m_generator)
00666 { return; }
00667
00668 unsigned char* seg_buffer = (unsigned char*) malloc(m_img_size);
00669 bzero(seg_buffer, m_img_size);
00670
00671 Drawer d;
00672 d.set_buffer(seg_buffer, m_img_width, m_img_height);
00673
00674 YuvColormap* cm = m_generator->get_current();
00675
00676 for (unsigned int w = 0; w < m_img_width; ++w)
00677 {
00678 for (unsigned int h = 0; h < m_img_height; ++h)
00679 {
00680 unsigned int y = YUV422_PLANAR_Y_AT(m_src_buffer, m_img_width, w, h);
00681 unsigned int u = YUV422_PLANAR_U_AT(m_src_buffer, m_img_width, m_img_height, w, h);
00682 unsigned int v = YUV422_PLANAR_V_AT(m_src_buffer, m_img_width, m_img_height, w, h);
00683
00684 d.set_color(ColorObjectMap::get_color(cm->determine(y, u, v)));
00685 d.color_point(w, h);
00686 }
00687 }
00688
00689 LossyScaler scaler;
00690 scaler.set_original_buffer(seg_buffer);
00691 scaler.set_original_dimensions(m_img_width, m_img_height);
00692 scaler.set_scaled_dimensions(m_seg_img_max_width, m_seg_img_max_height);
00693 unsigned int width = scaler.needed_scaled_width();
00694 unsigned int height = scaler.needed_scaled_height();
00695
00696 unsigned char* scaled_buffer = (unsigned char*) malloc( colorspace_buffer_size( m_img_cs,
00697 width,
00698 height ) );
00699 scaler.set_scaled_buffer(scaled_buffer);
00700 scaler.scale();
00701
00702 unsigned char* rgb_buffer = (unsigned char*) malloc( colorspace_buffer_size( RGB,
00703 width,
00704 height ) );
00705 convert(m_img_cs, RGB, scaled_buffer, rgb_buffer, width, height);
00706
00707 Glib::RefPtr<Gdk::Pixbuf> image = Gdk::Pixbuf::create_from_data( rgb_buffer,
00708 Gdk::COLORSPACE_RGB,
00709 false,
00710 8,
00711 width,
00712 height,
00713 3 * width,
00714 Gdk::Pixbuf::SlotDestroyData(&free_rgb_buffer));
00715
00716 m_img_segmentation->set(image);
00717
00718 free(scaled_buffer);
00719 free(seg_buffer);
00720 }
00721
00722
00723
00724
00725 void ColorTrainWidget::free_rgb_buffer(const guint8* rgb_buffer)
00726 {
00727 free(const_cast<guint8 *>(rgb_buffer));
00728 }