From d24c2e451c5ea6a21ab08495b9532c2ced60352d Mon Sep 17 00:00:00 2001 From: Brenno Date: Thu, 4 Feb 2021 15:45:33 -0300 Subject: [PATCH] Added support to insert the image of a clip inside a Tracked Object --- src/Clip.cpp | 2 ++ src/TrackedObjectBBox.cpp | 9 ++++++++ src/TrackedObjectBase.cpp | 2 ++ src/TrackedObjectBase.h | 6 +++++- src/effects/Tracker.cpp | 45 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 63 insertions(+), 1 deletion(-) diff --git a/src/Clip.cpp b/src/Clip.cpp index 14621933..3fbd975e 100644 --- a/src/Clip.cpp +++ b/src/Clip.cpp @@ -1218,6 +1218,8 @@ void Clip::AddEffect(EffectBase* effect) // Check if this clip has a parent timeline if (parentTimeline){ + effect->ParentTimeline(parentTimeline); + // Iterate through effect's vector of Tracked Objects for (auto const& trackedObject : effect->trackedObjects){ diff --git a/src/TrackedObjectBBox.cpp b/src/TrackedObjectBBox.cpp index 16329aca..cbdc7628 100644 --- a/src/TrackedObjectBBox.cpp +++ b/src/TrackedObjectBBox.cpp @@ -46,6 +46,7 @@ TrackedObjectBBox::TrackedObjectBBox() : delta_x(0.0), delta_y(0.0), scale_x(1.0 return; } + // Add a BBox to the BoxVec map void TrackedObjectBBox::AddBox(int64_t _frame_num, float _cx, float _cy, float _width, float _height, float _angle) { @@ -316,6 +317,7 @@ Json::Value TrackedObjectBBox::JsonValue() const root["BaseFPS"]["num"] = BaseFps.num; root["BaseFPS"]["den"] = BaseFps.den; root["TimeScale"] = TimeScale; + root["child_clip_id"] = ChildClipId(); // Keyframe's properties root["delta_x"] = delta_x.JsonValue(); @@ -375,6 +377,10 @@ void TrackedObjectBBox::SetJsonValue(const Json::Value root) if (!root["protobuf_data_path"].isNull()) protobufDataPath = root["protobuf_data_path"].asString(); + // Set the id of the child clio + if (!root["child_clip_id"].isNull()) + ChildClipId(root["child_clip_id"].asString()); + // Set the Keyframes by the given JSON object if (!root["delta_x"].isNull()) delta_x.SetJsonValue(root["delta_x"]); @@ -403,6 +409,9 @@ Json::Value TrackedObjectBBox::PropertiesJSON(int64_t requested_frame) const // Add the ID of this object to the JSON object root["box_id"] = add_property_json("Box ID", 0.0, "string", Id(), NULL, -1, -1, true, requested_frame); + // Add the ID of this object's child clip to the JSON object + root["child_clip_id"] = add_property_json("Child Clip ID", 0.0, "string", ChildClipId(), NULL, -1, -1, false, 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/TrackedObjectBase.cpp b/src/TrackedObjectBase.cpp index 234104de..c1fde78f 100644 --- a/src/TrackedObjectBase.cpp +++ b/src/TrackedObjectBase.cpp @@ -41,11 +41,13 @@ namespace openshot{ { // Initializes the id as "None" id = "None"; + childClipId = "None"; } // Default constructor TrackedObjectBase::TrackedObjectBase(std::string _id) : visible(1.0) { Id(_id); + childClipId = "None"; } } \ No newline at end of file diff --git a/src/TrackedObjectBase.h b/src/TrackedObjectBase.h index 7d3ee870..49f84c94 100644 --- a/src/TrackedObjectBase.h +++ b/src/TrackedObjectBase.h @@ -57,8 +57,9 @@ namespace openshot { class TrackedObjectBase { private: std::string id; + std::string childClipId; + ClipBase* parentClip; - public: @@ -77,6 +78,9 @@ namespace openshot { /// Get and set the parentClip of this object ClipBase* ParentClip() const { return parentClip; } void ParentClip(ClipBase* clip) { parentClip = clip; } + /// Get and set the Id of the childClip of this object + std::string ChildClipId() const { return childClipId; }; + void ChildClipId(std::string _childClipId) { childClipId = _childClipId; }; /// Scale an object's property virtual void ScalePoints(double scale) { return; }; diff --git a/src/effects/Tracker.cpp b/src/effects/Tracker.cpp index fa9f1a0b..c46b2311 100644 --- a/src/effects/Tracker.cpp +++ b/src/effects/Tracker.cpp @@ -33,6 +33,10 @@ #include #include "Timeline.h" +#include +#include +#include + using namespace std; using namespace openshot; using google::protobuf::util::TimeUtil; @@ -92,6 +96,11 @@ std::shared_ptr Tracker::GetFrame(std::shared_ptr frame, int64_t f // Get the frame's image cv::Mat frame_image = frame->GetImageCV(); + // Initialize the Qt rectangle that will hold the positions of the bounding-box + QRectF boxRect; + // Initialize the image of the TrackedObject child clip + std::shared_ptr childClipImage = nullptr; + // Check if frame isn't NULL if(!frame_image.empty()) { @@ -117,6 +126,24 @@ std::shared_ptr Tracker::GetFrame(std::shared_ptr frame, int64_t f { cv::line(frame_image, vertices[i], vertices[(i+1)%4], cv::Scalar(255,0,0), 2); } + + // Get the image of the Tracked Object' child clip + if (trackedData->ChildClipId() != "None"){ + // Cast the parent timeline of this effect + Timeline* parentTimeline = (Timeline *) ParentTimeline(); + if (parentTimeline){ + // Get the Tracked Object's child clip + Clip* childClip = parentTimeline->GetClip(trackedData->ChildClipId()); + if (childClip){ + // Get the image of the child clip for this frame + std::shared_ptr childClipFrame = childClip->GetFrame(frame_number); + childClipImage = childClipFrame->GetImage(); + + // Set the Qt rectangle with the bounding-box properties + boxRect.setRect( (int)((fd.cx-fd.width/2)*fw), (int)((fd.cy - fd.height/2)*fh), (int)(fd.width*fw), (int)(fd.height*fh) ); + } + } + } } } @@ -124,6 +151,21 @@ std::shared_ptr Tracker::GetFrame(std::shared_ptr frame, int64_t f // If the input image is NULL or doesn't have tracking data, it's returned as it came frame->SetImageCV(frame_image); + // Set the bounding-box image with the Tracked Object's child clip image + if (childClipImage){ + // Get the frame image + QImage frameImage = *(frame->GetImage()); + + // Set a Qt painter to the frame image + QPainter painter(&frameImage); + + // Draw the child clip image inside the bounding-box + painter.drawImage(boxRect, *childClipImage, QRectF(0, 0, frameImage.size().width(), frameImage.size().height())); + + // Set the frame image as the composed image + frame->AddImage(std::make_shared(frameImage)); + } + return frame; } @@ -182,6 +224,7 @@ Json::Value Tracker::JsonValue() const { root["scale_y"] = trackedObjectJSON["scale_y"]; root["rotation"] = trackedObjectJSON["rotation"]; root["visible"] = trackedObjectJSON["visible"]; + root["child_clip_id"] = trackedObjectJSON["child_clip_id"]; } // return JsonValue @@ -258,6 +301,7 @@ void Tracker::SetJsonValue(const Json::Value root) { trackedObjectJSON["scale_y"] = root["scale_y"]; trackedObjectJSON["rotation"] = root["rotation"]; trackedObjectJSON["visible"] = root["visible"]; + trackedObjectJSON["child_clip_id"] = root["child_clip_id"]; if (!trackedObjectJSON.isNull()) trackedObject.second->SetJsonValue(trackedObjectJSON); } @@ -287,6 +331,7 @@ std::string Tracker::PropertiesJSON(int64_t requested_frame) const { root["scale_x"] = trackedObjectJSON["scale_x"]; root["scale_y"] = trackedObjectJSON["scale_y"]; root["rotation"] = trackedObjectJSON["rotation"]; + root["child_clip_id"] = trackedObjectJSON["child_clip_id"]; } // Append effect's properties