diff --git a/dlib/data_io/image_dataset_metadata.h b/dlib/data_io/image_dataset_metadata.h index 7f3ede426a..acfbff90ac 100644 --- a/dlib/data_io/image_dataset_metadata.h +++ b/dlib/data_io/image_dataset_metadata.h @@ -93,6 +93,27 @@ namespace dlib ensures - returns true if label metadata is present and false otherwise. !*/ + + bool operator==(const box& rhs) const + { + return rect == rhs.rect && + parts == rhs.parts && + label == rhs.label && + difficult == rhs.difficult && + truncated == rhs.truncated && + occluded == rhs.occluded && + ignore == rhs.ignore && + pose == rhs.pose && + detection_score == rhs.detection_score && + angle == rhs.angle && + gender == rhs.gender && + age == rhs.age; + } + + bool operator!=(const box& rhs) const + { + return !(*this == rhs); + } }; // ------------------------------------------------------------------------------------ diff --git a/tools/imglab/src/metadata_editor.cpp b/tools/imglab/src/metadata_editor.cpp index f3e0e49db2..459f1fb88c 100644 --- a/tools/imglab/src/metadata_editor.cpp +++ b/tools/imglab/src/metadata_editor.cpp @@ -21,6 +21,11 @@ extern const char* VERSION; // ---------------------------------------------------------------------------------------- +std::vector get_overlays ( + const dlib::image_dataset_metadata::image& data, + color_mapper& string_to_color +); + metadata_editor:: metadata_editor( const std::string& filename_, @@ -390,6 +395,25 @@ on_keydown ( select_image(image_pos); } + if ((key == 'z' || key == 'Z') && (state&base_window::KBD_MOD_CONTROL) && !overlay_label.has_input_focus()) + { + if (state&base_window::KBD_MOD_SHIFT) + { + perform_redo(); + } + else + { + perform_undo(); + } + return; + } + + if ((key == 'y' || key == 'Y') && (state&base_window::KBD_MOD_CONTROL) && !overlay_label.has_input_focus()) + { + perform_redo(); + return; + } + // Make 'w' and 's' act like KEY_UP and KEY_DOWN if ((key == 'w' || key == 'W') && !overlay_label.has_input_focus()) { @@ -532,6 +556,12 @@ load_image( if (idx >= metadata.images.size()) return; + if (image_pos != idx) + { + undo_history.clear(); + redo_history.clear(); + } + image_pos = idx; array2d img; @@ -556,6 +586,40 @@ load_image( // ---------------------------------------------------------------------------------------- +void metadata_editor:: +perform_undo() +{ + if (!undo_history.empty()) + { + redo_history.push_back(metadata.images[image_pos].boxes); + if (redo_history.size() > MAX_UNDO_HISTORY) redo_history.erase(redo_history.begin()); + + metadata.images[image_pos].boxes = undo_history.back(); + undo_history.pop_back(); + display.clear_overlay(); + display.add_overlay(get_overlays(metadata.images[image_pos], string_to_color)); + } +} + +// ---------------------------------------------------------------------------------------- + +void metadata_editor:: +perform_redo() +{ + if (!redo_history.empty()) + { + undo_history.push_back(metadata.images[image_pos].boxes); + if (undo_history.size() > MAX_UNDO_HISTORY) undo_history.erase(undo_history.begin()); + + metadata.images[image_pos].boxes = redo_history.back(); + redo_history.pop_back(); + display.clear_overlay(); + display.add_overlay(get_overlays(metadata.images[image_pos], string_to_color)); + } +} + +// ---------------------------------------------------------------------------------------- + void metadata_editor:: load_image_and_set_size( unsigned long idx @@ -564,6 +628,12 @@ load_image_and_set_size( if (idx >= metadata.images.size()) return; + if (image_pos != idx) + { + undo_history.clear(); + redo_history.clear(); + } + image_pos = idx; array2d img; @@ -616,6 +686,7 @@ on_overlay_rects_changed( const std::vector& rects = display.get_overlay_rects(); std::vector& boxes = metadata.images[image_pos].boxes; + std::vector old_boxes = boxes; boxes.clear(); for (unsigned long i = 0; i < rects.size(); ++i) @@ -627,6 +698,14 @@ on_overlay_rects_changed( temp.ignore = rects[i].crossed_out; boxes.push_back(temp); } + + if (old_boxes != boxes) + { + undo_history.push_back(old_boxes); + if (undo_history.size() > MAX_UNDO_HISTORY) + undo_history.erase(undo_history.begin()); + redo_history.clear(); + } } } diff --git a/tools/imglab/src/metadata_editor.h b/tools/imglab/src/metadata_editor.h index eba3ed3a44..6320e36256 100644 --- a/tools/imglab/src/metadata_editor.h +++ b/tools/imglab/src/metadata_editor.h @@ -7,6 +7,7 @@ #include #include #include +#include // ---------------------------------------------------------------------------------------- @@ -69,6 +70,8 @@ class metadata_editor : public dlib::drawable_window ); private: + void perform_undo(); + void perform_redo(); void file_save(); void file_save_as(); @@ -96,6 +99,10 @@ class metadata_editor : public dlib::drawable_window std::string filename; dlib::image_dataset_metadata::dataset metadata; + std::vector> undo_history; + std::vector> redo_history; + static constexpr size_t MAX_UNDO_HISTORY = 10; + dlib::menu_bar mbar; dlib::list_box lb_images; unsigned long image_pos;