77#include < QFileDialog>
88#include < QLabel>
99#include < QDir>
10+ #include < cfloat>
1011#include < QDirIterator>
1112#include < QVBoxLayout>
1213#include < QGraphicsView>
@@ -189,7 +190,7 @@ void LabelImages::clear_for_new_image(){
189190 m_output_boolean_mask.clear ();
190191 m_mask_image = ImageRGB32 ();
191192 m_annotations.clear ();
192- m_last_object_idx = 0 ;
193+ m_selected_obj_idx = 0 ;
193194 m_annotation_file_path = " " ;
194195 m_fail_to_load_annotation_file = false ;
195196}
@@ -255,7 +256,7 @@ void LabelImages::load_image_related_data(const std::string& image_path, size_t
255256 );
256257 }
257258 }
258- m_last_object_idx = m_annotations.size ();
259+ m_selected_obj_idx = m_annotations.size ();
259260 cout << " Loaded existing annotation file " << m_annotation_file_path << endl;
260261}
261262
@@ -272,7 +273,7 @@ void LabelImages::update_rendered_objects(VideoOverlaySet& overlay_set){
272273 if (form != nullptr ){
273274 label = form->display_name ();
274275 }
275- Color mask_box_color = (i_obj == m_last_object_idx ) ? COLOR_BLACK : COLOR_BLUE;
276+ Color mask_box_color = (i_obj == m_selected_obj_idx ) ? COLOR_BLACK : COLOR_BLUE;
276277 overlay_set.add (mask_box_color, mask_float_box, label);
277278 size_t mask_width = obj.mask_box .width ();
278279 size_t mask_height = obj.mask_box .height ();
@@ -359,7 +360,7 @@ void LabelImages::compute_mask(VideoOverlaySet& overlay_set){
359360 }
360361
361362 annotation.label = label;
362- m_last_object_idx = m_annotations.size ();
363+ m_selected_obj_idx = m_annotations.size ();
363364 m_annotations.emplace_back (std::move (annotation));
364365
365366 update_rendered_objects (overlay_set);
@@ -372,12 +373,54 @@ void LabelImages::compute_embeddings_for_folder(const std::string& image_folder_
372373 ML::compute_embeddings_for_folder (embedding_model_path, image_folder_path);
373374}
374375
375- void LabelImages::delete_last_annotation (){
376- if (m_annotations.size () > 0 ){
377- m_annotations. pop_back () ;
376+ void LabelImages::delete_selected_annotation (){
377+ if (m_annotations.size () == 0 || m_selected_obj_idx >= m_annotations. size () ){
378+ return ;
378379 }
379- if (m_annotations.size () > 0 ){
380- m_last_object_idx = m_annotations.size () - 1 ;
380+
381+ m_annotations.erase (m_annotations.begin () + m_selected_obj_idx);
382+
383+ if (m_annotations.size () == 0 ){
384+ m_selected_obj_idx = 0 ;
385+ return ;
386+ }
387+
388+ if (m_selected_obj_idx >= m_annotations.size ()){
389+ m_selected_obj_idx = m_annotations.size () - 1 ;
390+ } else {
391+ // no change to the currently selected index
392+ }
393+
394+ std::string& cur_label = m_annotations[m_selected_obj_idx].label ;
395+ FORM_LABEL.set_by_slug (cur_label);
396+ }
397+
398+ void LabelImages::change_annotation_selection_by_mouse (double x, double y){
399+ if (m_annotations.size () == 0 ){
400+ return ;
401+ }
402+ // no annotation image loaded
403+ if (source_image_width == 0 || source_image_height == 0 ){
404+ return ;
405+ }
406+
407+ auto & cur_ui_label = FORM_LABEL.slug ();
408+
409+ double closest_distance = DBL_MAX;
410+ for (size_t i = 0 ; i < m_annotations.size (); i++){
411+ ImageFloatBox float_box = pixelbox_to_floatbox (source_image_width, source_image_height, m_annotations[i].mask_box );
412+ double center_x = float_box.x + float_box.width /2.0 ;
413+ double center_y = float_box.y + float_box.height /2.0 ;
414+ double d2 = (center_x-x)*(center_x-x) + (center_y-y)*(center_y-y);
415+ if (d2 < closest_distance){
416+ closest_distance = d2;
417+ m_selected_obj_idx = i;
418+ }
419+ }
420+
421+ auto new_label = m_annotations[m_selected_obj_idx].label ;
422+ if (cur_ui_label != new_label){
423+ FORM_LABEL.set_by_slug (new_label);
381424 }
382425}
383426
@@ -440,7 +483,7 @@ LabelImages_Widget::LabelImages_Widget(
440483 scroll_layout->addWidget (button);
441484 connect (button, &QPushButton::clicked, this , [this ](bool ){
442485 auto & program = this ->m_program ;
443- program.delete_last_annotation ();
486+ program.delete_selected_annotation ();
444487 program.update_rendered_objects (this ->m_overlay_set );
445488 });
446489
@@ -468,9 +511,13 @@ void LabelImages_Widget::clear_for_new_image(){
468511}
469512
470513void LabelImages_Widget::on_config_value_changed (void * object){
471- if (m_program.m_annotations .size () > 0 && m_program.m_last_object_idx < m_program.m_annotations .size ()){
472- std::string& cur_label = m_program.m_annotations [m_program.m_last_object_idx ].label ;
473- cur_label = m_program.FORM_LABEL .slug ();
514+ // TODO: the logic here should be part of LabelImage program
515+ if (m_program.m_annotations .size () > 0 && m_program.m_selected_obj_idx < m_program.m_annotations .size ()){
516+ std::string& cur_label = m_program.m_annotations [m_program.m_selected_obj_idx ].label ;
517+ const std::string& ui_slug = m_program.FORM_LABEL .slug ();
518+ if (ui_slug != cur_label){
519+ cur_label = m_program.FORM_LABEL .slug ();
520+ }
474521 }
475522 m_program.update_rendered_objects (m_overlay_set);
476523}
@@ -495,7 +542,7 @@ void LabelImages_Widget::post_startup(VideoSource* source){
495542 }
496543
497544 m_embedding_info_label->setText (QString::fromStdString (embedding_path_display));
498- m_embedding_info_label->setStyleSheet (" color: blue " );
545+ m_embedding_info_label->setStyleSheet (" color: green " );
499546
500547 const auto cur_res = m_display_session.video_session ().current_resolution ();
501548 if (cur_res.width == 0 || cur_res.height == 0 ){
@@ -512,7 +559,7 @@ void LabelImages_Widget::post_startup(VideoSource* source){
512559void LabelImages_Widget::key_release (QKeyEvent* event){
513560 const auto key = Qt::Key (event->key ());
514561 if (key == Qt::Key::Key_Delete || key == Qt::Key::Key_Backspace){
515- m_program.delete_last_annotation ();
562+ m_program.delete_selected_annotation ();
516563 m_program.update_rendered_objects (m_overlay_set);
517564 }
518565}
@@ -529,6 +576,12 @@ void LabelImages_Widget::on_mouse_press(double x, double y){
529576}
530577
531578void LabelImages_Widget::on_mouse_release (double x, double y){
579+ if (m_mouse_start == m_mouse_end){
580+ // process mouse clicking
581+ // change currently selected annotation
582+ // also change the option values in the UI
583+ m_program.change_annotation_selection_by_mouse (x, y);
584+ }
532585 m_mouse_start.reset ();
533586 m_mouse_end.reset ();
534587 m_program.compute_mask (m_overlay_set);
0 commit comments