From c55efd189723a6b13065b2278ec5e0508b481a55 Mon Sep 17 00:00:00 2001 From: Brenno Date: Sun, 28 Mar 2021 15:55:22 -0300 Subject: [PATCH] Added opacity to Tracker effect Optimization improvements are still necessary --- src/TrackedObjectBBox.cpp | 14 ++++++--- src/TrackedObjectBBox.h | 1 + src/effects/Tracker.cpp | 65 +++++++++++++++++++++++++++------------ src/effects/Tracker.h | 2 ++ 4 files changed, 58 insertions(+), 24 deletions(-) diff --git a/src/TrackedObjectBBox.cpp b/src/TrackedObjectBBox.cpp index 647031de..301e2d5f 100644 --- a/src/TrackedObjectBBox.cpp +++ b/src/TrackedObjectBBox.cpp @@ -41,8 +41,8 @@ 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), - stroke_width(2) , background_alpha(1), background_corner(0), stroke(0,0,255,0), - background(0,0,255,0) + stroke_width(2) , background_alpha(1.0), stroke_alpha(0.0), background_corner(0), + stroke(0,0,255,0), background(0,0,255,0) { this->TimeScale = 1.0; return; @@ -334,6 +334,7 @@ Json::Value TrackedObjectBBox::JsonValue() const root["background_corner"] = background_corner.JsonValue(); root["background"] = background.JsonValue(); root["stroke_width"] = stroke_width.JsonValue(); + root["stroke_alpha"] = stroke_alpha.JsonValue(); // return JsonValue return root; @@ -420,6 +421,8 @@ void TrackedObjectBBox::SetJsonValue(const Json::Value root) background.SetJsonValue(root["background"]); if (!root["stroke_width"].isNull()) stroke_width.SetJsonValue(root["stroke_width"]); + if (!root["stroke_alpha"].isNull()) + stroke_alpha.SetJsonValue(root["stroke_alpha"]); return; } @@ -446,8 +449,8 @@ Json::Value TrackedObjectBBox::PropertiesJSON(int64_t requested_frame) const // Add the bounding-box Keyframes to the JSON object root["delta_x"] = add_property_json("Displacement X-axis", delta_x.GetValue(requested_frame), "float", "", &delta_x, -1.0, 1.0, false, requested_frame); root["delta_y"] = add_property_json("Displacement Y-axis", delta_y.GetValue(requested_frame), "float", "", &delta_y, -1.0, 1.0, false, requested_frame); - root["scale_x"] = add_property_json("Scale (Width)", scale_x.GetValue(requested_frame), "float", "", &scale_x, -1.0, 1.0, false, requested_frame); - root["scale_y"] = add_property_json("Scale (Height)", scale_y.GetValue(requested_frame), "float", "", &scale_y, -1.0, 1.0, false, requested_frame); + root["scale_x"] = add_property_json("Scale (Width)", scale_x.GetValue(requested_frame), "float", "", &scale_x, 0.0, 1.0, false, requested_frame); + root["scale_y"] = add_property_json("Scale (Height)", scale_y.GetValue(requested_frame), "float", "", &scale_y, 0.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); @@ -460,7 +463,8 @@ Json::Value TrackedObjectBBox::PropertiesJSON(int64_t requested_frame) const 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["stroke_alpha"] = add_property_json("Stroke alpha", stroke_alpha.GetValue(requested_frame), "float", "", &stroke_alpha, 0.0, 1.0, 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); diff --git a/src/TrackedObjectBBox.h b/src/TrackedObjectBBox.h index 6b951813..d6a0d2d7 100644 --- a/src/TrackedObjectBBox.h +++ b/src/TrackedObjectBBox.h @@ -171,6 +171,7 @@ namespace openshot Keyframe background_alpha; ///< Background box opacity Keyframe background_corner; ///< Radius of rounded corners Keyframe stroke_width; ///< Thickness of border line + Keyframe stroke_alpha; ///< Stroke box opacity Color stroke; ///< Border line color Color background; ///< Background fill color diff --git a/src/effects/Tracker.cpp b/src/effects/Tracker.cpp index e1d1e16f..bf058ea7 100644 --- a/src/effects/Tracker.cpp +++ b/src/effects/Tracker.cpp @@ -117,32 +117,18 @@ std::shared_ptr Tracker::GetFrame(std::shared_ptr frame, int64_t f if (trackedData->draw_box.GetValue(frame_number) == 1) { std::vector stroke_rgba = trackedData->stroke.GetColorRGBA(frame_number); + int stroke_width = trackedData->stroke_width.GetValue(frame_number); + float stroke_alpha = trackedData->stroke_alpha.GetValue(frame_number); std::vector bg_rgba = trackedData->background.GetColorRGBA(frame_number); + float bg_alpha = trackedData->background_alpha.GetValue(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 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, vertices2f[i], vertices2f[(i+1)%4], cv::Scalar(stroke_rgba[2],stroke_rgba[1],stroke_rgba[0]), - trackedData->stroke_width.GetValue(frame_number)); - } + DrawRectangleRGBA(frame_image, box, bg_rgba, bg_alpha, 1, true); + DrawRectangleRGBA(frame_image, box, stroke_rgba, stroke_alpha, stroke_width, false); } // Get the image of the Tracked Object' child clip @@ -187,6 +173,47 @@ std::shared_ptr Tracker::GetFrame(std::shared_ptr frame, int64_t f return frame; } + +void Tracker::DrawRectangleRGBA(cv::Mat &frame_image, cv::RotatedRect box, std::vector color, float alpha, int thickness, bool is_background){ + // Get the bouding box vertices + cv::Point2f vertices2f[4]; + box.points(vertices2f); + + // TODO: take a rectangle of frame_image by refencence and draw on top of that to improve speed + // select min enclosing rectangle to draw on a small portion of the image + // cv::Rect rect = box.boundingRect(); + // cv::Mat image = frame_image(rect) + + if(is_background){ + cv::Mat overlayFrame; + frame_image.copyTo(overlayFrame); + + // draw bounding box background + cv::Point vertices[4]; + for(int i = 0; i < 4; ++i){ + vertices[i] = vertices2f[i];} + + cv::Rect rect = box.boundingRect(); + cv::fillConvexPoly(overlayFrame, vertices, 4, cv::Scalar(color[2],color[1],color[0]), cv::LINE_AA); + // add opacity + cv::addWeighted(overlayFrame, 1-alpha, frame_image, alpha, 0, frame_image); + } + else{ + cv::Mat overlayFrame; + frame_image.copyTo(overlayFrame); + + // Draw bounding box + for (int i = 0; i < 4; i++) + { + cv::line(overlayFrame, vertices2f[i], vertices2f[(i+1)%4], cv::Scalar(color[2],color[1],color[0]), + thickness, cv::LINE_AA); + } + + // add opacity + cv::addWeighted(overlayFrame, 1-alpha, frame_image, alpha, 0, frame_image); + } +} + // Get the indexes and IDs of all visible objects in the given frame std::string Tracker::GetVisibleObjects(int64_t frame_number) const{ diff --git a/src/effects/Tracker.h b/src/effects/Tracker.h index e5210094..749ec1b4 100644 --- a/src/effects/Tracker.h +++ b/src/effects/Tracker.h @@ -88,6 +88,8 @@ namespace openshot /// Get the indexes and IDs of all visible objects in the given frame std::string GetVisibleObjects(int64_t frame_number) const override; + void DrawRectangleRGBA(cv::Mat &frame_image, cv::RotatedRect box, std::vector color, float alpha, int thickness, bool is_background); + /// Get and Set JSON methods std::string Json() const override; ///< Generate JSON string of this object void SetJson(const std::string value) override; ///< Load JSON string into this object