diff options
author | Your Name <you@example.com> | 2021-08-17 12:38:14 -0400 |
---|---|---|
committer | Your Name <you@example.com> | 2021-08-17 12:38:14 -0400 |
commit | ab5e941dcaedcf2cc896eed1ea257c59780fdb59 (patch) | |
tree | 503284d6999fb92f86bbf39385e17e9b7d8bd8fa | |
parent | 2a4ca022ad37ff2452ec3addb8c760a93bb616c6 (diff) | |
download | annotator-ab5e941dcaedcf2cc896eed1ea257c59780fdb59.tar.gz annotator-ab5e941dcaedcf2cc896eed1ea257c59780fdb59.tar.bz2 annotator-ab5e941dcaedcf2cc896eed1ea257c59780fdb59.zip |
Implemented parts of mouse click event
-rw-r--r-- | src/labeller.cc | 5 | ||||
-rw-r--r-- | src/labeller.h | 4 | ||||
-rw-r--r-- | src/playback.cc | 8 | ||||
-rw-r--r-- | src/playback.h | 6 | ||||
-rw-r--r-- | src/ui.cc | 48 |
5 files changed, 57 insertions, 14 deletions
diff --git a/src/labeller.cc b/src/labeller.cc index f7fa69e..ea72db0 100644 --- a/src/labeller.cc +++ b/src/labeller.cc @@ -54,6 +54,11 @@ namespace backend { return labs; } + std::vector<label>& labeller::getEditableLabels() { + return data->annotations; + } + + std::vector<std::string> labeller::getLabels() const { return data->labels; } diff --git a/src/labeller.h b/src/labeller.h index e0dc090..cf108f5 100644 --- a/src/labeller.h +++ b/src/labeller.h @@ -10,6 +10,9 @@ namespace backend { struct rect { int x1=0, x2=0, y1=0, y2=0; + bool nonzero() const { + return (x1 != 0 || x1 != 0 || y1 != 0 || y2 != 0); + } }; struct label { @@ -24,6 +27,7 @@ namespace backend { public: labeller(const std::filesystem::path& savepath); std::pair<label, label> getSurrounding(double time) const; + std::vector<label>& getEditableLabels(); std::vector<std::string> getLabels() const; std::vector<std::string> getRectangleLabels() const; void applyLabel(std::string name, double time); diff --git a/src/playback.cc b/src/playback.cc index 8839528..bbc2649 100644 --- a/src/playback.cc +++ b/src/playback.cc @@ -1,4 +1,5 @@ #include "playback.h" +#include "labeller.h" #include <opencv2/opencv.hpp> #include <vector> #include <stdexcept> @@ -31,7 +32,12 @@ namespace frontend { cap.release(); } - void playback::display(const std::string& windowName) const { + void playback::display(const std::string& windowName, const backend::rect &r) const { + cv::Mat curr(data->images[data->frameNum]); + if(r.nonzero()) { + // Update with the rectangle + cv::rectangle(curr, cv::Point(r.x1, r.y1), cv::Point(r.x2, r.y2), cv::Scalar(255, 0, 0), 2, cv::LINE_8); + } cv::imshow(windowName, data->images[data->frameNum]); } diff --git a/src/playback.h b/src/playback.h index 2fd5fa9..3f6e67f 100644 --- a/src/playback.h +++ b/src/playback.h @@ -3,12 +3,16 @@ #include <memory> #include <string> +namespace backend { + struct rect; +} + namespace frontend { struct playback_impl; class playback { public: playback(const std::filesystem::path& video, std::size_t frameCap=0); - void display(const std::string& windowName) const; + void display(const std::string& windowName, const backend::rect &r) const; bool seekFrame(std::size_t frameNum); std::size_t getFrame() const; bool seekTime(double time); @@ -73,29 +73,52 @@ namespace frontend { return false; } + backend::label* getCurrentRectLabel(ui_impl *data) { + auto labs = data->llr->getEditableLabels(); + for(auto rit = labs.rbegin(); rit != labs.rend(); rit++) { + if(rit->location.nonzero()) { + return &(*rit); + } + } + return nullptr; + } + void mouseCallback(int event, int x, int y, int flags, void* userdata) { // userdata is actually a &shared_ptr<ui_impl> - shared_ptr<ui_impl> data = (shared_ptr<ui_impl>) *userdata; + auto data = static_cast<ui_impl*>(userdata); static bool mouseDown = false; // We're interested in left button down/up and movement when down if(event == cv::EVENT_LBUTTONDOWN) { // If the current frame doesn't have a rectangle label, then make one mouseDown = true; - double time = data->pb->getTime() - auto labs = data->llr->getSurrounding(time); - backend::label current; - if(labs.first.time == time) { - current = labs.first; - } else if(labs.second.time == time) { - current = labs.second; - } else { - + double time = data->pb->getTime(); + auto lab = getCurrentRectLabel(data); + if(lab && lab->time == time) { + // Use this one + } else { // Make one + // Try to use the first rectangle annotation, fall back on normal, then "Rectangle" + std::string name = "Rectangle"; + if(!data->llr->getRectangleLabels().empty()) { + name = data->llr->getRectangleLabels()[0]; + } else if(!data->llr->getLabels().empty()) { + name = data->llr->getLabels()[0]; + } + data->llr->applyLabel(name, time); + lab = &data->llr->getEditableLabels().back(); } + lab->location.x1 = x; + lab->location.y1 = y; } else if(event == cv::EVENT_LBUTTONUP) { // Mouse is no longer down mouseDown = false; } else if(event == cv::EVENT_MOUSEMOVE) { // If the mouse is down, update x2 and y2 of current window + if(mouseDown) { + auto lab = getCurrentRectLabel(data); // It will be valid! TODO: Will it? + std::cout << "Updating location from " << lab->location.x2 << ", " << lab->location.y2 << " to " << x << ", " << y << "\n"; + lab->location.x2 = x; + lab->location.y2 = y; + } } } @@ -111,9 +134,10 @@ namespace frontend { ioctl(STDOUT_FILENO, TIOCGWINSZ, &size); int cols = size.ws_col; // Register mouse callback - cv::setMouseCallback("Video", mouseCallback, &data); + data->pb->display("Video", (getCurrentRectLabel(data.get()))? getCurrentRectLabel(data.get())->location : backend::rect()); + cv::setMouseCallback("Video", mouseCallback, data.get()); while(true) { - data->pb->display("Video"); + data->pb->display("Video", (getCurrentRectLabel(data.get()))? getCurrentRectLabel(data.get())->location : backend::rect()); data->pb->interFrameSleep(); if(handleKey(cv::pollKey(), data)) { break; |