@@ -447,19 +447,39 @@ void LabelImages::change_annotation_selection_by_mouse(double x, double y){
447447 if (source_image_width == 0 || source_image_height == 0 || m_annotations.size () == 0 ){
448448 return ;
449449 }
450+
451+ const size_t px = (size_t )std::max<double >(source_image_width * x + 0.5 , 0 );
452+ const size_t py = (size_t )std::max<double >(source_image_height * y + 0.5 , 0 );
450453
451454 double closest_distance = DBL_MAX;
455+ std::vector<size_t > zero_distance_annotations;
452456 for (size_t i = 0 ; i < m_annotations.size (); i++){
453- ImageFloatBox float_box = pixelbox_to_floatbox (source_image_width, source_image_height, m_annotations[i].mask_box );
454- double center_x = float_box.x + float_box.width /2.0 ;
455- double center_y = float_box.y + float_box.height /2.0 ;
456- double d2 = (center_x-x)*(center_x-x) + (center_y-y)*(center_y-y);
457+ const size_t dx = m_annotations[i].mask_box .distance_to_point_x (px);
458+ const size_t dy = m_annotations[i].mask_box .distance_to_point_y (py);
459+ const size_t d2 = dx*dx + dy*dy;
460+ if (d2 == 0 ){
461+ zero_distance_annotations.push_back (i);
462+ }
457463 if (d2 < closest_distance){
458464 closest_distance = d2;
459465 m_selected_obj_idx = i;
460466 }
461467 }
462468
469+ if (zero_distance_annotations.size () > 1 ){
470+ // this point is inside multiple boxes, we then use the closest to the box center to determine
471+ closest_distance = DBL_MAX;
472+ for (size_t i : zero_distance_annotations){
473+ const size_t dx = m_annotations[i].mask_box .center_distance_to_point_x (px);
474+ const size_t dy = m_annotations[i].mask_box .center_distance_to_point_y (py);
475+ const size_t d2 = dx*dx + dy*dy;
476+ if (d2 < closest_distance){
477+ closest_distance = d2;
478+ m_selected_obj_idx = i;
479+ }
480+ }
481+ }
482+
463483 auto new_label = m_annotations[m_selected_obj_idx].label ;
464484 set_selected_label (new_label);
465485}
@@ -779,17 +799,30 @@ void LabelImages_Widget::on_mouse_press(double x, double y){
779799 m_mouse_end.emplace ();
780800 m_mouse_start->first = m_mouse_end->first = x;
781801 m_mouse_start->second = m_mouse_end->second = y;
802+ m_mouse_start_time = std::chrono::high_resolution_clock::now ();
782803}
783804
784805void LabelImages_Widget::on_mouse_release (double x, double y){
785- if (m_mouse_start == m_mouse_end){
806+ const std::chrono::duration<double > duration = std::chrono::high_resolution_clock::now () - m_mouse_start_time;
807+ const double rel_x = std::fabs (m_mouse_start->first - m_mouse_end->first );
808+ const double rel_y = std::fabs (m_mouse_start->second - m_mouse_end->second );
809+
810+ m_mouse_start.reset ();
811+ m_mouse_end.reset ();
812+
813+ // cout << "Mouse release " << (rel_x) << " " << (rel_y) << " duration " << duration << " " <<
814+ // (duration < std::chrono::milliseconds(150)) << endl;
815+
816+ // user may have very small movement while doing quick clicking. To register this as a simple click, use relative
817+ // screen distance threshold 0.0015 and click duration threshold 0.15 second:
818+ if ((rel_x == 0 && rel_y == 0 ) || (rel_x < 0.0015 && rel_y < 0.0015 && duration < std::chrono::milliseconds (150 ))){
786819 // process mouse clicking
787820 // change currently selected annotation
788821 // also change the option values in the UI
789822 m_program.change_annotation_selection_by_mouse (x, y);
823+ return ;
790824 }
791- m_mouse_start.reset ();
792- m_mouse_end.reset ();
825+
793826 m_program.compute_mask ();
794827}
795828
0 commit comments