41#include <google/protobuf/util/time_util.h>
49using google::protobuf::util::TimeUtil;
52Tracker::Tracker(std::string clipTrackerDataPath)
55 init_effect_details();
58 trackedData = std::make_shared<TrackedObjectBBox>(trackedDataObject);
72 init_effect_details();
75 trackedData = std::make_shared<TrackedObjectBBox>(trackedDataObject);
85void Tracker::init_effect_details()
93 info.
description =
"Track the selected bounding box through the video.";
98 this->TimeScale = 1.0;
106 cv::Mat frame_image = frame->GetImageCV();
111 std::shared_ptr<QImage> childClipImage =
nullptr;
114 if(!frame_image.empty() &&
119 float fw = frame_image.size().width;
120 float fh = frame_image.size().height;
126 if (
trackedData->draw_box.GetValue(frame_number) == 1)
128 std::vector<int> stroke_rgba =
trackedData->stroke.GetColorRGBA(frame_number);
129 int stroke_width =
trackedData->stroke_width.GetValue(frame_number);
130 float stroke_alpha =
trackedData->stroke_alpha.GetValue(frame_number);
131 std::vector<int> bg_rgba =
trackedData->background.GetColorRGBA(frame_number);
132 float bg_alpha =
trackedData->background_alpha.GetValue(frame_number);
135 cv::RotatedRect box ( cv::Point2f( (
int)(fd.
cx*fw), (
int)(fd.
cy*fh) ),
136 cv::Size2f( (
int)(fd.
width*fw), (
int)(fd.
height*fh) ),
140 DrawRectangleRGBA(frame_image, box, stroke_rgba, stroke_alpha, stroke_width,
false);
152 std::shared_ptr<Frame> f(
new Frame(1, frame->GetWidth(), frame->GetHeight(),
"#00000000"));
153 std::shared_ptr<Frame> childClipFrame = childClip->
GetFrame(f, frame_number);
154 childClipImage = childClipFrame->GetImage();
157 boxRect.setRect((
int)((fd.
cx-fd.
width/2)*fw),
169 frame->SetImageCV(frame_image);
174 QImage frameImage = *(frame->GetImage());
177 QPainter painter(&frameImage);
180 painter.drawImage(boxRect, *childClipImage, QRectF(0, 0, frameImage.size().width(), frameImage.size().height()));
183 frame->AddImage(std::make_shared<QImage>(frameImage));
189void Tracker::DrawRectangleRGBA(cv::Mat &frame_image, cv::RotatedRect box, std::vector<int> color,
float alpha,
int thickness,
bool is_background){
191 cv::Point2f vertices2f[4];
192 box.points(vertices2f);
200 cv::Mat overlayFrame;
201 frame_image.copyTo(overlayFrame);
204 cv::Point vertices[4];
205 for(
int i = 0; i < 4; ++i){
206 vertices[i] = vertices2f[i];}
208 cv::Rect rect = box.boundingRect();
209 cv::fillConvexPoly(overlayFrame, vertices, 4, cv::Scalar(color[2],color[1],color[0]), cv::LINE_AA);
211 cv::addWeighted(overlayFrame, 1-alpha, frame_image, alpha, 0, frame_image);
214 cv::Mat overlayFrame;
215 frame_image.copyTo(overlayFrame);
218 for (
int i = 0; i < 4; i++)
220 cv::line(overlayFrame, vertices2f[i], vertices2f[(i+1)%4], cv::Scalar(color[2],color[1],color[0]),
221 thickness, cv::LINE_AA);
225 cv::addWeighted(overlayFrame, 1-alpha, frame_image, alpha, 0, frame_image);
234 root[
"visible_objects_index"] = Json::Value(Json::arrayValue);
235 root[
"visible_objects_id"] = Json::Value(Json::arrayValue);
240 Json::Value trackedObjectJSON = trackedObject.second->PropertiesJSON(frame_number);
241 if (trackedObjectJSON[
"visible"][
"value"].asBool()){
243 root[
"visible_objects_index"].append(trackedObject.first);
244 root[
"visible_objects_id"].append(trackedObject.second->Id());
248 return root.toStyledString();
267 root[
"BaseFPS"][
"num"] = BaseFPS.
num;
268 root[
"BaseFPS"][
"den"] = BaseFPS.
den;
269 root[
"TimeScale"] = this->TimeScale;
274 Json::Value trackedObjectJSON = trackedObject.second->JsonValue();
276 objects[trackedObject.second->Id()] = trackedObjectJSON;
278 root[
"objects"] = objects;
294 catch (
const std::exception& e)
297 throw InvalidJSON(
"JSON is invalid (missing keys or invalid data types)");
308 if(!root[
"type"].isNull())
311 if (!root[
"BaseFPS"].isNull() && root[
"BaseFPS"].isObject())
313 if (!root[
"BaseFPS"][
"num"].isNull())
315 BaseFPS.
num = (int) root[
"BaseFPS"][
"num"].asInt();
317 if (!root[
"BaseFPS"][
"den"].isNull())
319 BaseFPS.
den = (int) root[
"BaseFPS"][
"den"].asInt();
323 if (!root[
"TimeScale"].isNull())
324 TimeScale = (
double) root[
"TimeScale"].asDouble();
337 if (!root[
"objects"].isNull()){
339 std::string obj_id = std::to_string(trackedObject.first);
340 if(!root[
"objects"][obj_id].isNull()){
341 trackedObject.second->SetJsonValue(root[
"objects"][obj_id]);
347 if (!root[
"objects_id"].isNull()){
349 Json::Value trackedObjectJSON;
350 trackedObjectJSON[
"box_id"] = root[
"objects_id"][trackedObject.first].asString();
351 trackedObject.second->SetJsonValue(trackedObjectJSON);
367 Json::Value trackedObjectJSON = trackedObject.second->PropertiesJSON(requested_frame);
369 objects[trackedObject.second->Id()] = trackedObjectJSON;
371 root[
"objects"] = objects;
374 root[
"id"] =
add_property_json(
"ID", 0.0,
"string",
Id(), NULL, -1, -1,
true, requested_frame);
375 root[
"position"] =
add_property_json(
"Position",
Position(),
"float",
"", NULL, 0, 1000 * 60 * 30,
false, requested_frame);
377 root[
"start"] =
add_property_json(
"Start",
Start(),
"float",
"", NULL, 0, 1000 * 60 * 30,
false, requested_frame);
378 root[
"end"] =
add_property_json(
"End",
End(),
"float",
"", NULL, 0, 1000 * 60 * 30,
false, requested_frame);
379 root[
"duration"] =
add_property_json(
"Duration",
Duration(),
"float",
"", NULL, 0, 1000 * 60 * 30,
true, requested_frame);
382 return root.toStyledString();
Header file for all Exception classes.
Header file for Timeline class.
Header file for Tracker effect class.
This abstract class is the base class, used by all clips in libopenshot.
openshot::TimelineBase * ParentTimeline()
Get the associated Timeline pointer (if any)
float End() const
Get end position (in seconds) of clip (trim end of video)
float Start() const
Get start position (in seconds) of clip (trim start of video)
float Duration() const
Get the length of this clip (in seconds)
std::string Id() const
Get the Id of this clip object.
int Layer() const
Get layer of clip on timeline (lower number is covered by higher numbers)
float Position() const
Get position on timeline (in seconds)
Json::Value add_property_json(std::string name, float value, std::string type, std::string memo, const Keyframe *keyframe, float min_value, float max_value, bool readonly, int64_t requested_frame) const
Generate JSON for a property.
This class represents a clip (used to arrange readers on the timeline)
std::shared_ptr< openshot::Frame > GetFrame(int64_t frame_number) override
Get an openshot::Frame object for a specific frame number of this clip. The image size and number of ...
virtual Json::Value JsonValue() const
Generate Json::Value for this object.
openshot::ClipBase * ParentClip()
Parent clip object of this effect (which can be unparented and NULL)
virtual void SetJsonValue(const Json::Value root)
Load Json::Value into this object.
EffectInfoStruct info
Information about the current effect.
std::map< int, std::shared_ptr< openshot::TrackedObjectBase > > trackedObjects
Map of Tracked Object's by their indices (used by Effects that track objects on clips)
int num
Numerator for the fraction.
int den
Denominator for the fraction.
This class represents a single frame of video (i.e. image & audio data)
Exception for invalid JSON.
This class represents a timeline.
openshot::Clip * GetClip(const std::string &id)
Look up a single clip by ID.
This class contains the properties of a tracked object and functions to manipulate it.
std::string Json() const override
Generate JSON string of this object.
std::string GetVisibleObjects(int64_t frame_number) const override
Get the indexes and IDs of all visible objects in the given frame.
Json::Value JsonValue() const override
Generate Json::Value for this object.
void SetJson(const std::string value) override
Load JSON string into this object.
std::shared_ptr< Frame > GetFrame(std::shared_ptr< Frame > frame, int64_t frame_number) override
This method is required for all derived classes of EffectBase, and returns a modified openshot::Frame...
std::string PropertiesJSON(int64_t requested_frame) const override
std::shared_ptr< TrackedObjectBBox > trackedData
Pointer to an object that holds the bounding-box data and it's Keyframes.
void SetJsonValue(const Json::Value root) override
Load Json::Value into this object.
Tracker()
Default constructor.
void DrawRectangleRGBA(cv::Mat &frame_image, cv::RotatedRect box, std::vector< int > color, float alpha, int thickness, bool is_background)
std::string protobuf_data_path
Path to the protobuf file that holds the bounding-box data.
This namespace is the default namespace for all code in the openshot library.
const Json::Value stringToJson(const std::string value)
This struct holds the information of a bounding-box.
float cy
y-coordinate of the bounding box center
float height
bounding box height
float cx
x-coordinate of the bounding box center
float width
bounding box width
float angle
bounding box rotation angle [degrees]
bool has_video
Determines if this effect manipulates the image of a frame.
bool has_audio
Determines if this effect manipulates the audio of a frame.
std::string class_name
The class name of the effect.
std::string name
The name of the effect.
std::string description
The description of this effect and what it does.
bool has_tracked_object
Determines if this effect track objects through the clip.