From 4ea85ec859150d902900a86bbdfa5702d26285d0 Mon Sep 17 00:00:00 2001 From: Brenno Date: Sat, 27 Mar 2021 22:50:01 -0300 Subject: [PATCH] Implemented Stroke width and background color for Tracker bounding boxes --- src/Color.cpp | 11 +++++++++++ src/Color.h | 3 +++ src/TrackedObjectBBox.cpp | 36 +++++++++++++++++++++++++++++++++--- src/TrackedObjectBBox.h | 7 +++++++ src/effects/Tracker.cpp | 21 ++++++++++++++++++--- 5 files changed, 72 insertions(+), 6 deletions(-) diff --git a/src/Color.cpp b/src/Color.cpp index fe3055918..e848f1f7f 100644 --- a/src/Color.cpp +++ b/src/Color.cpp @@ -75,6 +75,17 @@ std::string Color::GetColorHex(int64_t frame_number) { return QColor( r,g,b,a ).name().toStdString(); } +// Get the RGBA values of a color at a specific frame +std::vector Color::GetColorRGBA(int64_t frame_number) { + std::vector rgba; + rgba.push_back(red.GetInt(frame_number)); + rgba.push_back(green.GetInt(frame_number)); + rgba.push_back(blue.GetInt(frame_number)); + rgba.push_back(alpha.GetInt(frame_number)); + + return rgba; +} + // Get the distance between 2 RGB pairs (alpha is ignored) long Color::GetDistance(long R1, long G1, long B1, long R2, long G2, long B2) { diff --git a/src/Color.h b/src/Color.h index 2b4a6d771..564af4ef9 100644 --- a/src/Color.h +++ b/src/Color.h @@ -65,6 +65,9 @@ namespace openshot { /// Get the HEX value of a color at a specific frame std::string GetColorHex(int64_t frame_number); + // Get the RGBA values of a color at a specific frame + std::vector GetColorRGBA(int64_t frame_number); + /// Get the distance between 2 RGB pairs. (0=identical colors, 10=very close colors, 760=very different colors) static long GetDistance(long R1, long G1, long B1, long R2, long G2, long B2); diff --git a/src/TrackedObjectBBox.cpp b/src/TrackedObjectBBox.cpp index 19cc80929..647031de2 100644 --- a/src/TrackedObjectBBox.cpp +++ b/src/TrackedObjectBBox.cpp @@ -40,7 +40,9 @@ using namespace openshot; // Default Constructor that sets the bounding-box displacement as 0 and the scales as 1 for the first frame -TrackedObjectBBox::TrackedObjectBBox() : delta_x(0.0), delta_y(0.0), scale_x(1.0), scale_y(1.0), rotation(0.0) +TrackedObjectBBox::TrackedObjectBBox() : delta_x(0.0), delta_y(0.0), scale_x(1.0), scale_y(1.0), rotation(0.0), + stroke_width(2) , background_alpha(1), background_corner(0), stroke(0,0,255,0), + background(0,0,255,0) { this->TimeScale = 1.0; return; @@ -327,6 +329,11 @@ Json::Value TrackedObjectBBox::JsonValue() const root["rotation"] = rotation.JsonValue(); root["visible"] = visible.JsonValue(); root["draw_box"] = draw_box.JsonValue(); + root["stroke"] = stroke.JsonValue(); + root["background_alpha"] = background_alpha.JsonValue(); + root["background_corner"] = background_corner.JsonValue(); + root["background"] = background.JsonValue(); + root["stroke_width"] = stroke_width.JsonValue(); // return JsonValue return root; @@ -403,7 +410,16 @@ void TrackedObjectBBox::SetJsonValue(const Json::Value root) visible.SetJsonValue(root["visible"]); if (!root["draw_box"].isNull()) draw_box.SetJsonValue(root["draw_box"]); - + if (!root["stroke"].isNull()) + stroke.SetJsonValue(root["stroke"]); + if (!root["background_alpha"].isNull()) + background_alpha.SetJsonValue(root["background_alpha"]); + if (!root["background_corner"].isNull()) + background_corner.SetJsonValue(root["background_corner"]); + if (!root["background"].isNull()) + background.SetJsonValue(root["background"]); + if (!root["stroke_width"].isNull()) + stroke_width.SetJsonValue(root["stroke_width"]); return; } @@ -434,10 +450,24 @@ Json::Value TrackedObjectBBox::PropertiesJSON(int64_t requested_frame) const root["scale_y"] = add_property_json("Scale (Height)", scale_y.GetValue(requested_frame), "float", "", &scale_y, -1.0, 1.0, false, requested_frame); root["rotation"] = add_property_json("Rotation", rotation.GetValue(requested_frame), "float", "", &rotation, 0, 360, false, requested_frame); root["visible"] = add_property_json("Visible", visible.GetValue(requested_frame), "int", "", &visible, 0, 1, false, requested_frame); - + root["draw_box"] = add_property_json("Draw Box", draw_box.GetValue(requested_frame), "int", "", &draw_box, -1, 1.0, false, requested_frame); root["draw_box"]["choices"].append(add_property_choice_json("Off", 0, draw_box.GetValue(requested_frame))); root["draw_box"]["choices"].append(add_property_choice_json("On", 1, draw_box.GetValue(requested_frame))); + + root["stroke"] = add_property_json("Border", 0.0, "color", "", NULL, 0, 255, false, requested_frame); + root["stroke"]["red"] = add_property_json("Red", stroke.red.GetValue(requested_frame), "float", "", &stroke.red, 0, 255, false, requested_frame); + root["stroke"]["blue"] = add_property_json("Blue", stroke.blue.GetValue(requested_frame), "float", "", &stroke.blue, 0, 255, false, requested_frame); + root["stroke"]["green"] = add_property_json("Green", stroke.green.GetValue(requested_frame), "float", "", &stroke.green, 0, 255, false, requested_frame); + root["stroke_width"] = add_property_json("Stroke Width", stroke_width.GetValue(requested_frame), "int", "", &stroke_width, 1, 10, false, requested_frame); + + root["background_alpha"] = add_property_json("Background Alpha", background_alpha.GetValue(requested_frame), "float", "", &background_alpha, 0.0, 1.0, false, requested_frame); + root["background_corner"] = add_property_json("Background Corner Radius", background_corner.GetValue(requested_frame), "int", "", &background_corner, 0.0, 60.0, false, requested_frame); + + root["background"] = add_property_json("Background", 0.0, "color", "", NULL, 0, 255, false, requested_frame); + root["background"]["red"] = add_property_json("Red", background.red.GetValue(requested_frame), "float", "", &background.red, 0, 255, false, requested_frame); + root["background"]["blue"] = add_property_json("Blue", background.blue.GetValue(requested_frame), "float", "", &background.blue, 0, 255, false, requested_frame); + root["background"]["green"] = add_property_json("Green", background.green.GetValue(requested_frame), "float", "", &background.green, 0, 255, false, requested_frame); // Return formatted string return root; diff --git a/src/TrackedObjectBBox.h b/src/TrackedObjectBBox.h index 693cac8b6..6b9518134 100644 --- a/src/TrackedObjectBBox.h +++ b/src/TrackedObjectBBox.h @@ -43,6 +43,7 @@ #include "Json.h" #include "KeyFrame.h" #include "TrackedObjectBase.h" +#include "Color.h" #include "protobuf_messages/trackerdata.pb.h" #include @@ -167,6 +168,12 @@ namespace openshot Keyframe scale_x; ///< X-direction scale Keyframe Keyframe scale_y; ///< Y-direction scale Keyframe Keyframe rotation; ///< Rotation Keyframe + Keyframe background_alpha; ///< Background box opacity + Keyframe background_corner; ///< Radius of rounded corners + Keyframe stroke_width; ///< Thickness of border line + Color stroke; ///< Border line color + Color background; ///< Background fill color + std::string protobufDataPath; ///< Path to the protobuf file that holds the bounding box points across the frames /// Default Constructor diff --git a/src/effects/Tracker.cpp b/src/effects/Tracker.cpp index 8ea249428..e1d1e16fa 100644 --- a/src/effects/Tracker.cpp +++ b/src/effects/Tracker.cpp @@ -116,17 +116,32 @@ std::shared_ptr Tracker::GetFrame(std::shared_ptr frame, int64_t f // Check if track data exists for the requested frame if (trackedData->draw_box.GetValue(frame_number) == 1) { + std::vector stroke_rgba = trackedData->stroke.GetColorRGBA(frame_number); + std::vector bg_rgba = trackedData->background.GetColorRGBA(frame_number); + // Create a rotated rectangle object that holds the bounding box cv::RotatedRect box ( cv::Point2f( (int)(fd.cx*fw), (int)(fd.cy*fh) ), cv::Size2f( (int)(fd.width*fw), (int)(fd.height*fh) ), (int) (fd.angle) ); // Get the bouding box vertices - cv::Point2f vertices[4]; - box.points(vertices); + cv::Point2f vertices2f[4]; + box.points(vertices2f); + + cv::Point vertices[4]; + for(int i = 0; i < 4; ++i){ + vertices[i] = vertices2f[i]; + } + + cv::fillConvexPoly(frame_image, vertices, 4, cv::Scalar(bg_rgba[2],bg_rgba[1],bg_rgba[0]), cv::LINE_AA); + + // const Point *pts = (const cv::Point*) cv::Mat(vertices).data; + // cv::polylines(frame_image, &pts, 4, 1, true, (255, 0, 255), cv::Scalar(stroke_rgba[2],stroke_rgba[1],stroke_rgba[0]), cv::LINE_AA); + // Draw the bounding-box on the image for (int i = 0; i < 4; i++) { - cv::line(frame_image, vertices[i], vertices[(i+1)%4], cv::Scalar(255,0,0), 2); + cv::line(frame_image, vertices2f[i], vertices2f[(i+1)%4], cv::Scalar(stroke_rgba[2],stroke_rgba[1],stroke_rgba[0]), + trackedData->stroke_width.GetValue(frame_number)); } }