From d6e0acb0cbde41cfda53ba7e74a7aa1ed478d256 Mon Sep 17 00:00:00 2001 From: Brenno Date: Fri, 22 Jan 2021 20:03:05 -0300 Subject: [PATCH] ObjectDetection: show object's icons and transform handlers per frame Only show the tracked object's icon (on the mini-GUI to attach a clip to it) and transform handler if the object appears on the screen (i.e. it has data for the requested frame) --- src/Fraction.cpp | 2 +- src/Fraction.h | 2 +- src/TrackedObjectBBox.cpp | 24 +++++++++++++++++++++--- src/TrackedObjectBBox.h | 6 ++++-- src/effects/ObjectDetection.cpp | 23 ++++++++++++++--------- src/effects/Tracker.cpp | 1 + tests/CVTracker_Tests.cpp | 4 ++-- 7 files changed, 44 insertions(+), 18 deletions(-) diff --git a/src/Fraction.cpp b/src/Fraction.cpp index b0d5464d..a5576aad 100644 --- a/src/Fraction.cpp +++ b/src/Fraction.cpp @@ -81,7 +81,7 @@ void Fraction::Reduce() { } // Return the reciprocal as a new Fraction -Fraction Fraction::Reciprocal() +Fraction Fraction::Reciprocal() const { // flip the fraction return Fraction(den, num); diff --git a/src/Fraction.h b/src/Fraction.h index 0c46643e..7d2ba0a3 100644 --- a/src/Fraction.h +++ b/src/Fraction.h @@ -68,7 +68,7 @@ namespace openshot { int ToInt(); /// Return the reciprocal as a Fraction - Fraction Reciprocal(); + Fraction Reciprocal() const; }; diff --git a/src/TrackedObjectBBox.cpp b/src/TrackedObjectBBox.cpp index 75f96094..5ce95397 100644 --- a/src/TrackedObjectBBox.cpp +++ b/src/TrackedObjectBBox.cpp @@ -84,15 +84,30 @@ int64_t TrackedObjectBBox::GetLength() const } // Check if there is a bounding-box in the given frame -bool TrackedObjectBBox::Contains(int64_t frame_num) +bool TrackedObjectBBox::Contains(int64_t frame_num) const { // Get the time of given frame double time = this->FrameNToTime(frame_num, 1.0); // Create an iterator that points to the BoxVec pair indexed by the time of given frame (or the closest time) auto it = BoxVec.lower_bound(time); - if (it == BoxVec.end()) + if (it == BoxVec.end()){ // BoxVec pair not found return false; + } + return true; +} + +// Check if there is a bounding-box in the exact frame number +bool TrackedObjectBBox::ExactlyContains(int64_t frame_number) const +{ + // Get the time of given frame + double time = FrameNToTime(frame_number, 1.0); + // Create an iterator that points to the BoxVec pair indexed by the exact time of given frame + auto it = BoxVec.find(time); + if (it == BoxVec.end()){ + // BoxVec pair not found + return false; + } return true; } @@ -210,7 +225,7 @@ Fraction TrackedObjectBBox::GetBaseFPS(){ } // Get the time of the given frame -double TrackedObjectBBox::FrameNToTime(int64_t frame_number, double time_scale){ +double TrackedObjectBBox::FrameNToTime(int64_t frame_number, double time_scale) const{ double time = ((double)frame_number) * this->BaseFps.Reciprocal().ToDouble() * (1.0 / time_scale); return time; @@ -384,6 +399,9 @@ Json::Value TrackedObjectBBox::PropertiesJSON(int64_t requested_frame) const // Id root["box_id"] = add_property_json("Box ID", 0.0, "string", Id(), NULL, -1, -1, true, requested_frame); + // Add a boolean property to inform if the object has data for the requested frame + root["visible"] = add_property_json("Visible", ExactlyContains(requested_frame), "bool", "", NULL, -1, -1, true, requested_frame); + // Add the data of given frame bounding-box to the JSON object root["x1"] = add_property_json("X1", box.cx-(box.width/2), "float", "", NULL, 0.0, 1.0, false, requested_frame); root["y1"] = add_property_json("Y1", box.cy-(box.height/2), "float", "", NULL, 0.0, 1.0, false, requested_frame); diff --git a/src/TrackedObjectBBox.h b/src/TrackedObjectBBox.h index a8deadf6..b670b3a5 100644 --- a/src/TrackedObjectBBox.h +++ b/src/TrackedObjectBBox.h @@ -186,7 +186,9 @@ namespace openshot void ScalePoints(double scale) override; /// Check if there is a bounding-box in the given frame - bool Contains(int64_t frame_number); + bool Contains(int64_t frame_number) const; + /// Check if there is a bounding-box in the exact frame number + bool ExactlyContains(int64_t frame_number) const; /// Get the size of BoxVec map int64_t GetLength() const; @@ -205,7 +207,7 @@ namespace openshot bool LoadBoxData(std::string inputFilePath); /// Get the time of the given frame - double FrameNToTime(int64_t frame_number, double time_scale); + double FrameNToTime(int64_t frame_number, double time_scale) const; /// Interpolate the bouding-boxes properties BBox InterpolateBoxes(double t1, double t2, BBox left, BBox right, double target); diff --git a/src/effects/ObjectDetection.cpp b/src/effects/ObjectDetection.cpp index f95f559b..62107013 100644 --- a/src/effects/ObjectDetection.cpp +++ b/src/effects/ObjectDetection.cpp @@ -346,15 +346,20 @@ std::string ObjectDetection::PropertiesJSON(int64_t requested_frame) const { // Save the trackedObject Id on root Json::Value trackedObjectJSON = trackedObject.second->PropertiesJSON(requested_frame); root["box_id-"+to_string(trackedObject.first)] = trackedObjectJSON["box_id"]; - root["x1-"+to_string(trackedObject.first)] = trackedObjectJSON["x1"]; - root["y1-"+to_string(trackedObject.first)] = trackedObjectJSON["y1"]; - root["x2-"+to_string(trackedObject.first)] = trackedObjectJSON["x2"]; - root["y2-"+to_string(trackedObject.first)] = trackedObjectJSON["y2"]; - root["delta_x-"+to_string(trackedObject.first)] = trackedObjectJSON["delta_x"]; - root["delta_y-"+to_string(trackedObject.first)] = trackedObjectJSON["delta_y"]; - root["scale_x-"+to_string(trackedObject.first)] = trackedObjectJSON["scale_x"]; - root["scale_y-"+to_string(trackedObject.first)] = trackedObjectJSON["scale_y"]; - root["rotation-"+to_string(trackedObject.first)] = trackedObjectJSON["rotation"]; + root["visible-"+to_string(trackedObject.first)] = trackedObjectJSON["visible"]; + + // Add trackedObject's properties only if it's visible in this frame (performance boost) + if (trackedObjectJSON["visible"]["value"].asBool()){ + root["x1-"+to_string(trackedObject.first)] = trackedObjectJSON["x1"]; + root["y1-"+to_string(trackedObject.first)] = trackedObjectJSON["y1"]; + root["x2-"+to_string(trackedObject.first)] = trackedObjectJSON["x2"]; + root["y2-"+to_string(trackedObject.first)] = trackedObjectJSON["y2"]; + root["delta_x-"+to_string(trackedObject.first)] = trackedObjectJSON["delta_x"]; + root["delta_y-"+to_string(trackedObject.first)] = trackedObjectJSON["delta_y"]; + root["scale_x-"+to_string(trackedObject.first)] = trackedObjectJSON["scale_x"]; + root["scale_y-"+to_string(trackedObject.first)] = trackedObjectJSON["scale_y"]; + root["rotation-"+to_string(trackedObject.first)] = trackedObjectJSON["rotation"]; + } } root["id"] = add_property_json("ID", 0.0, "string", Id(), NULL, -1, -1, true, requested_frame); diff --git a/src/effects/Tracker.cpp b/src/effects/Tracker.cpp index 5f43cbeb..ec755392 100644 --- a/src/effects/Tracker.cpp +++ b/src/effects/Tracker.cpp @@ -245,6 +245,7 @@ std::string Tracker::PropertiesJSON(int64_t requested_frame) const { for (auto const& trackedObject : trackedObjects){ Json::Value trackedObjectJSON = trackedObject.second->PropertiesJSON(requested_frame); root["box_id-"+to_string(trackedObject.first)] = trackedObjectJSON["box_id"]; + root["visible-"+to_string(trackedObject.first)] = trackedObjectJSON["visible"]; root["x1-"+to_string(trackedObject.first)] = trackedObjectJSON["x1"]; root["y1-"+to_string(trackedObject.first)] = trackedObjectJSON["y1"]; root["x2-"+to_string(trackedObject.first)] = trackedObjectJSON["x2"]; diff --git a/tests/CVTracker_Tests.cpp b/tests/CVTracker_Tests.cpp index cab85062..3fdb220c 100644 --- a/tests/CVTracker_Tests.cpp +++ b/tests/CVTracker_Tests.cpp @@ -75,7 +75,7 @@ SUITE(CVTracker_Tests) float y = fd.y1; float width = fd.x2 - x; float height = fd.y2 - y; - std::cout<<"\n\n Error: "<< processingController.GetErrorMessage() <<"\n"; + // Compare if tracked data is equal to pre-tested ones CHECK_EQUAL(259, (int)(x * 640)); CHECK_EQUAL(131, (int)(y * 360)); @@ -140,7 +140,7 @@ SUITE(CVTracker_Tests) float y_2 = fd_2.y1; float width_2 = fd_2.x2 - x_2; float height_2 = fd_2.y2 - y_2; - std::cout<<"\n\n Error: "<< processingController.GetErrorMessage() <<"\n"; + // Compare first tracker data with second tracker data CHECK_EQUAL((int)(x_1 * 640), (int)(x_2 * 640)); CHECK_EQUAL((int)(y_1 * 360), (int)(y_2 * 360));