From 5db1c0f4532eb42a8eb4044ef9e897748257465a Mon Sep 17 00:00:00 2001 From: Brenno Date: Thu, 29 Oct 2020 00:34:31 -0300 Subject: [PATCH 01/84] Initial design of new keyframes specialized classes The keyframe collections would better integrate with effects that uses bounding boxes, skeletons and facial points. --- src/CMakeLists.txt | 1 + src/IKeyFrame.h | 90 +++++++++++ src/KeyFrameBBox.cpp | 341 +++++++++++++++++++++++++++++++++++++++ src/KeyFrameBBox.h | 129 +++++++++++++++ src/OpenShot.h | 1 + tests/KeyFrame_Tests.cpp | 40 +++++ 6 files changed, 602 insertions(+) create mode 100644 src/IKeyFrame.h create mode 100644 src/KeyFrameBBox.cpp create mode 100644 src/KeyFrameBBox.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ac2c032f3..8144127a1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -86,6 +86,7 @@ set(OPENSHOT_SOURCES FrameMapper.cpp Json.cpp KeyFrame.cpp + KeyFrameBBox.cpp OpenShotVersion.cpp ZmqLogger.cpp PlayerBase.cpp diff --git a/src/IKeyFrame.h b/src/IKeyFrame.h new file mode 100644 index 000000000..3aef26cd1 --- /dev/null +++ b/src/IKeyFrame.h @@ -0,0 +1,90 @@ +/** + * @file + * @brief Header file for the IKeyframe class + * @author Jonathan Thomas + * + * @ref License + */ + +/* LICENSE + * + * Copyright (c) 2008-2019 OpenShot Studios, LLC + * . This file is part of + * OpenShot Library (libopenshot), an open-source project dedicated to + * delivering high quality video editing and animation solutions to the + * world. For more information visit . + * + * OpenShot Library (libopenshot) is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * OpenShot Library (libopenshot) is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OpenShot Library. If not, see . + */ + +#ifndef OPENSHOT_IKEYFRAME_H +#define OPENSHOT_IKEYFRAME_H + +#include +#include +#include +#include +#include +#include "Exceptions.h" +#include "Fraction.h" +#include "Coordinate.h" +#include "Point.h" +#include "Json.h" + + +namespace openshot { + /** + * @brief A Keyframe is a collection of Point instances, which is used to vary a number or property over time. + * + * Keyframes are used to animate and interpolate values of properties over time. For example, a single property + * can use a Keyframe instead of a constant value. Assume you want to slide an image (from left to right) over + * a video. You can create a Keyframe which will adjust the X value of the image over 100 frames (or however many + * frames the animation needs to last) from the value of 0 to 640. + * + * \endcode + */ + + class IKeyFrame { + public: + virtual void AddPoint(Point p) = 0; + virtual void AddPoint(double x, double y) = 0; + virtual bool Contains(Point p) const = 0; + virtual std::vector GetValue(int64_t frame_number) = 0; + virtual double GetDelta(int64_t index) const = 0; + virtual int64_t GetLength() const = 0; + virtual int64_t GetCount() const = 0; + + /// Get and Set JSON methods + virtual std::string Json() const = 0; ///< Generate JSON string of this object + virtual Json::Value JsonValue() const = 0; ///< Generate Json::Value for this object + virtual void SetJson(const std::string value) = 0; ///< Load JSON string into this object + virtual void SetJsonValue(const Json::Value root) = 0; ///< Load Json::Value into this object + + /// Remove a single point by matching a value + virtual void RemovePoint(Point p) = 0; + + /// Remove a points by frame_number + virtual void RemovePoint(int64_t frame_number) = 0; + + /// Replace an existing point with a new point + virtual void UpdatePoint(int64_t index, Point p) = 0; + + /// Print collection of points + virtual void PrintPoints() const = 0; + + }; + +} + +#endif \ No newline at end of file diff --git a/src/KeyFrameBBox.cpp b/src/KeyFrameBBox.cpp new file mode 100644 index 000000000..c0d3edcc5 --- /dev/null +++ b/src/KeyFrameBBox.cpp @@ -0,0 +1,341 @@ +/** + * @file + * @brief Source file for the Keyframe class + * @author Jonathan Thomas + * + * @ref License + */ + +/* LICENSE + * + * Copyright (c) 2008-2019 OpenShot Studios, LLC + * . This file is part of + * OpenShot Library (libopenshot), an open-source project dedicated to + * delivering high quality video editing and animation solutions to the + * world. For more information visit . + * + * OpenShot Library (libopenshot) is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * OpenShot Library (libopenshot) is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OpenShot Library. If not, see . + */ + +#include "KeyFrameBBox.h" +#include +#include +//#include "Point.h" +//#include + +using namespace std; +using namespace openshot; + +namespace { + bool IsPointBeforeX(Point const & p, double const x) { + return p.co.X < x; + } + + double InterpolateLinearCurve(Point const & left, Point const & right, double const target) { + double const diff_Y = right.co.Y - left.co.Y; + double const diff_X = right.co.X - left.co.X; + double const slope = diff_Y / diff_X; + return left.co.Y + slope * (target - left.co.X); + } + + double InterpolateBezierCurve(Point const & left, Point const & right, double const target, double const allowed_error) { + double const X_diff = right.co.X - left.co.X; + double const Y_diff = right.co.Y - left.co.Y; + Coordinate const p0 = left.co; + Coordinate const p1 = Coordinate(p0.X + left.handle_right.X * X_diff, p0.Y + left.handle_right.Y * Y_diff); + Coordinate const p2 = Coordinate(p0.X + right.handle_left.X * X_diff, p0.Y + right.handle_left.Y * Y_diff); + Coordinate const p3 = right.co; + + double t = 0.5; + double t_step = 0.25; + do { + // Bernstein polynoms + double B[4] = {1, 3, 3, 1}; + double oneMinTExp = 1; + double tExp = 1; + for (int i = 0; i < 4; ++i, tExp *= t) { + B[i] *= tExp; + } + for (int i = 0; i < 4; ++i, oneMinTExp *= 1 - t) { + B[4 - i - 1] *= oneMinTExp; + } + double const x = p0.X * B[0] + p1.X * B[1] + p2.X * B[2] + p3.X * B[3]; + double const y = p0.Y * B[0] + p1.Y * B[1] + p2.Y * B[2] + p3.Y * B[3]; + if (fabs(target - x) < allowed_error) { + return y; + } + if (x > target) { + t -= t_step; + } + else { + t += t_step; + } + t_step /= 2; + } while (true); + } + + + double InterpolateBetween(Point const & left, Point const & right, double target, double allowed_error) { + assert(left.co.X < target); + assert(target <= right.co.X); + switch (right.interpolation) { + case CONSTANT: return left.co.Y; + case LINEAR: return InterpolateLinearCurve(left, right, target); + case BEZIER: return InterpolateBezierCurve(left, right, target, allowed_error); + } + } + + + template + int64_t SearchBetweenPoints(Point const & left, Point const & right, int64_t const current, Check check) { + int64_t start = left.co.X; + int64_t stop = right.co.X; + while (start < stop) { + int64_t const mid = (start + stop + 1) / 2; + double const value = InterpolateBetween(left, right, mid, 0.01); + if (check(round(value), current)) { + start = mid; + } else { + stop = mid - 1; + } + } + return start; + } +} + + +KeyFrameBBox::KeyFrameBBox(): delta_x(0.0), delta_y(0.0), scale_x(0.0), scale_y(0.0) { + + return; +} + +void KeyFrameBBox::AddDisplacement(int64_t frame_num, double _delta_x, double _delta_y){ + if (!this->Contains((int64_t) frame_num)) + return; + + double time = this->FrameNToTime(frame_num); + + if (_delta_x != 0.0) + delta_x.AddPoint(time, _delta_x, openshot::InterpolationType::LINEAR); + if (_delta_y != 0.0) + delta_y.AddPoint(time, _delta_y, openshot::InterpolationType::LINEAR); + + return; +} + +void KeyFrameBBox::AddScale(int64_t frame_num, double _scale_x, double _scale_y){ + if (!this->Contains((double) frame_num)) + return; + + double time = this->FrameNToTime(frame_num); + + if (_scale_x != 0.0) + scale_x.AddPoint(time, _scale_x, openshot::InterpolationType::LINEAR); + if (_scale_y != 0.0) + scale_y.AddPoint(time, _scale_y, openshot::InterpolationType::LINEAR); + + return; +} + +void KeyFrameBBox::AddBox(int64_t _frame_num , float _cx, float _cy, float _width, float _height){ + + if (_frame_num < 0) + return; + + BBox box = BBox(_cx, _cy, _width, _height); + + double time = this->FrameNToTime(_frame_num); + + auto it = BoxVec.find(time); + if (it != BoxVec.end()) + it->second = box; + else + BoxVec.insert({time, box}); +} + +int64_t KeyFrameBBox::GetLength() const{ + + if (BoxVec.empty()) + return 0; + if (BoxVec.size() == 1) + return 1; + + return BoxVec.size(); +} + +bool KeyFrameBBox::Contains(int64_t frame_num) { + + double time = this->FrameNToTime(frame_num); + + auto it = BoxVec.find(time); + if (it != BoxVec.end()) + return true; + + return false; +} + +void KeyFrameBBox::RemovePoint(int64_t frame_number){ + + double time = this->FrameNToTime(frame_number); + + auto it = BoxVec.find(time); + if (it != BoxVec.end()){ + BoxVec.erase(frame_number); + + RemoveDelta(frame_number); + RemoveScale(frame_number); + } + return; +} + +void KeyFrameBBox::RemoveDelta(int64_t frame_number) { + + double attr_x = this->delta_x.GetValue(frame_number); + Point point_x = this->delta_x.GetClosestPoint(Point((double) frame_number, attr_x)); + if (point_x.co.X == (double) frame_number) + this->delta_x.RemovePoint(point_x); + + double attr_y = this->delta_y.GetValue(frame_number); + Point point_y = this->delta_y.GetClosestPoint(Point((double) frame_number, attr_y)); + if (point_y.co.X == (double) frame_number) + this->delta_y.RemovePoint(point_y); + + + return; +} + +void KeyFrameBBox::PrintParams() { + std::cout << "delta_x "; + this->delta_x.PrintPoints(); + + std::cout << "delta_y "; + this->delta_y.PrintPoints(); + + std::cout << "scale_x "; + this->scale_x.PrintPoints(); + + std::cout << "scale_y "; + this->scale_y.PrintPoints(); +} + + +void KeyFrameBBox::RemoveScale(int64_t frame_number) { + + double attr_x = this->scale_x.GetValue(frame_number); + Point point_x = this->scale_x.GetClosestPoint(Point((double) frame_number, attr_x)); + if (point_x.co.X == (double) frame_number) + this->scale_x.RemovePoint(point_x); + + double attr_y = this->scale_y.GetValue(frame_number); + Point point_y = this->scale_y.GetClosestPoint(Point((double) frame_number, attr_y)); + if (point_y.co.X == (double) frame_number) + this->scale_y.RemovePoint(point_y); + + + return; +} + +/*BBox KeyFrameBBox::GetValue(int64_t frame_number){ + + double time = this->FrameNToTime(frame_number); + + auto it = BoxVec.find(time); + if (it != BoxVec.end()){ + BBox res = it->second; + res.cx += this->delta_x.GetValue(time); + res.cy += this->delta_y.GetValue(time); + res.height += this->scale_y.GetValue(time); + res.width += this->scale_x.GetValue(time); + + return res; + } else { + + + } + + BBox val; + + return val; +}*/ +BBox KeyFrameBBox::GetValue(int64_t frame_number){ + double time = this->FrameNToTime(frame_number); + + auto it = BoxVec.lower_bound(time); + if (it->first == time){ + BBox res = it->second; + res.cx += this->delta_x.GetValue(time); + res.cy += this->delta_y.GetValue(time); + res.height += this->scale_y.GetValue(time); + res.width += this->scale_x.GetValue(time); + + return res; + } else { + BBox second_ref = it->second; + //advance(it, -1); + BBox first_ref = prev(it, 1)->second; + + BBox res = InterpolateBoxes(prev(it, 1)->first, it->first, first_ref, second_ref, time); + + res.cx += this->delta_x.GetValue(time); + res.cy += this->delta_y.GetValue(time); + res.height += this->scale_y.GetValue(time); + res.width += this->scale_x.GetValue(time); + + return res; + } + +} + +BBox KeyFrameBBox::InterpolateBoxes(double t1, double t2, BBox left, BBox right, double target){ + + Point p1_left(t1, left.cx, openshot::InterpolationType::LINEAR); + Point p1_right(t2, right.cx, openshot::InterpolationType::LINEAR); + + Point p1 = InterpolateBetween(p1_left, p1_right, target, 0.01); + + Point p2_left(t1, left.cy, openshot::InterpolationType::LINEAR); + Point p2_right(t2, right.cy, openshot::InterpolationType::LINEAR); + + Point p2 = InterpolateBetween(p2_left, p2_right, target, 0.01); + + Point p3_left(t1, left.height, openshot::InterpolationType::LINEAR); + Point p3_right(t2, right.height, openshot::InterpolationType::LINEAR); + + Point p3 = InterpolateBetween(p3_left, p3_right, target, 0.01); + + Point p4_left(t1, left.width, openshot::InterpolationType::LINEAR); + Point p4_right(t2, right.width, openshot::InterpolationType::LINEAR); + + Point p4 = InterpolateBetween(p4_left, p4_right, target, 0.01); + + BBox ans(p1.co.Y, p2.co.Y, p3.co.Y, p4.co.Y); + + return ans; +} + + +void KeyFrameBBox::SetFPS(Fraction fps){ + this->fps = fps; + return; +} + +Fraction KeyFrameBBox::GetFPS(){ + return fps; +} + +double KeyFrameBBox::FrameNToTime(int64_t frame_number){ + double time = ((double) frame_number) * this->fps.Reciprocal().ToDouble(); + + return time; +} diff --git a/src/KeyFrameBBox.h b/src/KeyFrameBBox.h new file mode 100644 index 000000000..9d3083183 --- /dev/null +++ b/src/KeyFrameBBox.h @@ -0,0 +1,129 @@ +/** + * @file + * @brief Header file for the IKeyframe class + * @author Jonathan Thomas + * + * @ref License + */ + + +/* LICENSE + * + * Copyright (c) 2008-2019 OpenShot Studios, LLC + * . This file is part of + * OpenShot Library (libopenshot), an open-source project dedicated to + * delivering high quality video editing and animation solutions to the + * world. For more information visit . + * + * OpenShot Library (libopenshot) is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * OpenShot Library (libopenshot) is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OpenShot Library. If not, see . + */ + +#ifndef OPENSHOT_BBOXKEYFRAME_H +#define OPENSHOT_BBOXKEYFRAME_H + +#include +#include +#include +#include +#include +#include "Exceptions.h" +#include "Fraction.h" +#include "Coordinate.h" +#include "Point.h" +#include "Json.h" +#include "IKeyFrame.h" +#include "KeyFrame.h" + + +struct BBox{ + float cx = -1; + float cy = -1; + float width = -1; + float height = -1; + + // Constructors + BBox(){ + return; + } + + BBox(float _cx, float _cy, float _width, float _height){ + //frame_num = _frame_num; + cx = _cx; + cy = _cy; + width = _width; + height = _height; + } +}; + + +namespace openshot { + /** + * @brief A Keyframe is a collection of Point instances, which is used to vary a number or property over time. + * + * Keyframes are used to animate and interpolate values of properties over time. For example, a single property + * can use a Keyframe instead of a constant value. Assume you want to slide an image (from left to right) over + * a video. You can create a Keyframe which will adjust the X value of the image over 100 frames (or however many + * frames the animation needs to last) from the value of 0 to 640. + * + * \endcode + */ + + class KeyFrameBBox { + private: + bool visible; + Fraction fps; + std::map BoxVec; + public: + Keyframe delta_x; + Keyframe delta_y; + Keyframe scale_x; + Keyframe scale_y; + + KeyFrameBBox(); + + void AddDisplacement(int64_t _frame_num, double _delta_x, double _delta_y); + void AddScale(int64_t _frame_num, double _delta_x, double _delta_y); + void AddBox(int64_t _frame_num, float _cx, float _cy, float _width, float _height); + + void SetFPS(Fraction fps); + Fraction GetFPS(); + + bool Contains(int64_t frame_number); + //double GetDelta(int64_t index) const ; + int64_t GetLength() const; + + /// Get and Set JSON methods + //std::string Json() const ; ///< Generate JSON string of this object + //Json::Value JsonValue() const ; ///< Generate Json::Value for this object + //void SetJson(const std::string value) ; ///< Load JSON string into this object + //void SetJsonValue(const Json::Value root) ; ///< Load Json::Value into this object + + /// Remove a points by frame_number + void RemovePoint(int64_t frame_number); + void RemoveDelta(int64_t frame_number); + void RemoveScale(int64_t frame_number); + + BBox GetValue(int64_t frame_number); + + /// Print collection of points + void PrintParams(); + + double FrameNToTime(int64_t frame_number); + BBox InterpolateBoxes(double t1, double t2, BBox left, BBox right, double target); + + }; + +} + +#endif \ No newline at end of file diff --git a/src/OpenShot.h b/src/OpenShot.h index e1209ac49..1cb8700a9 100644 --- a/src/OpenShot.h +++ b/src/OpenShot.h @@ -132,6 +132,7 @@ #include "TextReader.h" #endif #include "KeyFrame.h" +#include "KeyFrameBBox.h" #include "PlayerBase.h" #include "Point.h" #include "Profiles.h" diff --git a/tests/KeyFrame_Tests.cpp b/tests/KeyFrame_Tests.cpp index 840251654..b38eb8c9b 100644 --- a/tests/KeyFrame_Tests.cpp +++ b/tests/KeyFrame_Tests.cpp @@ -494,3 +494,43 @@ TEST(Keyframe_Handle_Large_Segment) Fraction fr = kf.GetRepeatFraction(250000); CHECK_CLOSE(0.5, (double)fr.num / fr.den, 0.01); } + + +TEST(KeyFrameBBox_init_test) { + + KeyFrameBBox kfb; + +} + +TEST(KeyFrameBBox_addBox_test) { + KeyFrameBBox kfb; + + kfb.AddBox(1, 10.0, 10.0, 100.0, 100.0); + + CHECK_EQUAL(true, kfb.Contains(1)); + CHECK_EQUAL(1, kfb.GetLength()); + + kfb.PrintParams(); + + kfb.RemovePoint(1); + + CHECK_EQUAL(false, kfb.Contains(1)); + CHECK_EQUAL(0, kfb.GetLength()); +} + + +TEST(KeyFrameBBox_GetVal_test) { + KeyFrameBBox kfb; + + kfb.AddBox(1, 10.0, 10.0, 100.0, 100.0); + + kfb.AddDisplacement(1, 20.0, 20.0); + kfb.AddScale(1, 30, 30); + + BBox val = kfb.GetValue(1); + + CHECK_EQUAL(30.0, val.cx); + CHECK_EQUAL(30.0, val.cy); + CHECK_EQUAL(130.0,val.width); + CHECK_EQUAL(130.0, val.height); +} \ No newline at end of file From 1215d042c7c741a49c85090bb1d827f11cc26be7 Mon Sep 17 00:00:00 2001 From: Brenno Date: Thu, 12 Nov 2020 21:25:27 -0300 Subject: [PATCH 02/84] Added scale factor to class to replace OpFPS. --- src/KeyFrameBBox.cpp | 253 ++++++++++++++++++++++++++++----------- src/KeyFrameBBox.h | 125 ++++++++++++++----- src/effects/Tracker.cpp | 56 +++++---- src/effects/Tracker.h | 8 +- tests/KeyFrame_Tests.cpp | 63 +++++++++- 5 files changed, 383 insertions(+), 122 deletions(-) diff --git a/src/KeyFrameBBox.cpp b/src/KeyFrameBBox.cpp index c0d3edcc5..7bb0bebb4 100644 --- a/src/KeyFrameBBox.cpp +++ b/src/KeyFrameBBox.cpp @@ -115,8 +115,8 @@ namespace { } -KeyFrameBBox::KeyFrameBBox(): delta_x(0.0), delta_y(0.0), scale_x(0.0), scale_y(0.0) { - +KeyFrameBBox::KeyFrameBBox(): delta_x(0.0), delta_y(0.0), scale_x(0.0), scale_y(0.0), rotation(0.0) { + this->TimeScale = 1.0; return; } @@ -124,7 +124,7 @@ void KeyFrameBBox::AddDisplacement(int64_t frame_num, double _delta_x, double _d if (!this->Contains((int64_t) frame_num)) return; - double time = this->FrameNToTime(frame_num); + double time = this->FrameNToTime(frame_num, 1.0); if (_delta_x != 0.0) delta_x.AddPoint(time, _delta_x, openshot::InterpolationType::LINEAR); @@ -138,7 +138,7 @@ void KeyFrameBBox::AddScale(int64_t frame_num, double _scale_x, double _scale_y) if (!this->Contains((double) frame_num)) return; - double time = this->FrameNToTime(frame_num); + double time = this->FrameNToTime(frame_num, 1.0); if (_scale_x != 0.0) scale_x.AddPoint(time, _scale_x, openshot::InterpolationType::LINEAR); @@ -148,6 +148,15 @@ void KeyFrameBBox::AddScale(int64_t frame_num, double _scale_x, double _scale_y) return; } +void KeyFrameBBox::AddRotation(int64_t _frame_num, double rot){ + if (!this->Contains((double) _frame_num)) + return; + + double time = this->FrameNToTime(_frame_num, 1.0); + + rotation.AddPoint(time, rot, openshot::InterpolationType::LINEAR); +} + void KeyFrameBBox::AddBox(int64_t _frame_num , float _cx, float _cy, float _width, float _height){ if (_frame_num < 0) @@ -155,7 +164,7 @@ void KeyFrameBBox::AddBox(int64_t _frame_num , float _cx, float _cy, float _widt BBox box = BBox(_cx, _cy, _width, _height); - double time = this->FrameNToTime(_frame_num); + double time = this->FrameNToTime(_frame_num, 1.0); auto it = BoxVec.find(time); if (it != BoxVec.end()) @@ -176,45 +185,61 @@ int64_t KeyFrameBBox::GetLength() const{ bool KeyFrameBBox::Contains(int64_t frame_num) { - double time = this->FrameNToTime(frame_num); + double time = this->FrameNToTime(frame_num, 1.0); - auto it = BoxVec.find(time); - if (it != BoxVec.end()) - return true; - - return false; + auto it = BoxVec.lower_bound(time); + if (it == BoxVec.end()) + return false; + + return true; } void KeyFrameBBox::RemovePoint(int64_t frame_number){ - double time = this->FrameNToTime(frame_number); + double time = this->FrameNToTime(frame_number, 1.0); auto it = BoxVec.find(time); if (it != BoxVec.end()){ - BoxVec.erase(frame_number); + BoxVec.erase(time); - RemoveDelta(frame_number); - RemoveScale(frame_number); + RemoveDelta(time); + RemoveScale(time); } return; } void KeyFrameBBox::RemoveDelta(int64_t frame_number) { - double attr_x = this->delta_x.GetValue(frame_number); - Point point_x = this->delta_x.GetClosestPoint(Point((double) frame_number, attr_x)); - if (point_x.co.X == (double) frame_number) + double time = this->FrameNToTime(frame_number, 1.0); + + double attr_x = this->delta_x.GetValue(time); + Point point_x = this->delta_x.GetClosestPoint(Point((double) time, attr_x)); + if (point_x.co.X == (double) time) this->delta_x.RemovePoint(point_x); - double attr_y = this->delta_y.GetValue(frame_number); - Point point_y = this->delta_y.GetClosestPoint(Point((double) frame_number, attr_y)); - if (point_y.co.X == (double) frame_number) + double attr_y = this->delta_y.GetValue(time); + Point point_y = this->delta_y.GetClosestPoint(Point((double) time, attr_y)); + if (point_y.co.X == (double) time) this->delta_y.RemovePoint(point_y); return; } +void KeyFrameBBox::RemoveRotation(int64_t frame_number) { + + double time = this->FrameNToTime(frame_number, 1.0); + + double rot = this->rotation.GetValue(time); + Point point_rot = this->rotation.GetClosestPoint(Point((double) time, rot)); + if (point_rot.co.X == (double) time) + this->rotation.RemovePoint(point_rot); + + return; +} + + + void KeyFrameBBox::PrintParams() { std::cout << "delta_x "; this->delta_x.PrintPoints(); @@ -227,51 +252,40 @@ void KeyFrameBBox::PrintParams() { std::cout << "scale_y "; this->scale_y.PrintPoints(); + + std::cout << "rotation "; + this->rotation.PrintPoints(); + } void KeyFrameBBox::RemoveScale(int64_t frame_number) { - double attr_x = this->scale_x.GetValue(frame_number); - Point point_x = this->scale_x.GetClosestPoint(Point((double) frame_number, attr_x)); - if (point_x.co.X == (double) frame_number) + double time = this->FrameNToTime(frame_number, 1.0); + + double attr_x = this->scale_x.GetValue(time); + Point point_x = this->scale_x.GetClosestPoint(Point((double) time, attr_x)); + if (point_x.co.X == (double) time) this->scale_x.RemovePoint(point_x); - double attr_y = this->scale_y.GetValue(frame_number); - Point point_y = this->scale_y.GetClosestPoint(Point((double) frame_number, attr_y)); - if (point_y.co.X == (double) frame_number) + double attr_y = this->scale_y.GetValue(time); + Point point_y = this->scale_y.GetClosestPoint(Point((double) time, attr_y)); + if (point_y.co.X == (double) time) this->scale_y.RemovePoint(point_y); return; } -/*BBox KeyFrameBBox::GetValue(int64_t frame_number){ - - double time = this->FrameNToTime(frame_number); - - auto it = BoxVec.find(time); - if (it != BoxVec.end()){ - BBox res = it->second; - res.cx += this->delta_x.GetValue(time); - res.cy += this->delta_y.GetValue(time); - res.height += this->scale_y.GetValue(time); - res.width += this->scale_x.GetValue(time); - - return res; - } else { - - - } - - BBox val; - - return val; -}*/ BBox KeyFrameBBox::GetValue(int64_t frame_number){ - double time = this->FrameNToTime(frame_number); + double time = this->FrameNToTime(frame_number, this->TimeScale); auto it = BoxVec.lower_bound(time); + if (it == BoxVec.end()){ + BBox resp; + return resp; + } + if (it->first == time){ BBox res = it->second; res.cx += this->delta_x.GetValue(time); @@ -280,20 +294,22 @@ BBox KeyFrameBBox::GetValue(int64_t frame_number){ res.width += this->scale_x.GetValue(time); return res; - } else { - BBox second_ref = it->second; - //advance(it, -1); - BBox first_ref = prev(it, 1)->second; + } + + BBox second_ref = it->second; + BBox first_ref = prev(it, 1)->second; - BBox res = InterpolateBoxes(prev(it, 1)->first, it->first, first_ref, second_ref, time); + BBox res = InterpolateBoxes(prev(it, 1)->first, it->first, first_ref, second_ref, time); - res.cx += this->delta_x.GetValue(time); - res.cy += this->delta_y.GetValue(time); - res.height += this->scale_y.GetValue(time); - res.width += this->scale_x.GetValue(time); + /*later add rotation transform to these points*/ + + res.cx += this->delta_x.GetValue(time); + res.cy += this->delta_y.GetValue(time); + res.height += this->scale_y.GetValue(time); + res.width += this->scale_x.GetValue(time); - return res; - } + return res; + } @@ -325,17 +341,120 @@ BBox KeyFrameBBox::InterpolateBoxes(double t1, double t2, BBox left, BBox right, } -void KeyFrameBBox::SetFPS(Fraction fps){ - this->fps = fps; +void KeyFrameBBox::SetBaseFPS(Fraction fps){ + this->BaseFps = fps; return; } -Fraction KeyFrameBBox::GetFPS(){ - return fps; +Fraction KeyFrameBBox::GetBaseFPS(){ + return BaseFps; } -double KeyFrameBBox::FrameNToTime(int64_t frame_number){ - double time = ((double) frame_number) * this->fps.Reciprocal().ToDouble(); +double KeyFrameBBox::FrameNToTime(int64_t frame_number, double time_scale){ + double time = ((double) frame_number) * this->BaseFps.Reciprocal().ToDouble() * time_scale; return time; } + +void KeyFrameBBox::ScalePoints(double time_scale){ + this->TimeScale = time_scale; +} + + +// Generate JSON string of this object +std::string KeyFrameBBox::Json() { + + // Return formatted string + return JsonValue().toStyledString(); +} + +// Generate Json::Value for this object +Json::Value KeyFrameBBox::JsonValue() { + + // Create root json object + Json::Value root; + //root["Points"] = Json::Value(Json::arrayValue); + + root["BaseFPS"]["num"] = BaseFps.num; + root["BaseFPS"]["den"] = BaseFps.den; + root["TimeScale"] = this->TimeScale; + root["boxes"] = Json::Value(Json::arrayValue); + + // loop through points + for (auto const& x : BoxVec){ + Json::Value elem; + elem["key"] = x.first; + elem["val"] = x.second.JsonValue(); + root["boxes"].append(elem); + } + + + root["delta_x"] = delta_x.JsonValue(); + root["delta_y"] = delta_y.JsonValue(); + root["scale_x"] = scale_x.JsonValue(); + root["scale_y"] = scale_y.JsonValue(); + root["rotation"] = rotation.JsonValue(); + + // return JsonValue + return root; +} + +// Load JSON string into this object +void KeyFrameBBox::SetJson(const std::string value) { + + // Parse JSON string into JSON objects + try + { + const Json::Value root = openshot::stringToJson(value); + // Set all values that match + SetJsonValue(root); + } + catch (const std::exception& e) + { + // Error parsing JSON (or missing keys) + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); + } + + return; +} + +void KeyFrameBBox::clear(){ + BoxVec.clear(); +} + + + +// Load Json::Value into this object +void KeyFrameBBox::SetJsonValue(const Json::Value root) { + // Clear existing points + BoxVec.clear(); + + delta_x.SetJsonValue(root["delta_x"]); + delta_y.SetJsonValue(root["delta_y"]); + scale_x.SetJsonValue(root["scale_x"]); + scale_y.SetJsonValue(root["scale_y"]); + rotation.SetJsonValue(root["rotation"]); + + + if (!root["BaseFPS"].isNull() && root["BaseFPS"].isObject()) { + if (!root["BaseFPS"]["num"].isNull()) + BaseFps.num = (int) root["BaseFPS"]["num"].asInt(); + if (!root["BaseFPS"]["den"].isNull()) + BaseFps.den = (int) root["BaseFPS"]["den"].asInt(); + } + if (!root["TimeScale"].isNull()) { + this->TimeScale = (double) root["TimeScale"].asDouble(); + } + + if (!root["boxes"].isNull()){ + // loop through points + for (const auto existing_point : root["boxes"]) { + // Create Point + BBox box; + box.SetJsonValue(existing_point["val"]); + + BoxVec.insert({existing_point["key"].asDouble(), box}); + } + } + return; +} \ No newline at end of file diff --git a/src/KeyFrameBBox.h b/src/KeyFrameBBox.h index 9d3083183..a80c7d7d7 100644 --- a/src/KeyFrameBBox.h +++ b/src/KeyFrameBBox.h @@ -46,26 +46,6 @@ #include "KeyFrame.h" -struct BBox{ - float cx = -1; - float cy = -1; - float width = -1; - float height = -1; - - // Constructors - BBox(){ - return; - } - - BBox(float _cx, float _cy, float _width, float _height){ - //frame_num = _frame_num; - cx = _cx; - cy = _cy; - width = _width; - height = _height; - } -}; - namespace openshot { /** @@ -79,49 +59,130 @@ namespace openshot { * \endcode */ + + + struct BBox{ + float cx = -1; + float cy = -1; + float width = -1; + float height = -1; + + // Constructors + BBox(){ + return; + } + + BBox(float _cx, float _cy, float _width, float _height){ + //frame_num = _frame_num; + cx = _cx; + cy = _cy; + width = _width; + height = _height; + } + + std::string Json() const { + // Return formatted string + return JsonValue().toStyledString(); + } + + // Generate Json::Value for this object + Json::Value JsonValue() const { + + // Create root json object + Json::Value root; + root["cx"] = cx; + root["cy"] = cy; + root["height"] = height; + root["width"] = width; + + return root; + } + + // Load JSON string into this object + void SetJson(const std::string value) { + + // Parse JSON string into JSON objects + try + { + const Json::Value root = openshot::stringToJson(value); + // Set all values that match + SetJsonValue(root); + } + catch (const std::exception& e) + { + // Error parsing JSON (or missing keys) + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); + } + } + + // Load Json::Value into this object + void SetJsonValue(const Json::Value root) { + + // Set data from Json (if key is found) + if (!root["cx"].isNull()) + cx = root["cx"].asDouble(); + if (!root["cy"].isNull()) + cy = root["cy"].asDouble(); + if (!root["height"].isNull()) + height = root["height"].asDouble(); + if (!root["width"].isNull()) + width = root["width"].asDouble(); + } + }; + + class KeyFrameBBox { private: bool visible; - Fraction fps; + Fraction BaseFps; + double TimeScale; std::map BoxVec; public: Keyframe delta_x; Keyframe delta_y; Keyframe scale_x; Keyframe scale_y; - + Keyframe rotation; + KeyFrameBBox(); void AddDisplacement(int64_t _frame_num, double _delta_x, double _delta_y); void AddScale(int64_t _frame_num, double _delta_x, double _delta_y); void AddBox(int64_t _frame_num, float _cx, float _cy, float _width, float _height); - - void SetFPS(Fraction fps); - Fraction GetFPS(); + void AddRotation(int64_t _frame_num, double rot); + + void SetBaseFPS(Fraction fps); + Fraction GetBaseFPS(); + + void ScalePoints(double scale); bool Contains(int64_t frame_number); //double GetDelta(int64_t index) const ; int64_t GetLength() const; - - /// Get and Set JSON methods - //std::string Json() const ; ///< Generate JSON string of this object - //Json::Value JsonValue() const ; ///< Generate Json::Value for this object - //void SetJson(const std::string value) ; ///< Load JSON string into this object - //void SetJsonValue(const Json::Value root) ; ///< Load Json::Value into this object /// Remove a points by frame_number void RemovePoint(int64_t frame_number); void RemoveDelta(int64_t frame_number); void RemoveScale(int64_t frame_number); + void RemoveRotation(int64_t frame_number); BBox GetValue(int64_t frame_number); /// Print collection of points void PrintParams(); - double FrameNToTime(int64_t frame_number); + double FrameNToTime(int64_t frame_number, double time_scale); BBox InterpolateBoxes(double t1, double t2, BBox left, BBox right, double target); + /// Get and Set JSON methods + std::string Json(); ///< Generate JSON string of this object + Json::Value JsonValue(); ///< Generate Json::Value for this object + void SetJson(const std::string value); ///< Load JSON string into this object + void SetJsonValue(const Json::Value root); ///< Load Json::Value into this object + + void clear(); //clear all fields + + }; } diff --git a/src/effects/Tracker.cpp b/src/effects/Tracker.cpp index 78fd3e079..5205a7460 100644 --- a/src/effects/Tracker.cpp +++ b/src/effects/Tracker.cpp @@ -37,7 +37,10 @@ Tracker::Tracker(std::string clipTrackerDataPath) { // Init effect properties init_effect_details(); - +/* + this->trackedData.SetBaseFPS(fps); + this->trackedData.SetOpFPS(fps); +*/ // Tries to load the tracker data from protobuf LoadTrackedData(clipTrackerDataPath); } @@ -47,7 +50,10 @@ Tracker::Tracker() { // Init effect properties init_effect_details(); - +/* + this->trackedData.SetBaseFPS(fps); + this->trackedData.SetOpFPS(fps); +*/ } // Init effect settings @@ -62,6 +68,7 @@ void Tracker::init_effect_details() info.description = "Track the selected bounding box through the video."; info.has_audio = false; info.has_video = true; + } // This method is required for all derived classes of EffectBase, and returns a @@ -76,17 +83,20 @@ std::shared_ptr Tracker::GetFrame(std::shared_ptr frame, int64_t f if(!frame_image.empty()){ // Check if track data exists for the requested frame - if (trackedDataById.find(frame_number) != trackedDataById.end()) { + if (trackedData.Contains(frame_number)) { float fw = frame_image.size().width; float fh = frame_image.size().height; // Draw box on image - EffectFrameData fd = trackedDataById[frame_number]; - cv::Rect2d box((int)(fd.x1*fw), - (int)(fd.y1*fh), - (int)((fd.x2-fd.x1)*fw), - (int)((fd.y2-fd.y1)*fh)); + //EffectFrameData fd = trackedDataById[frame_number]; + + BBox fd = this->trackedData.GetValue(frame_number); + + cv::Rect2d box((int)(fd.cx*fw), + (int)(fd.cy*fh), + (int)(fd.width*fw), + (int)(fd.height*fh)); cv::rectangle(frame_image, box, cv::Scalar( 255, 0, 0 ), 2, 1 ); } } @@ -113,7 +123,9 @@ bool Tracker::LoadTrackedData(std::string inputFilePath){ } // Make sure the trackedData is empty - trackedDataById.clear(); + //trackedDataById.clear(); + trackedData.clear(); + // Iterate over all frames of the saved message for (size_t i = 0; i < trackerMessage.frame_size(); i++) { @@ -131,8 +143,10 @@ bool Tracker::LoadTrackedData(std::string inputFilePath){ float y2 = box.y2(); // Assign data to tracker map - trackedDataById[id] = EffectFrameData(id, rotation, x1, y1, x2, y2); - } + //trackedDataById[id] = EffectFrameData(id, rotation, x1, y1, x2, y2); + trackedData.AddBox(id, x1, y1, (x2-x1), (y2-y1)); + trackedData.AddRotation(id, rotation); + } // Show the time stamp from the last update in tracker data file if (trackerMessage.has_last_updated()) { @@ -146,15 +160,8 @@ bool Tracker::LoadTrackedData(std::string inputFilePath){ } // Get tracker info for the desired frame -EffectFrameData Tracker::GetTrackedData(size_t frameId){ - - // Check if the tracker info for the requested frame exists - if ( trackedDataById.find(frameId) == trackedDataById.end() ) { - return EffectFrameData(); - } else { - return trackedDataById[frameId]; - } - +BBox Tracker::GetTrackedData(size_t frameId){ + return this->trackedData.GetValue(frameId); } // Generate JSON string of this object @@ -171,6 +178,8 @@ Json::Value Tracker::JsonValue() const { Json::Value root = EffectBase::JsonValue(); // get parent properties root["type"] = info.class_name; root["protobuf_data_path"] = protobuf_data_path; + root["BaseFPS"]["num"] = BaseFPS.num; + root["BaseFPS"]["den"] = BaseFPS.den; // return JsonValue return root; @@ -207,6 +216,13 @@ void Tracker::SetJsonValue(const Json::Value root) { protobuf_data_path = ""; } } + + if (!root["BaseFPS"].isNull() && root["BaseFPS"].isObject()) { + if (!root["BaseFPS"]["num"].isNull()) + BaseFPS.num = (int) root["BaseFPS"]["num"].asInt(); + if (!root["BaseFPS"]["den"].isNull()) + BaseFPS.den = (int) root["BaseFPS"]["den"].asInt(); + } } // Get all properties for a specific frame diff --git a/src/effects/Tracker.h b/src/effects/Tracker.h index abc816e15..3350428ae 100644 --- a/src/effects/Tracker.h +++ b/src/effects/Tracker.h @@ -42,6 +42,8 @@ #include "../Color.h" #include "../Json.h" #include "../KeyFrame.h" +#include "../KeyFrameBBox.h" +#include "../Clip.h" #include "trackerdata.pb.h" using namespace std; @@ -89,11 +91,13 @@ namespace openshot /// Init effect settings void init_effect_details(); std::string protobuf_data_path; - + Fraction BaseFPS; public: std::map trackedDataById; // Save object tracking box data + KeyFrameBBox trackedData; + /// Blank constructor, useful when using Json to load the effect properties Tracker(std::string clipTrackerDataPath); @@ -116,7 +120,7 @@ namespace openshot bool LoadTrackedData(std::string inputFilePath); // Get tracker info for the desired frame - EffectFrameData GetTrackedData(size_t frameId); + BBox GetTrackedData(size_t frameId); /// Get and Set JSON methods std::string Json() const override; ///< Generate JSON string of this object diff --git a/tests/KeyFrame_Tests.cpp b/tests/KeyFrame_Tests.cpp index b38eb8c9b..13a4c68f7 100644 --- a/tests/KeyFrame_Tests.cpp +++ b/tests/KeyFrame_Tests.cpp @@ -533,4 +533,65 @@ TEST(KeyFrameBBox_GetVal_test) { CHECK_EQUAL(30.0, val.cy); CHECK_EQUAL(130.0,val.width); CHECK_EQUAL(130.0, val.height); -} \ No newline at end of file +} + + +TEST(KeyFrameBBox_GetVal_Interpolation) { + KeyFrameBBox kfb; + + kfb.AddBox(1, 10.0, 10.0, 100.0, 100.0); + kfb.AddBox(11, 20.0, 20.0, 100.0, 100.0); + kfb.AddBox(21, 30.0, 30.0, 100.0, 100.0); + kfb.AddBox(31, 40.0, 40.0, 100.0, 100.0); + + + //kfb.AddDisplacement(1, 20.0, 20.0); + //kfb.AddScale(1, 30, 30); + + BBox val = kfb.GetValue(5); + + CHECK_EQUAL(14.0, val.cx); + CHECK_EQUAL(14.0, val.cy); + CHECK_EQUAL(100.0,val.width); + CHECK_EQUAL(100.0, val.height); + + val = kfb.GetValue(15); + + CHECK_EQUAL(24.0, val.cx); + CHECK_EQUAL(24.0, val.cy); + CHECK_EQUAL(100.0,val.width); + CHECK_EQUAL(100.0, val.height); + + val = kfb.GetValue(25); + + CHECK_EQUAL(34.0, val.cx); + CHECK_EQUAL(34.0, val.cy); + CHECK_EQUAL(100.0,val.width); + CHECK_EQUAL(100.0, val.height); + +} + + +TEST(KeyFrameBBox_Json_set) { + KeyFrameBBox kfb; + + kfb.AddBox(0, 10.0, 10.0, 100.0, 100.0); + kfb.AddBox(10, 20.0, 20.0, 100.0, 100.0); + kfb.AddBox(20, 30.0, 30.0, 100.0, 100.0); + kfb.AddBox(30, 40.0, 40.0, 100.0, 100.0); + + kfb.SetBaseFPS(Fraction(24.0, 1.0)); + kfb.ScalePoints(1.2); + auto data = kfb.Json(); + + KeyFrameBBox from_json; + from_json.SetJson(data); + + BBox val = kfb.GetValue(0); + BBox val_json = from_json.GetValue(0); + + std::cout << from_json.Json() << std::endl; + + CHECK_EQUAL(val.cx, val_json.cx); +} + From 34aabcc6e22a5214a146b244326ccacc49c43e2f Mon Sep 17 00:00:00 2001 From: Brenno Date: Thu, 12 Nov 2020 21:30:11 -0300 Subject: [PATCH 03/84] Removed Excess information from json. --- src/KeyFrameBBox.cpp | 7 ++++--- src/effects/Tracker.cpp | 17 ++++++++++------- tests/KeyFrame_Tests.cpp | 5 +---- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/KeyFrameBBox.cpp b/src/KeyFrameBBox.cpp index 7bb0bebb4..98307a890 100644 --- a/src/KeyFrameBBox.cpp +++ b/src/KeyFrameBBox.cpp @@ -381,13 +381,13 @@ Json::Value KeyFrameBBox::JsonValue() { root["boxes"] = Json::Value(Json::arrayValue); // loop through points - for (auto const& x : BoxVec){ + /*for (auto const& x : BoxVec){ Json::Value elem; elem["key"] = x.first; elem["val"] = x.second.JsonValue(); root["boxes"].append(elem); } - + */ root["delta_x"] = delta_x.JsonValue(); root["delta_y"] = delta_y.JsonValue(); @@ -445,7 +445,7 @@ void KeyFrameBBox::SetJsonValue(const Json::Value root) { if (!root["TimeScale"].isNull()) { this->TimeScale = (double) root["TimeScale"].asDouble(); } - + /* if (!root["boxes"].isNull()){ // loop through points for (const auto existing_point : root["boxes"]) { @@ -456,5 +456,6 @@ void KeyFrameBBox::SetJsonValue(const Json::Value root) { BoxVec.insert({existing_point["key"].asDouble(), box}); } } + */ return; } \ No newline at end of file diff --git a/src/effects/Tracker.cpp b/src/effects/Tracker.cpp index 5205a7460..423328b39 100644 --- a/src/effects/Tracker.cpp +++ b/src/effects/Tracker.cpp @@ -207,6 +207,16 @@ void Tracker::SetJsonValue(const Json::Value root) { // Set parent data EffectBase::SetJsonValue(root); + + if (!root["BaseFPS"].isNull() && root["BaseFPS"].isObject()) { + if (!root["BaseFPS"]["num"].isNull()) + BaseFPS.num = (int) root["BaseFPS"]["num"].asInt(); + if (!root["BaseFPS"]["den"].isNull()) + BaseFPS.den = (int) root["BaseFPS"]["den"].asInt(); + } + + trackedData.SetBaseFPS(this->BaseFPS); + // Set data from Json (if key is found) if (!root["protobuf_data_path"].isNull()){ protobuf_data_path = (root["protobuf_data_path"].asString()); @@ -216,13 +226,6 @@ void Tracker::SetJsonValue(const Json::Value root) { protobuf_data_path = ""; } } - - if (!root["BaseFPS"].isNull() && root["BaseFPS"].isObject()) { - if (!root["BaseFPS"]["num"].isNull()) - BaseFPS.num = (int) root["BaseFPS"]["num"].asInt(); - if (!root["BaseFPS"]["den"].isNull()) - BaseFPS.den = (int) root["BaseFPS"]["den"].asInt(); - } } // Get all properties for a specific frame diff --git a/tests/KeyFrame_Tests.cpp b/tests/KeyFrame_Tests.cpp index 13a4c68f7..dcdab721e 100644 --- a/tests/KeyFrame_Tests.cpp +++ b/tests/KeyFrame_Tests.cpp @@ -587,11 +587,8 @@ TEST(KeyFrameBBox_Json_set) { KeyFrameBBox from_json; from_json.SetJson(data); - BBox val = kfb.GetValue(0); - BBox val_json = from_json.GetValue(0); - std::cout << from_json.Json() << std::endl; - CHECK_EQUAL(val.cx, val_json.cx); + CHECK_EQUAL(kfb.GetBaseFPS().num, from_json.GetBaseFPS().num); } From 940840c9047c11a4df2c2934295e7b8a8ab87933 Mon Sep 17 00:00:00 2001 From: Brenno Date: Thu, 12 Nov 2020 21:33:53 -0300 Subject: [PATCH 04/84] Solved FPS bug. --- src/KeyFrameBBox.cpp | 31 ++++++++++++++++--------------- src/effects/Tracker.cpp | 16 ++++++++++++---- src/effects/Tracker.h | 1 + 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/src/KeyFrameBBox.cpp b/src/KeyFrameBBox.cpp index 98307a890..ddb5c3fc5 100644 --- a/src/KeyFrameBBox.cpp +++ b/src/KeyFrameBBox.cpp @@ -279,19 +279,19 @@ void KeyFrameBBox::RemoveScale(int64_t frame_number) { BBox KeyFrameBBox::GetValue(int64_t frame_number){ double time = this->FrameNToTime(frame_number, this->TimeScale); - auto it = BoxVec.lower_bound(time); + if (it == BoxVec.end()){ BBox resp; return resp; } - if (it->first == time){ + if ((it->first == time) || (it == BoxVec.begin())){ BBox res = it->second; - res.cx += this->delta_x.GetValue(time); - res.cy += this->delta_y.GetValue(time); - res.height += this->scale_y.GetValue(time); - res.width += this->scale_x.GetValue(time); + res.cx += this->delta_x.GetValue(it->first); + res.cy += this->delta_y.GetValue(it->first); + res.height += this->scale_y.GetValue(it->first); + res.width += this->scale_x.GetValue(it->first); return res; } @@ -324,7 +324,7 @@ BBox KeyFrameBBox::InterpolateBoxes(double t1, double t2, BBox left, BBox right, Point p2_right(t2, right.cy, openshot::InterpolationType::LINEAR); Point p2 = InterpolateBetween(p2_left, p2_right, target, 0.01); - + Point p3_left(t1, left.height, openshot::InterpolationType::LINEAR); Point p3_right(t2, right.height, openshot::InterpolationType::LINEAR); @@ -334,8 +334,8 @@ BBox KeyFrameBBox::InterpolateBoxes(double t1, double t2, BBox left, BBox right, Point p4_right(t2, right.width, openshot::InterpolationType::LINEAR); Point p4 = InterpolateBetween(p4_left, p4_right, target, 0.01); - - BBox ans(p1.co.Y, p2.co.Y, p3.co.Y, p4.co.Y); + + BBox ans(p1.co.Y, p2.co.Y, p4.co.Y, p3.co.Y); return ans; } @@ -351,7 +351,7 @@ Fraction KeyFrameBBox::GetBaseFPS(){ } double KeyFrameBBox::FrameNToTime(int64_t frame_number, double time_scale){ - double time = ((double) frame_number) * this->BaseFps.Reciprocal().ToDouble() * time_scale; + double time = ((double) frame_number) * this->BaseFps.Reciprocal().ToDouble() * (1.0 / time_scale); return time; } @@ -381,13 +381,13 @@ Json::Value KeyFrameBBox::JsonValue() { root["boxes"] = Json::Value(Json::arrayValue); // loop through points - /*for (auto const& x : BoxVec){ + for (auto const& x : BoxVec){ Json::Value elem; elem["key"] = x.first; elem["val"] = x.second.JsonValue(); root["boxes"].append(elem); } - */ + root["delta_x"] = delta_x.JsonValue(); root["delta_y"] = delta_y.JsonValue(); @@ -443,9 +443,10 @@ void KeyFrameBBox::SetJsonValue(const Json::Value root) { BaseFps.den = (int) root["BaseFPS"]["den"].asInt(); } if (!root["TimeScale"].isNull()) { - this->TimeScale = (double) root["TimeScale"].asDouble(); + double scale = (double) root["TimeScale"].asDouble(); + this->ScalePoints(scale); } - /* + if (!root["boxes"].isNull()){ // loop through points for (const auto existing_point : root["boxes"]) { @@ -456,6 +457,6 @@ void KeyFrameBBox::SetJsonValue(const Json::Value root) { BoxVec.insert({existing_point["key"].asDouble(), box}); } } - */ + return; } \ No newline at end of file diff --git a/src/effects/Tracker.cpp b/src/effects/Tracker.cpp index 423328b39..42ed3ea2c 100644 --- a/src/effects/Tracker.cpp +++ b/src/effects/Tracker.cpp @@ -69,6 +69,7 @@ void Tracker::init_effect_details() info.has_audio = false; info.has_video = true; + this->TimeScale = 1.0; } // This method is required for all derived classes of EffectBase, and returns a @@ -144,8 +145,10 @@ bool Tracker::LoadTrackedData(std::string inputFilePath){ // Assign data to tracker map //trackedDataById[id] = EffectFrameData(id, rotation, x1, y1, x2, y2); - trackedData.AddBox(id, x1, y1, (x2-x1), (y2-y1)); - trackedData.AddRotation(id, rotation); + if ((x1 >= 0.0) && (y1 >= 0.0) && (x2 >= 0.0) && (y2 >= 0.0)){ + trackedData.AddBox(id, x1, y1, (x2-x1), (y2-y1)); + trackedData.AddRotation(id, rotation); + } } // Show the time stamp from the last update in tracker data file @@ -180,7 +183,7 @@ Json::Value Tracker::JsonValue() const { root["protobuf_data_path"] = protobuf_data_path; root["BaseFPS"]["num"] = BaseFPS.num; root["BaseFPS"]["den"] = BaseFPS.den; - + root["TimeScale"] = this->TimeScale; // return JsonValue return root; } @@ -215,8 +218,13 @@ void Tracker::SetJsonValue(const Json::Value root) { BaseFPS.den = (int) root["BaseFPS"]["den"].asInt(); } + if (!root["TimeScale"].isNull()){ + TimeScale = (double) root["TimeScale"].asDouble(); + } + trackedData.SetBaseFPS(this->BaseFPS); - + trackedData.ScalePoints(TimeScale); + // Set data from Json (if key is found) if (!root["protobuf_data_path"].isNull()){ protobuf_data_path = (root["protobuf_data_path"].asString()); diff --git a/src/effects/Tracker.h b/src/effects/Tracker.h index 3350428ae..391e89345 100644 --- a/src/effects/Tracker.h +++ b/src/effects/Tracker.h @@ -92,6 +92,7 @@ namespace openshot void init_effect_details(); std::string protobuf_data_path; Fraction BaseFPS; + double TimeScale; public: std::map trackedDataById; // Save object tracking box data From 9113153be845f1bfbb2274971dba65ec00f5823d Mon Sep 17 00:00:00 2001 From: Brenno Date: Thu, 12 Nov 2020 21:35:47 -0300 Subject: [PATCH 05/84] Added properties to Tracker effects (still needs some fine-tuning) --- src/KeyFrameBBox.cpp | 34 ++++++++++++++--------- src/KeyFrameBBox.h | 26 +++++++++--------- src/effects/Tracker.cpp | 59 +++++++++++++++++++++++++++++----------- src/effects/Tracker.h | 10 +++++-- tests/KeyFrame_Tests.cpp | 14 +++++----- 5 files changed, 92 insertions(+), 51 deletions(-) diff --git a/src/KeyFrameBBox.cpp b/src/KeyFrameBBox.cpp index ddb5c3fc5..9c7c4ea0b 100644 --- a/src/KeyFrameBBox.cpp +++ b/src/KeyFrameBBox.cpp @@ -114,12 +114,19 @@ namespace { } } - +/* KeyFrameBBox::KeyFrameBBox(): delta_x(0.0), delta_y(0.0), scale_x(0.0), scale_y(0.0), rotation(0.0) { this->TimeScale = 1.0; return; } +*/ + +KeyFrameBBox::KeyFrameBBox(){ + this->TimeScale = 1.0; + return; +} +/* void KeyFrameBBox::AddDisplacement(int64_t frame_num, double _delta_x, double _delta_y){ if (!this->Contains((int64_t) frame_num)) return; @@ -156,7 +163,7 @@ void KeyFrameBBox::AddRotation(int64_t _frame_num, double rot){ rotation.AddPoint(time, rot, openshot::InterpolationType::LINEAR); } - +*/ void KeyFrameBBox::AddBox(int64_t _frame_num , float _cx, float _cy, float _width, float _height){ if (_frame_num < 0) @@ -202,12 +209,12 @@ void KeyFrameBBox::RemovePoint(int64_t frame_number){ if (it != BoxVec.end()){ BoxVec.erase(time); - RemoveDelta(time); - RemoveScale(time); + //RemoveDelta(time); + //RemoveScale(time); } return; } - +/* void KeyFrameBBox::RemoveDelta(int64_t frame_number) { double time = this->FrameNToTime(frame_number, 1.0); @@ -276,6 +283,7 @@ void KeyFrameBBox::RemoveScale(int64_t frame_number) { return; } +*/ BBox KeyFrameBBox::GetValue(int64_t frame_number){ double time = this->FrameNToTime(frame_number, this->TimeScale); @@ -288,11 +296,11 @@ BBox KeyFrameBBox::GetValue(int64_t frame_number){ if ((it->first == time) || (it == BoxVec.begin())){ BBox res = it->second; - res.cx += this->delta_x.GetValue(it->first); + /*res.cx += this->delta_x.GetValue(it->first); res.cy += this->delta_y.GetValue(it->first); res.height += this->scale_y.GetValue(it->first); res.width += this->scale_x.GetValue(it->first); - + */ return res; } @@ -302,12 +310,12 @@ BBox KeyFrameBBox::GetValue(int64_t frame_number){ BBox res = InterpolateBoxes(prev(it, 1)->first, it->first, first_ref, second_ref, time); /*later add rotation transform to these points*/ - + /* res.cx += this->delta_x.GetValue(time); res.cy += this->delta_y.GetValue(time); res.height += this->scale_y.GetValue(time); res.width += this->scale_x.GetValue(time); - + */ return res; @@ -388,13 +396,13 @@ Json::Value KeyFrameBBox::JsonValue() { root["boxes"].append(elem); } - +/* root["delta_x"] = delta_x.JsonValue(); root["delta_y"] = delta_y.JsonValue(); root["scale_x"] = scale_x.JsonValue(); root["scale_y"] = scale_y.JsonValue(); root["rotation"] = rotation.JsonValue(); - +*/ // return JsonValue return root; } @@ -428,13 +436,13 @@ void KeyFrameBBox::clear(){ void KeyFrameBBox::SetJsonValue(const Json::Value root) { // Clear existing points BoxVec.clear(); - +/* delta_x.SetJsonValue(root["delta_x"]); delta_y.SetJsonValue(root["delta_y"]); scale_x.SetJsonValue(root["scale_x"]); scale_y.SetJsonValue(root["scale_y"]); rotation.SetJsonValue(root["rotation"]); - +*/ if (!root["BaseFPS"].isNull() && root["BaseFPS"].isObject()) { if (!root["BaseFPS"]["num"].isNull()) diff --git a/src/KeyFrameBBox.h b/src/KeyFrameBBox.h index a80c7d7d7..803492862 100644 --- a/src/KeyFrameBBox.h +++ b/src/KeyFrameBBox.h @@ -138,18 +138,18 @@ namespace openshot { double TimeScale; std::map BoxVec; public: - Keyframe delta_x; - Keyframe delta_y; - Keyframe scale_x; - Keyframe scale_y; - Keyframe rotation; + //Keyframe delta_x; + //Keyframe delta_y; + //Keyframe scale_x; + //Keyframe scale_y; + //Keyframe rotation; KeyFrameBBox(); - void AddDisplacement(int64_t _frame_num, double _delta_x, double _delta_y); - void AddScale(int64_t _frame_num, double _delta_x, double _delta_y); + //void AddDisplacement(int64_t _frame_num, double _delta_x, double _delta_y); + //void AddScale(int64_t _frame_num, double _delta_x, double _delta_y); void AddBox(int64_t _frame_num, float _cx, float _cy, float _width, float _height); - void AddRotation(int64_t _frame_num, double rot); + //void AddRotation(int64_t _frame_num, double rot); void SetBaseFPS(Fraction fps); Fraction GetBaseFPS(); @@ -162,19 +162,19 @@ namespace openshot { /// Remove a points by frame_number void RemovePoint(int64_t frame_number); - void RemoveDelta(int64_t frame_number); - void RemoveScale(int64_t frame_number); - void RemoveRotation(int64_t frame_number); + //void RemoveDelta(int64_t frame_number); + //void RemoveScale(int64_t frame_number); + //void RemoveRotation(int64_t frame_number); BBox GetValue(int64_t frame_number); /// Print collection of points - void PrintParams(); + //void PrintParams(); double FrameNToTime(int64_t frame_number, double time_scale); BBox InterpolateBoxes(double t1, double t2, BBox left, BBox right, double target); - /// Get and Set JSON methods + /// Get and Set JSON methods std::string Json(); ///< Generate JSON string of this object Json::Value JsonValue(); ///< Generate Json::Value for this object void SetJson(const std::string value); ///< Load JSON string into this object diff --git a/src/effects/Tracker.cpp b/src/effects/Tracker.cpp index 42ed3ea2c..138ff3ac6 100644 --- a/src/effects/Tracker.cpp +++ b/src/effects/Tracker.cpp @@ -33,29 +33,23 @@ using namespace openshot; /// Blank constructor, useful when using Json to load the effect properties -Tracker::Tracker(std::string clipTrackerDataPath) +Tracker::Tracker(std::string clipTrackerDataPath): delta_x(0.0), delta_y(0.0), scale_x(0.0), scale_y(0.0), rotation(0.0) { // Init effect properties init_effect_details(); -/* - this->trackedData.SetBaseFPS(fps); - this->trackedData.SetOpFPS(fps); -*/ // Tries to load the tracker data from protobuf LoadTrackedData(clipTrackerDataPath); } // Default constructor -Tracker::Tracker() +Tracker::Tracker(): delta_x(0.0), delta_y(0.0), scale_x(0.0), scale_y(0.0), rotation(0.0) { // Init effect properties init_effect_details(); -/* - this->trackedData.SetBaseFPS(fps); - this->trackedData.SetOpFPS(fps); -*/ + } + // Init effect settings void Tracker::init_effect_details() { @@ -89,15 +83,21 @@ std::shared_ptr Tracker::GetFrame(std::shared_ptr frame, int64_t f float fw = frame_image.size().width; float fh = frame_image.size().height; + double scale_x = this->scale_x.GetValue(frame_number); + double scale_y = this->scale_y.GetValue(frame_number); + double delta_x = this->delta_x.GetValue(frame_number); + double delta_y = this->delta_y.GetValue(frame_number); + + // Draw box on image //EffectFrameData fd = trackedDataById[frame_number]; BBox fd = this->trackedData.GetValue(frame_number); - - cv::Rect2d box((int)(fd.cx*fw), - (int)(fd.cy*fh), - (int)(fd.width*fw), - (int)(fd.height*fh)); + + cv::Rect2d box((int)( (fd.cx + delta_x) * fw ), + (int)( (fd.cy + delta_y) * fh ), + (int)( (fd.width + scale_x) * fw), + (int)( (fd.height + scale_y) * fh) ); cv::rectangle(frame_image, box, cv::Scalar( 255, 0, 0 ), 2, 1 ); } } @@ -147,7 +147,7 @@ bool Tracker::LoadTrackedData(std::string inputFilePath){ //trackedDataById[id] = EffectFrameData(id, rotation, x1, y1, x2, y2); if ((x1 >= 0.0) && (y1 >= 0.0) && (x2 >= 0.0) && (y2 >= 0.0)){ trackedData.AddBox(id, x1, y1, (x2-x1), (y2-y1)); - trackedData.AddRotation(id, rotation); + //trackedData.AddRotation(id, rotation); } } @@ -184,6 +184,13 @@ Json::Value Tracker::JsonValue() const { root["BaseFPS"]["num"] = BaseFPS.num; root["BaseFPS"]["den"] = BaseFPS.den; root["TimeScale"] = this->TimeScale; + + root["delta_x"] = delta_x.JsonValue(); + root["delta_y"] = delta_y.JsonValue(); + root["scale_x"] = scale_x.JsonValue(); + root["scale_y"] = scale_y.JsonValue(); + root["rotation"] = rotation.JsonValue(); + // return JsonValue return root; } @@ -234,6 +241,19 @@ void Tracker::SetJsonValue(const Json::Value root) { protobuf_data_path = ""; } } + + if (!root["delta_x"].isNull()) + delta_x.SetJsonValue(root["delta_x"]); + if (!root["delta_y"].isNull()) + delta_y.SetJsonValue(root["delta_y"]); + if (!root["scale_x"].isNull()) + scale_x.SetJsonValue(root["scale_x"]); + if (!root["scale_y"].isNull()) + scale_y.SetJsonValue(root["scale_y"]); + if (!root["rotation"].isNull()) + rotation.SetJsonValue(root["rotation"]); + + } // Get all properties for a specific frame @@ -248,6 +268,13 @@ std::string Tracker::PropertiesJSON(int64_t requested_frame) const { root["end"] = add_property_json("End", End(), "float", "", NULL, 0, 1000 * 60 * 30, false, requested_frame); root["duration"] = add_property_json("Duration", Duration(), "float", "", NULL, 0, 1000 * 60 * 30, true, requested_frame); + // Keyframes + 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["rotation"] = add_property_json("Rotation", rotation.GetValue(requested_frame), "float", "", &rotation, 0, 360, false, requested_frame); + // Return formatted string return root.toStyledString(); } diff --git a/src/effects/Tracker.h b/src/effects/Tracker.h index 391e89345..34408a7ae 100644 --- a/src/effects/Tracker.h +++ b/src/effects/Tracker.h @@ -93,9 +93,15 @@ namespace openshot std::string protobuf_data_path; Fraction BaseFPS; double TimeScale; - public: - std::map trackedDataById; // Save object tracking box data + public: + Keyframe delta_x; + Keyframe delta_y; + Keyframe scale_x; + Keyframe scale_y; + Keyframe rotation; + + std::map trackedDataById; // Save object tracking box data KeyFrameBBox trackedData; diff --git a/tests/KeyFrame_Tests.cpp b/tests/KeyFrame_Tests.cpp index dcdab721e..56192b1d3 100644 --- a/tests/KeyFrame_Tests.cpp +++ b/tests/KeyFrame_Tests.cpp @@ -510,7 +510,7 @@ TEST(KeyFrameBBox_addBox_test) { CHECK_EQUAL(true, kfb.Contains(1)); CHECK_EQUAL(1, kfb.GetLength()); - kfb.PrintParams(); + //kfb.PrintParams(); kfb.RemovePoint(1); @@ -524,15 +524,15 @@ TEST(KeyFrameBBox_GetVal_test) { kfb.AddBox(1, 10.0, 10.0, 100.0, 100.0); - kfb.AddDisplacement(1, 20.0, 20.0); - kfb.AddScale(1, 30, 30); + //kfb.AddDisplacement(1, 20.0, 20.0); + //kfb.AddScale(1, 30, 30); BBox val = kfb.GetValue(1); - CHECK_EQUAL(30.0, val.cx); - CHECK_EQUAL(30.0, val.cy); - CHECK_EQUAL(130.0,val.width); - CHECK_EQUAL(130.0, val.height); + CHECK_EQUAL(10.0, val.cx); + CHECK_EQUAL(10.0, val.cy); + CHECK_EQUAL(100.0,val.width); + CHECK_EQUAL(100.0, val.height); } From 1933d887e9a6de70440e36ead7830f71da550fee Mon Sep 17 00:00:00 2001 From: Brenno Date: Sat, 28 Nov 2020 18:00:38 -0300 Subject: [PATCH 06/84] Fixed opencv example compilation on cmake --- examples/CMakeLists.txt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 874751288..3f77d7009 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -63,3 +63,18 @@ if (BLACKMAGIC_FOUND) # Link test executable to the new library target_link_libraries(openshot-blackmagic openshot) endif() + +############### OPENCV EXAMPLE ################ +find_package( OpenCV 4 ) +if (OpenCV_FOUND) + # Create test executable + add_executable(openshot-example-opencv + Example_opencv.cpp) + + target_compile_definitions(openshot-example-opencv PRIVATE + -DTEST_MEDIA_PATH="${TEST_MEDIA_PATH}" ) + + # Link test executable to the new library + target_link_libraries(openshot-example-opencv openshot) + +endif() From a9d783c1061a0b66b2ba71ec2ec564f35c9b1ca4 Mon Sep 17 00:00:00 2001 From: Brenno Date: Sat, 28 Nov 2020 18:01:58 -0300 Subject: [PATCH 07/84] Updated include path on opencv examples --- examples/Example_opencv.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/examples/Example_opencv.cpp b/examples/Example_opencv.cpp index e820708a8..6b605a840 100644 --- a/examples/Example_opencv.cpp +++ b/examples/Example_opencv.cpp @@ -31,12 +31,12 @@ #include #include #include -#include "../../include/CVTracker.h" -#include "../../include/CVStabilization.h" -#include "../../include/CVObjectDetection.h" +#include "../../src/CVTracker.h" +#include "../../src/CVStabilization.h" +#include "../../src/CVObjectDetection.h" -#include "../../include/OpenShot.h" -#include "../../include/CrashHandler.h" +#include "../../src/OpenShot.h" +#include "../../src/CrashHandler.h" using namespace openshot; using namespace std; @@ -118,7 +118,7 @@ int main(int argc, char* argv[]) { CVTracker tracker(trackerJson(r, false), processingController); // Start the tracking - tracker.trackClip(r9, 0, 100, true); + tracker.trackClip(r9, 0, 0, true); // Save the tracked data tracker.SaveTrackedData(); @@ -230,13 +230,14 @@ string trackerJson(cv::Rect2d r, bool onlyProtoPath){ // Construct all the composition of the JSON string string protobuf_data_path = jsonFormat("protobuf_data_path", protobufDataPath); - string trackerType = jsonFormat("tracker_type", tracker); + string trackerType = jsonFormat("tracker-type", tracker); string bboxCoords = jsonFormat( - "bbox", + "region", "{" + jsonFormat("x", to_string(r.x), "int") + "," + jsonFormat("y", to_string(r.y), "int") + - "," + jsonFormat("w", to_string(r.width), "int") + - "," + jsonFormat("h", to_string(r.height), "int") + + "," + jsonFormat("width", to_string(r.width), "int") + + "," + jsonFormat("height", to_string(r.height), "int") + + "," + jsonFormat("first-frame", to_string(0), "int") + "}", "rstring"); From dd9e203695e77d3f9feb5da8bbc6d419856afedb Mon Sep 17 00:00:00 2001 From: Brenno Date: Sat, 28 Nov 2020 18:09:10 -0300 Subject: [PATCH 08/84] Added transform handler for Tracker effect It's now possible to adjust the tracked bounding box from the preview window. Some work is needed to make it generic to the ObjectDetection effect and future effects --- src/KeyFrameBBox.cpp | 20 ++++++++--------- src/KeyFrameBBox.h | 34 ++++++++++++++++++---------- src/effects/Tracker.cpp | 48 ++++++++++++++++++++++++++++------------ tests/KeyFrame_Tests.cpp | 16 +++++++------- 4 files changed, 74 insertions(+), 44 deletions(-) diff --git a/src/KeyFrameBBox.cpp b/src/KeyFrameBBox.cpp index 9c7c4ea0b..870506a8e 100644 --- a/src/KeyFrameBBox.cpp +++ b/src/KeyFrameBBox.cpp @@ -164,12 +164,12 @@ void KeyFrameBBox::AddRotation(int64_t _frame_num, double rot){ rotation.AddPoint(time, rot, openshot::InterpolationType::LINEAR); } */ -void KeyFrameBBox::AddBox(int64_t _frame_num , float _cx, float _cy, float _width, float _height){ +void KeyFrameBBox::AddBox(int64_t _frame_num , float _x1, float _y1, float _width, float _height){ if (_frame_num < 0) return; - BBox box = BBox(_cx, _cy, _width, _height); + BBox box = BBox(_x1, _y1, _width, _height); double time = this->FrameNToTime(_frame_num, 1.0); @@ -296,8 +296,8 @@ BBox KeyFrameBBox::GetValue(int64_t frame_number){ if ((it->first == time) || (it == BoxVec.begin())){ BBox res = it->second; - /*res.cx += this->delta_x.GetValue(it->first); - res.cy += this->delta_y.GetValue(it->first); + /*res.x1 += this->delta_x.GetValue(it->first); + res.y1 += this->delta_y.GetValue(it->first); res.height += this->scale_y.GetValue(it->first); res.width += this->scale_x.GetValue(it->first); */ @@ -311,8 +311,8 @@ BBox KeyFrameBBox::GetValue(int64_t frame_number){ /*later add rotation transform to these points*/ /* - res.cx += this->delta_x.GetValue(time); - res.cy += this->delta_y.GetValue(time); + res.x1 += this->delta_x.GetValue(time); + res.y1 += this->delta_y.GetValue(time); res.height += this->scale_y.GetValue(time); res.width += this->scale_x.GetValue(time); */ @@ -323,13 +323,13 @@ BBox KeyFrameBBox::GetValue(int64_t frame_number){ BBox KeyFrameBBox::InterpolateBoxes(double t1, double t2, BBox left, BBox right, double target){ - Point p1_left(t1, left.cx, openshot::InterpolationType::LINEAR); - Point p1_right(t2, right.cx, openshot::InterpolationType::LINEAR); + Point p1_left(t1, left.x1, openshot::InterpolationType::LINEAR); + Point p1_right(t2, right.x1, openshot::InterpolationType::LINEAR); Point p1 = InterpolateBetween(p1_left, p1_right, target, 0.01); - Point p2_left(t1, left.cy, openshot::InterpolationType::LINEAR); - Point p2_right(t2, right.cy, openshot::InterpolationType::LINEAR); + Point p2_left(t1, left.y1, openshot::InterpolationType::LINEAR); + Point p2_right(t2, right.y1, openshot::InterpolationType::LINEAR); Point p2 = InterpolateBetween(p2_left, p2_right, target, 0.01); diff --git a/src/KeyFrameBBox.h b/src/KeyFrameBBox.h index 803492862..9828812fd 100644 --- a/src/KeyFrameBBox.h +++ b/src/KeyFrameBBox.h @@ -62,8 +62,8 @@ namespace openshot { struct BBox{ - float cx = -1; - float cy = -1; + float x1 = -1; + float y1 = -1; float width = -1; float height = -1; @@ -72,14 +72,16 @@ namespace openshot { return; } - BBox(float _cx, float _cy, float _width, float _height){ + BBox(float _x1, float _y1, float _width, float _height){ //frame_num = _frame_num; - cx = _cx; - cy = _cy; + x1 = _x1; + y1 = _y1; width = _width; height = _height; } + + std::string Json() const { // Return formatted string return JsonValue().toStyledString(); @@ -90,8 +92,8 @@ namespace openshot { // Create root json object Json::Value root; - root["cx"] = cx; - root["cy"] = cy; + root["x1"] = x1; + root["y1"] = y1; root["height"] = height; root["width"] = width; @@ -119,10 +121,10 @@ namespace openshot { void SetJsonValue(const Json::Value root) { // Set data from Json (if key is found) - if (!root["cx"].isNull()) - cx = root["cx"].asDouble(); - if (!root["cy"].isNull()) - cy = root["cy"].asDouble(); + if (!root["x1"].isNull()) + x1 = root["x1"].asDouble(); + if (!root["y1"].isNull()) + y1 = root["y1"].asDouble(); if (!root["height"].isNull()) height = root["height"].asDouble(); if (!root["width"].isNull()) @@ -143,12 +145,14 @@ namespace openshot { //Keyframe scale_x; //Keyframe scale_y; //Keyframe rotation; + + KeyFrameBBox(); //void AddDisplacement(int64_t _frame_num, double _delta_x, double _delta_y); //void AddScale(int64_t _frame_num, double _delta_x, double _delta_y); - void AddBox(int64_t _frame_num, float _cx, float _cy, float _width, float _height); + void AddBox(int64_t _frame_num, float _x1, float _y1, float _width, float _height); //void AddRotation(int64_t _frame_num, double rot); void SetBaseFPS(Fraction fps); @@ -166,7 +170,13 @@ namespace openshot { //void RemoveScale(int64_t frame_number); //void RemoveRotation(int64_t frame_number); + BBox GetValue(int64_t frame_number) const + { + return const_cast(this)->GetValue(frame_number); + } + BBox GetValue(int64_t frame_number); + /// Print collection of points //void PrintParams(); diff --git a/src/effects/Tracker.cpp b/src/effects/Tracker.cpp index 138ff3ac6..17e234615 100644 --- a/src/effects/Tracker.cpp +++ b/src/effects/Tracker.cpp @@ -33,7 +33,7 @@ using namespace openshot; /// Blank constructor, useful when using Json to load the effect properties -Tracker::Tracker(std::string clipTrackerDataPath): delta_x(0.0), delta_y(0.0), scale_x(0.0), scale_y(0.0), rotation(0.0) +Tracker::Tracker(std::string clipTrackerDataPath): delta_x(0.0), delta_y(0.0), scale_x(1.0), scale_y(1.0), rotation(0.0) { // Init effect properties init_effect_details(); @@ -42,7 +42,7 @@ Tracker::Tracker(std::string clipTrackerDataPath): delta_x(0.0), delta_y(0.0), s } // Default constructor -Tracker::Tracker(): delta_x(0.0), delta_y(0.0), scale_x(0.0), scale_y(0.0), rotation(0.0) +Tracker::Tracker(): delta_x(0.0), delta_y(0.0), scale_x(1.0), scale_y(1.0), rotation(0.0) { // Init effect properties init_effect_details(); @@ -88,16 +88,19 @@ std::shared_ptr Tracker::GetFrame(std::shared_ptr frame, int64_t f double delta_x = this->delta_x.GetValue(frame_number); double delta_y = this->delta_y.GetValue(frame_number); + // convert to [cx, cy, width, height]. Apply scale and translation + BBox fd = this->trackedData.GetValue(frame_number); + float cx = fd.x1 + (fd.width/2) + delta_x; + float cy = fd.y1 + (fd.height/2) + delta_y; + float width = fd.width * scale_x; + float height = fd.height * scale_y; - // Draw box on image - //EffectFrameData fd = trackedDataById[frame_number]; - BBox fd = this->trackedData.GetValue(frame_number); - - cv::Rect2d box((int)( (fd.cx + delta_x) * fw ), - (int)( (fd.cy + delta_y) * fh ), - (int)( (fd.width + scale_x) * fw), - (int)( (fd.height + scale_y) * fh) ); + // Draw box on image + cv::Rect2d box((int)( (cx - (width/2) ) * fw ), + (int)( (cy - (height/2) ) * fh ), + (int)( (width) * fw), + (int)( (height) * fh) ); cv::rectangle(frame_image, box, cv::Scalar( 255, 0, 0 ), 2, 1 ); } } @@ -256,6 +259,7 @@ void Tracker::SetJsonValue(const Json::Value root) { } + // Get all properties for a specific frame std::string Tracker::PropertiesJSON(int64_t requested_frame) const { @@ -269,12 +273,28 @@ std::string Tracker::PropertiesJSON(int64_t requested_frame) const { root["duration"] = add_property_json("Duration", Duration(), "float", "", NULL, 0, 1000 * 60 * 30, true, requested_frame); // Keyframes - 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); + float scale_x_value = this->scale_x.GetValue(requested_frame); + float scale_y_value = this->scale_y.GetValue(requested_frame); + float delta_x_value = this->delta_x.GetValue(requested_frame); + float delta_y_value = this->delta_y.GetValue(requested_frame); + root["delta_x"] = add_property_json("Displacement X-axis", this->delta_x.GetValue(requested_frame), "float", "", &delta_x, -1.0, 1.0, false, requested_frame); + root["delta_y"] = add_property_json("Displacement Y-axis", this->delta_y.GetValue(requested_frame), "float", "", &delta_y, -1.0, 1.0, false, requested_frame); + root["scale_x"] = add_property_json("Scale (Width)", this->scale_x.GetValue(requested_frame), "float", "", &scale_x, 0.0, 1.0, false, requested_frame); + root["scale_y"] = add_property_json("Scale (Height)", this->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); + // TODO: use p1, p2 convention instead of [x1, y1, width, height] + BBox fd = this->trackedData.GetValue(requested_frame); + float cx = fd.x1 + (fd.width/2) + delta_x_value; + float cy = fd.y1 + (fd.height/2) + delta_y_value; + float width = fd.width * scale_x_value; + float height = fd.height * scale_y_value; + + root["x1"] = add_property_json("X1", cx-(width/2), "float", "", NULL, 0.0, 1.0, false, requested_frame); + root["y1"] = add_property_json("Y1", cy-(height/2), "float", "", NULL, 0.0, 1.0, false, requested_frame); + root["x2"] = add_property_json("X2", cx+(width/2), "float", "", NULL, 0.0, 1.0, false, requested_frame); + root["y2"] = add_property_json("Y2", cy+(height/2), "float", "", NULL, 0.0, 1.0, false, requested_frame); + // Return formatted string return root.toStyledString(); } diff --git a/tests/KeyFrame_Tests.cpp b/tests/KeyFrame_Tests.cpp index 56192b1d3..c5d5b6da7 100644 --- a/tests/KeyFrame_Tests.cpp +++ b/tests/KeyFrame_Tests.cpp @@ -529,8 +529,8 @@ TEST(KeyFrameBBox_GetVal_test) { BBox val = kfb.GetValue(1); - CHECK_EQUAL(10.0, val.cx); - CHECK_EQUAL(10.0, val.cy); + CHECK_EQUAL(10.0, val.x1); + CHECK_EQUAL(10.0, val.y1); CHECK_EQUAL(100.0,val.width); CHECK_EQUAL(100.0, val.height); } @@ -550,22 +550,22 @@ TEST(KeyFrameBBox_GetVal_Interpolation) { BBox val = kfb.GetValue(5); - CHECK_EQUAL(14.0, val.cx); - CHECK_EQUAL(14.0, val.cy); + CHECK_EQUAL(14.0, val.x1); + CHECK_EQUAL(14.0, val.y1); CHECK_EQUAL(100.0,val.width); CHECK_EQUAL(100.0, val.height); val = kfb.GetValue(15); - CHECK_EQUAL(24.0, val.cx); - CHECK_EQUAL(24.0, val.cy); + CHECK_EQUAL(24.0, val.x1); + CHECK_EQUAL(24.0, val.y1); CHECK_EQUAL(100.0,val.width); CHECK_EQUAL(100.0, val.height); val = kfb.GetValue(25); - CHECK_EQUAL(34.0, val.cx); - CHECK_EQUAL(34.0, val.cy); + CHECK_EQUAL(34.0, val.x1); + CHECK_EQUAL(34.0, val.y1); CHECK_EQUAL(100.0,val.width); CHECK_EQUAL(100.0, val.height); From e3bd2e4b1528173e0b3bbcc5dab68eb14a06dec8 Mon Sep 17 00:00:00 2001 From: Brenno Date: Sat, 12 Dec 2020 19:28:08 -0300 Subject: [PATCH 09/84] Improved protobuf message compiling --- src/CMakeLists.txt | 39 +- src/effects/ObjectDetection.h | 2 +- src/objdetectdata.pb.cc | 1003 ------------------------- src/objdetectdata.pb.h | 1020 -------------------------- src/protobuf_messages/CMakeLists.txt | 38 + src/stabilizedata.pb.cc | 722 ------------------ src/stabilizedata.pb.h | 723 ------------------ src/trackerdata.pb.cc | 961 ------------------------ src/trackerdata.pb.h | 931 ----------------------- 9 files changed, 45 insertions(+), 5394 deletions(-) delete mode 100644 src/objdetectdata.pb.cc delete mode 100644 src/objdetectdata.pb.h create mode 100644 src/protobuf_messages/CMakeLists.txt delete mode 100644 src/stabilizedata.pb.cc delete mode 100644 src/stabilizedata.pb.h delete mode 100644 src/trackerdata.pb.cc delete mode 100644 src/trackerdata.pb.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6958580b8..cfb73feca 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -113,13 +113,6 @@ set(OPENSHOT_CV_SOURCES ./sort_filter/Hungarian.cpp ./sort_filter/KalmanTracker.cpp) -# Compiled Protobuf messages -set(PROTOBUF_MESSAGES - stabilizedata.pb.cc - trackerdata.pb.cc - objdetectdata.pb.cc - ) - # Video effects set(EFFECTS_SOURCES effects/Bars.cpp @@ -416,37 +409,16 @@ if (OpenCV_FOUND) message(FATAL_ERROR "\nPLEASE INSTALL PROTOBUF. Protobuf is required when compiling with opencv.\n") endif() - # compiling protobuf messages - include_directories(${PROTOBUF_INCLUDE_DIR}) - set(PROTOBUF_MESSAGES_FOLDER "${CMAKE_CURRENT_SOURCE_DIR}/protobuf_messages") - - FILE(GLOB PROTO_MSGS "${PROTOBUF_MESSAGES_FOLDER}/*.proto") - foreach(PROTO_MSG ${PROTO_MSGS}) - execute_process ( - COMMAND bash -c "${PROTOBUF_PROTOC_EXECUTABLE} -I=${PROTOBUF_MESSAGES_FOLDER} --cpp_out=${PROTOBUF_MESSAGES_FOLDER} ${PROTO_MSG}" - ) - endforeach() - - FILE(GLOB PROTO_CCS "${PROTOBUF_MESSAGES_FOLDER}/*.pb.cc") - foreach(PROTO_CC ${PROTO_CCS}) - execute_process(COMMAND ${CMAKE_COMMAND} -E copy ${PROTO_CC} ${CMAKE_CURRENT_SOURCE_DIR}) - file(REMOVE ${PROTO_CC}) - endforeach() - - FILE(GLOB PROTO_HS "${PROTOBUF_MESSAGES_FOLDER}/*.pb.h") - foreach(PROTO_H ${PROTO_HS}) - execute_process(COMMAND ${CMAKE_COMMAND} -E copy ${PROTO_H} ${CMAKE_CURRENT_SOURCE_DIR}) - file(REMOVE ${PROTO_H}) - endforeach() + add_subdirectory(protobuf_messages) + + target_include_directories(openshot PUBLIC ${ProtobufMessagePath}) # Add OpenCV target sources target_sources(openshot PRIVATE - ${OPENSHOT_CV_SOURCES} - ${PROTOBUF_MESSAGES}) + ${OPENSHOT_CV_SOURCES}) # Link libopenshot with OpenCV libs - target_link_libraries(openshot PUBLIC ${OpenCV_LIBS} ${PROTOBUF_LIBRARY}) - + target_link_libraries(openshot PUBLIC ProtoMessages ${OpenCV_LIBS} ${PROTOBUF_LIBRARY} ${Protobuf_INCLUDE_DIRS}) endif() ############### LINK LIBRARY ################# @@ -490,3 +462,4 @@ endif() set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Jonathan Thomas") #required include(CPack) + diff --git a/src/effects/ObjectDetection.h b/src/effects/ObjectDetection.h index ac528ef6f..45d30d588 100644 --- a/src/effects/ObjectDetection.h +++ b/src/effects/ObjectDetection.h @@ -40,7 +40,7 @@ #include "../Color.h" #include "../Json.h" #include "../KeyFrame.h" -#include "../objdetectdata.pb.h" +#include "objdetectdata.pb.h" // Struct that stores the detected bounding boxes for all the clip frames struct DetectionData{ diff --git a/src/objdetectdata.pb.cc b/src/objdetectdata.pb.cc deleted file mode 100644 index d4d04ea06..000000000 --- a/src/objdetectdata.pb.cc +++ /dev/null @@ -1,1003 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: objdetectdata.proto - -#include "objdetectdata.pb.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -// @@protoc_insertion_point(includes) -#include -extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2ftimestamp_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Timestamp_google_2fprotobuf_2ftimestamp_2eproto; -extern PROTOBUF_INTERNAL_EXPORT_objdetectdata_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_Frame_objdetectdata_2eproto; -extern PROTOBUF_INTERNAL_EXPORT_objdetectdata_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Frame_Box_objdetectdata_2eproto; -namespace libopenshotobjdetect { -class Frame_BoxDefaultTypeInternal { - public: - ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; -} _Frame_Box_default_instance_; -class FrameDefaultTypeInternal { - public: - ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; -} _Frame_default_instance_; -class ObjDetectDefaultTypeInternal { - public: - ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; -} _ObjDetect_default_instance_; -} // namespace libopenshotobjdetect -static void InitDefaultsscc_info_Frame_objdetectdata_2eproto() { - GOOGLE_PROTOBUF_VERIFY_VERSION; - - { - void* ptr = &::libopenshotobjdetect::_Frame_default_instance_; - new (ptr) ::libopenshotobjdetect::Frame(); - ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); - } - ::libopenshotobjdetect::Frame::InitAsDefaultInstance(); -} - -::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_Frame_objdetectdata_2eproto = - {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_Frame_objdetectdata_2eproto}, { - &scc_info_Frame_Box_objdetectdata_2eproto.base,}}; - -static void InitDefaultsscc_info_Frame_Box_objdetectdata_2eproto() { - GOOGLE_PROTOBUF_VERIFY_VERSION; - - { - void* ptr = &::libopenshotobjdetect::_Frame_Box_default_instance_; - new (ptr) ::libopenshotobjdetect::Frame_Box(); - ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); - } - ::libopenshotobjdetect::Frame_Box::InitAsDefaultInstance(); -} - -::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Frame_Box_objdetectdata_2eproto = - {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_Frame_Box_objdetectdata_2eproto}, {}}; - -static void InitDefaultsscc_info_ObjDetect_objdetectdata_2eproto() { - GOOGLE_PROTOBUF_VERIFY_VERSION; - - { - void* ptr = &::libopenshotobjdetect::_ObjDetect_default_instance_; - new (ptr) ::libopenshotobjdetect::ObjDetect(); - ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); - } - ::libopenshotobjdetect::ObjDetect::InitAsDefaultInstance(); -} - -::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<2> scc_info_ObjDetect_objdetectdata_2eproto = - {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 2, 0, InitDefaultsscc_info_ObjDetect_objdetectdata_2eproto}, { - &scc_info_Frame_objdetectdata_2eproto.base, - &scc_info_Timestamp_google_2fprotobuf_2ftimestamp_2eproto.base,}}; - -static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_objdetectdata_2eproto[3]; -static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_objdetectdata_2eproto = nullptr; -static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_objdetectdata_2eproto = nullptr; - -const ::PROTOBUF_NAMESPACE_ID::uint32 TableStruct_objdetectdata_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { - ~0u, // no _has_bits_ - PROTOBUF_FIELD_OFFSET(::libopenshotobjdetect::Frame_Box, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - PROTOBUF_FIELD_OFFSET(::libopenshotobjdetect::Frame_Box, x_), - PROTOBUF_FIELD_OFFSET(::libopenshotobjdetect::Frame_Box, y_), - PROTOBUF_FIELD_OFFSET(::libopenshotobjdetect::Frame_Box, w_), - PROTOBUF_FIELD_OFFSET(::libopenshotobjdetect::Frame_Box, h_), - PROTOBUF_FIELD_OFFSET(::libopenshotobjdetect::Frame_Box, classid_), - PROTOBUF_FIELD_OFFSET(::libopenshotobjdetect::Frame_Box, confidence_), - ~0u, // no _has_bits_ - PROTOBUF_FIELD_OFFSET(::libopenshotobjdetect::Frame, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - PROTOBUF_FIELD_OFFSET(::libopenshotobjdetect::Frame, id_), - PROTOBUF_FIELD_OFFSET(::libopenshotobjdetect::Frame, bounding_box_), - ~0u, // no _has_bits_ - PROTOBUF_FIELD_OFFSET(::libopenshotobjdetect::ObjDetect, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - PROTOBUF_FIELD_OFFSET(::libopenshotobjdetect::ObjDetect, frame_), - PROTOBUF_FIELD_OFFSET(::libopenshotobjdetect::ObjDetect, last_updated_), - PROTOBUF_FIELD_OFFSET(::libopenshotobjdetect::ObjDetect, classnames_), -}; -static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { - { 0, -1, sizeof(::libopenshotobjdetect::Frame_Box)}, - { 11, -1, sizeof(::libopenshotobjdetect::Frame)}, - { 18, -1, sizeof(::libopenshotobjdetect::ObjDetect)}, -}; - -static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = { - reinterpret_cast(&::libopenshotobjdetect::_Frame_Box_default_instance_), - reinterpret_cast(&::libopenshotobjdetect::_Frame_default_instance_), - reinterpret_cast(&::libopenshotobjdetect::_ObjDetect_default_instance_), -}; - -const char descriptor_table_protodef_objdetectdata_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = - "\n\023objdetectdata.proto\022\024libopenshotobjdet" - "ect\032\037google/protobuf/timestamp.proto\"\242\001\n" - "\005Frame\022\n\n\002id\030\001 \001(\005\0225\n\014bounding_box\030\002 \003(\013" - "2\037.libopenshotobjdetect.Frame.Box\032V\n\003Box" - "\022\t\n\001x\030\001 \001(\002\022\t\n\001y\030\002 \001(\002\022\t\n\001w\030\003 \001(\002\022\t\n\001h\030\004" - " \001(\002\022\017\n\007classId\030\005 \001(\005\022\022\n\nconfidence\030\006 \001(" - "\002\"}\n\tObjDetect\022*\n\005frame\030\001 \003(\0132\033.libopens" - "hotobjdetect.Frame\0220\n\014last_updated\030\002 \001(\013" - "2\032.google.protobuf.Timestamp\022\022\n\nclassNam" - "es\030\003 \003(\tb\006proto3" - ; -static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_objdetectdata_2eproto_deps[1] = { - &::descriptor_table_google_2fprotobuf_2ftimestamp_2eproto, -}; -static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_objdetectdata_2eproto_sccs[3] = { - &scc_info_Frame_objdetectdata_2eproto.base, - &scc_info_Frame_Box_objdetectdata_2eproto.base, - &scc_info_ObjDetect_objdetectdata_2eproto.base, -}; -static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_objdetectdata_2eproto_once; -const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_objdetectdata_2eproto = { - false, false, descriptor_table_protodef_objdetectdata_2eproto, "objdetectdata.proto", 376, - &descriptor_table_objdetectdata_2eproto_once, descriptor_table_objdetectdata_2eproto_sccs, descriptor_table_objdetectdata_2eproto_deps, 3, 1, - schemas, file_default_instances, TableStruct_objdetectdata_2eproto::offsets, - file_level_metadata_objdetectdata_2eproto, 3, file_level_enum_descriptors_objdetectdata_2eproto, file_level_service_descriptors_objdetectdata_2eproto, -}; - -// Force running AddDescriptors() at dynamic initialization time. -static bool dynamic_init_dummy_objdetectdata_2eproto = (static_cast(::PROTOBUF_NAMESPACE_ID::internal::AddDescriptors(&descriptor_table_objdetectdata_2eproto)), true); -namespace libopenshotobjdetect { - -// =================================================================== - -void Frame_Box::InitAsDefaultInstance() { -} -class Frame_Box::_Internal { - public: -}; - -Frame_Box::Frame_Box(::PROTOBUF_NAMESPACE_ID::Arena* arena) - : ::PROTOBUF_NAMESPACE_ID::Message(arena) { - SharedCtor(); - RegisterArenaDtor(arena); - // @@protoc_insertion_point(arena_constructor:libopenshotobjdetect.Frame.Box) -} -Frame_Box::Frame_Box(const Frame_Box& from) - : ::PROTOBUF_NAMESPACE_ID::Message() { - _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); - ::memcpy(&x_, &from.x_, - static_cast(reinterpret_cast(&confidence_) - - reinterpret_cast(&x_)) + sizeof(confidence_)); - // @@protoc_insertion_point(copy_constructor:libopenshotobjdetect.Frame.Box) -} - -void Frame_Box::SharedCtor() { - ::memset(&x_, 0, static_cast( - reinterpret_cast(&confidence_) - - reinterpret_cast(&x_)) + sizeof(confidence_)); -} - -Frame_Box::~Frame_Box() { - // @@protoc_insertion_point(destructor:libopenshotobjdetect.Frame.Box) - SharedDtor(); - _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); -} - -void Frame_Box::SharedDtor() { - GOOGLE_DCHECK(GetArena() == nullptr); -} - -void Frame_Box::ArenaDtor(void* object) { - Frame_Box* _this = reinterpret_cast< Frame_Box* >(object); - (void)_this; -} -void Frame_Box::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { -} -void Frame_Box::SetCachedSize(int size) const { - _cached_size_.Set(size); -} -const Frame_Box& Frame_Box::default_instance() { - ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Frame_Box_objdetectdata_2eproto.base); - return *internal_default_instance(); -} - - -void Frame_Box::Clear() { -// @@protoc_insertion_point(message_clear_start:libopenshotobjdetect.Frame.Box) - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void) cached_has_bits; - - ::memset(&x_, 0, static_cast( - reinterpret_cast(&confidence_) - - reinterpret_cast(&x_)) + sizeof(confidence_)); - _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); -} - -const char* Frame_Box::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { -#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure - ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena; - while (!ctx->Done(&ptr)) { - ::PROTOBUF_NAMESPACE_ID::uint32 tag; - ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); - CHK_(ptr); - switch (tag >> 3) { - // float x = 1; - case 1: - if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 13)) { - x_ = ::PROTOBUF_NAMESPACE_ID::internal::UnalignedLoad(ptr); - ptr += sizeof(float); - } else goto handle_unusual; - continue; - // float y = 2; - case 2: - if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 21)) { - y_ = ::PROTOBUF_NAMESPACE_ID::internal::UnalignedLoad(ptr); - ptr += sizeof(float); - } else goto handle_unusual; - continue; - // float w = 3; - case 3: - if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 29)) { - w_ = ::PROTOBUF_NAMESPACE_ID::internal::UnalignedLoad(ptr); - ptr += sizeof(float); - } else goto handle_unusual; - continue; - // float h = 4; - case 4: - if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 37)) { - h_ = ::PROTOBUF_NAMESPACE_ID::internal::UnalignedLoad(ptr); - ptr += sizeof(float); - } else goto handle_unusual; - continue; - // int32 classId = 5; - case 5: - if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 40)) { - classid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); - CHK_(ptr); - } else goto handle_unusual; - continue; - // float confidence = 6; - case 6: - if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 53)) { - confidence_ = ::PROTOBUF_NAMESPACE_ID::internal::UnalignedLoad(ptr); - ptr += sizeof(float); - } else goto handle_unusual; - continue; - default: { - handle_unusual: - if ((tag & 7) == 4 || tag == 0) { - ctx->SetLastTag(tag); - goto success; - } - ptr = UnknownFieldParse(tag, - _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), - ptr, ctx); - CHK_(ptr != nullptr); - continue; - } - } // switch - } // while -success: - return ptr; -failure: - ptr = nullptr; - goto success; -#undef CHK_ -} - -::PROTOBUF_NAMESPACE_ID::uint8* Frame_Box::_InternalSerialize( - ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:libopenshotobjdetect.Frame.Box) - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - // float x = 1; - if (!(this->x() <= 0 && this->x() >= 0)) { - target = stream->EnsureSpace(target); - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteFloatToArray(1, this->_internal_x(), target); - } - - // float y = 2; - if (!(this->y() <= 0 && this->y() >= 0)) { - target = stream->EnsureSpace(target); - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteFloatToArray(2, this->_internal_y(), target); - } - - // float w = 3; - if (!(this->w() <= 0 && this->w() >= 0)) { - target = stream->EnsureSpace(target); - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteFloatToArray(3, this->_internal_w(), target); - } - - // float h = 4; - if (!(this->h() <= 0 && this->h() >= 0)) { - target = stream->EnsureSpace(target); - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteFloatToArray(4, this->_internal_h(), target); - } - - // int32 classId = 5; - if (this->classid() != 0) { - target = stream->EnsureSpace(target); - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(5, this->_internal_classid(), target); - } - - // float confidence = 6; - if (!(this->confidence() <= 0 && this->confidence() >= 0)) { - target = stream->EnsureSpace(target); - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteFloatToArray(6, this->_internal_confidence(), target); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:libopenshotobjdetect.Frame.Box) - return target; -} - -size_t Frame_Box::ByteSizeLong() const { -// @@protoc_insertion_point(message_byte_size_start:libopenshotobjdetect.Frame.Box) - size_t total_size = 0; - - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void) cached_has_bits; - - // float x = 1; - if (!(this->x() <= 0 && this->x() >= 0)) { - total_size += 1 + 4; - } - - // float y = 2; - if (!(this->y() <= 0 && this->y() >= 0)) { - total_size += 1 + 4; - } - - // float w = 3; - if (!(this->w() <= 0 && this->w() >= 0)) { - total_size += 1 + 4; - } - - // float h = 4; - if (!(this->h() <= 0 && this->h() >= 0)) { - total_size += 1 + 4; - } - - // int32 classId = 5; - if (this->classid() != 0) { - total_size += 1 + - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( - this->_internal_classid()); - } - - // float confidence = 6; - if (!(this->confidence() <= 0 && this->confidence() >= 0)) { - total_size += 1 + 4; - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( - _internal_metadata_, total_size, &_cached_size_); - } - int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); - SetCachedSize(cached_size); - return total_size; -} - -void Frame_Box::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { -// @@protoc_insertion_point(generalized_merge_from_start:libopenshotobjdetect.Frame.Box) - GOOGLE_DCHECK_NE(&from, this); - const Frame_Box* source = - ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( - &from); - if (source == nullptr) { - // @@protoc_insertion_point(generalized_merge_from_cast_fail:libopenshotobjdetect.Frame.Box) - ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); - } else { - // @@protoc_insertion_point(generalized_merge_from_cast_success:libopenshotobjdetect.Frame.Box) - MergeFrom(*source); - } -} - -void Frame_Box::MergeFrom(const Frame_Box& from) { -// @@protoc_insertion_point(class_specific_merge_from_start:libopenshotobjdetect.Frame.Box) - GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - if (!(from.x() <= 0 && from.x() >= 0)) { - _internal_set_x(from._internal_x()); - } - if (!(from.y() <= 0 && from.y() >= 0)) { - _internal_set_y(from._internal_y()); - } - if (!(from.w() <= 0 && from.w() >= 0)) { - _internal_set_w(from._internal_w()); - } - if (!(from.h() <= 0 && from.h() >= 0)) { - _internal_set_h(from._internal_h()); - } - if (from.classid() != 0) { - _internal_set_classid(from._internal_classid()); - } - if (!(from.confidence() <= 0 && from.confidence() >= 0)) { - _internal_set_confidence(from._internal_confidence()); - } -} - -void Frame_Box::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { -// @@protoc_insertion_point(generalized_copy_from_start:libopenshotobjdetect.Frame.Box) - if (&from == this) return; - Clear(); - MergeFrom(from); -} - -void Frame_Box::CopyFrom(const Frame_Box& from) { -// @@protoc_insertion_point(class_specific_copy_from_start:libopenshotobjdetect.Frame.Box) - if (&from == this) return; - Clear(); - MergeFrom(from); -} - -bool Frame_Box::IsInitialized() const { - return true; -} - -void Frame_Box::InternalSwap(Frame_Box* other) { - using std::swap; - _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); - ::PROTOBUF_NAMESPACE_ID::internal::memswap< - PROTOBUF_FIELD_OFFSET(Frame_Box, confidence_) - + sizeof(Frame_Box::confidence_) - - PROTOBUF_FIELD_OFFSET(Frame_Box, x_)>( - reinterpret_cast(&x_), - reinterpret_cast(&other->x_)); -} - -::PROTOBUF_NAMESPACE_ID::Metadata Frame_Box::GetMetadata() const { - return GetMetadataStatic(); -} - - -// =================================================================== - -void Frame::InitAsDefaultInstance() { -} -class Frame::_Internal { - public: -}; - -Frame::Frame(::PROTOBUF_NAMESPACE_ID::Arena* arena) - : ::PROTOBUF_NAMESPACE_ID::Message(arena), - bounding_box_(arena) { - SharedCtor(); - RegisterArenaDtor(arena); - // @@protoc_insertion_point(arena_constructor:libopenshotobjdetect.Frame) -} -Frame::Frame(const Frame& from) - : ::PROTOBUF_NAMESPACE_ID::Message(), - bounding_box_(from.bounding_box_) { - _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); - id_ = from.id_; - // @@protoc_insertion_point(copy_constructor:libopenshotobjdetect.Frame) -} - -void Frame::SharedCtor() { - ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_Frame_objdetectdata_2eproto.base); - id_ = 0; -} - -Frame::~Frame() { - // @@protoc_insertion_point(destructor:libopenshotobjdetect.Frame) - SharedDtor(); - _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); -} - -void Frame::SharedDtor() { - GOOGLE_DCHECK(GetArena() == nullptr); -} - -void Frame::ArenaDtor(void* object) { - Frame* _this = reinterpret_cast< Frame* >(object); - (void)_this; -} -void Frame::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { -} -void Frame::SetCachedSize(int size) const { - _cached_size_.Set(size); -} -const Frame& Frame::default_instance() { - ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Frame_objdetectdata_2eproto.base); - return *internal_default_instance(); -} - - -void Frame::Clear() { -// @@protoc_insertion_point(message_clear_start:libopenshotobjdetect.Frame) - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void) cached_has_bits; - - bounding_box_.Clear(); - id_ = 0; - _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); -} - -const char* Frame::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { -#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure - ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena; - while (!ctx->Done(&ptr)) { - ::PROTOBUF_NAMESPACE_ID::uint32 tag; - ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); - CHK_(ptr); - switch (tag >> 3) { - // int32 id = 1; - case 1: - if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { - id_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); - CHK_(ptr); - } else goto handle_unusual; - continue; - // repeated .libopenshotobjdetect.Frame.Box bounding_box = 2; - case 2: - if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 18)) { - ptr -= 1; - do { - ptr += 1; - ptr = ctx->ParseMessage(_internal_add_bounding_box(), ptr); - CHK_(ptr); - if (!ctx->DataAvailable(ptr)) break; - } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<18>(ptr)); - } else goto handle_unusual; - continue; - default: { - handle_unusual: - if ((tag & 7) == 4 || tag == 0) { - ctx->SetLastTag(tag); - goto success; - } - ptr = UnknownFieldParse(tag, - _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), - ptr, ctx); - CHK_(ptr != nullptr); - continue; - } - } // switch - } // while -success: - return ptr; -failure: - ptr = nullptr; - goto success; -#undef CHK_ -} - -::PROTOBUF_NAMESPACE_ID::uint8* Frame::_InternalSerialize( - ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:libopenshotobjdetect.Frame) - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - // int32 id = 1; - if (this->id() != 0) { - target = stream->EnsureSpace(target); - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(1, this->_internal_id(), target); - } - - // repeated .libopenshotobjdetect.Frame.Box bounding_box = 2; - for (unsigned int i = 0, - n = static_cast(this->_internal_bounding_box_size()); i < n; i++) { - target = stream->EnsureSpace(target); - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: - InternalWriteMessage(2, this->_internal_bounding_box(i), target, stream); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:libopenshotobjdetect.Frame) - return target; -} - -size_t Frame::ByteSizeLong() const { -// @@protoc_insertion_point(message_byte_size_start:libopenshotobjdetect.Frame) - size_t total_size = 0; - - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void) cached_has_bits; - - // repeated .libopenshotobjdetect.Frame.Box bounding_box = 2; - total_size += 1UL * this->_internal_bounding_box_size(); - for (const auto& msg : this->bounding_box_) { - total_size += - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); - } - - // int32 id = 1; - if (this->id() != 0) { - total_size += 1 + - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( - this->_internal_id()); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( - _internal_metadata_, total_size, &_cached_size_); - } - int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); - SetCachedSize(cached_size); - return total_size; -} - -void Frame::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { -// @@protoc_insertion_point(generalized_merge_from_start:libopenshotobjdetect.Frame) - GOOGLE_DCHECK_NE(&from, this); - const Frame* source = - ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( - &from); - if (source == nullptr) { - // @@protoc_insertion_point(generalized_merge_from_cast_fail:libopenshotobjdetect.Frame) - ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); - } else { - // @@protoc_insertion_point(generalized_merge_from_cast_success:libopenshotobjdetect.Frame) - MergeFrom(*source); - } -} - -void Frame::MergeFrom(const Frame& from) { -// @@protoc_insertion_point(class_specific_merge_from_start:libopenshotobjdetect.Frame) - GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - bounding_box_.MergeFrom(from.bounding_box_); - if (from.id() != 0) { - _internal_set_id(from._internal_id()); - } -} - -void Frame::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { -// @@protoc_insertion_point(generalized_copy_from_start:libopenshotobjdetect.Frame) - if (&from == this) return; - Clear(); - MergeFrom(from); -} - -void Frame::CopyFrom(const Frame& from) { -// @@protoc_insertion_point(class_specific_copy_from_start:libopenshotobjdetect.Frame) - if (&from == this) return; - Clear(); - MergeFrom(from); -} - -bool Frame::IsInitialized() const { - return true; -} - -void Frame::InternalSwap(Frame* other) { - using std::swap; - _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); - bounding_box_.InternalSwap(&other->bounding_box_); - swap(id_, other->id_); -} - -::PROTOBUF_NAMESPACE_ID::Metadata Frame::GetMetadata() const { - return GetMetadataStatic(); -} - - -// =================================================================== - -void ObjDetect::InitAsDefaultInstance() { - ::libopenshotobjdetect::_ObjDetect_default_instance_._instance.get_mutable()->last_updated_ = const_cast< PROTOBUF_NAMESPACE_ID::Timestamp*>( - PROTOBUF_NAMESPACE_ID::Timestamp::internal_default_instance()); -} -class ObjDetect::_Internal { - public: - static const PROTOBUF_NAMESPACE_ID::Timestamp& last_updated(const ObjDetect* msg); -}; - -const PROTOBUF_NAMESPACE_ID::Timestamp& -ObjDetect::_Internal::last_updated(const ObjDetect* msg) { - return *msg->last_updated_; -} -void ObjDetect::clear_last_updated() { - if (GetArena() == nullptr && last_updated_ != nullptr) { - delete last_updated_; - } - last_updated_ = nullptr; -} -ObjDetect::ObjDetect(::PROTOBUF_NAMESPACE_ID::Arena* arena) - : ::PROTOBUF_NAMESPACE_ID::Message(arena), - frame_(arena), - classnames_(arena) { - SharedCtor(); - RegisterArenaDtor(arena); - // @@protoc_insertion_point(arena_constructor:libopenshotobjdetect.ObjDetect) -} -ObjDetect::ObjDetect(const ObjDetect& from) - : ::PROTOBUF_NAMESPACE_ID::Message(), - frame_(from.frame_), - classnames_(from.classnames_) { - _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); - if (from._internal_has_last_updated()) { - last_updated_ = new PROTOBUF_NAMESPACE_ID::Timestamp(*from.last_updated_); - } else { - last_updated_ = nullptr; - } - // @@protoc_insertion_point(copy_constructor:libopenshotobjdetect.ObjDetect) -} - -void ObjDetect::SharedCtor() { - ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_ObjDetect_objdetectdata_2eproto.base); - last_updated_ = nullptr; -} - -ObjDetect::~ObjDetect() { - // @@protoc_insertion_point(destructor:libopenshotobjdetect.ObjDetect) - SharedDtor(); - _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); -} - -void ObjDetect::SharedDtor() { - GOOGLE_DCHECK(GetArena() == nullptr); - if (this != internal_default_instance()) delete last_updated_; -} - -void ObjDetect::ArenaDtor(void* object) { - ObjDetect* _this = reinterpret_cast< ObjDetect* >(object); - (void)_this; -} -void ObjDetect::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { -} -void ObjDetect::SetCachedSize(int size) const { - _cached_size_.Set(size); -} -const ObjDetect& ObjDetect::default_instance() { - ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_ObjDetect_objdetectdata_2eproto.base); - return *internal_default_instance(); -} - - -void ObjDetect::Clear() { -// @@protoc_insertion_point(message_clear_start:libopenshotobjdetect.ObjDetect) - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void) cached_has_bits; - - frame_.Clear(); - classnames_.Clear(); - if (GetArena() == nullptr && last_updated_ != nullptr) { - delete last_updated_; - } - last_updated_ = nullptr; - _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); -} - -const char* ObjDetect::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { -#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure - ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena; - while (!ctx->Done(&ptr)) { - ::PROTOBUF_NAMESPACE_ID::uint32 tag; - ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); - CHK_(ptr); - switch (tag >> 3) { - // repeated .libopenshotobjdetect.Frame frame = 1; - case 1: - if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) { - ptr -= 1; - do { - ptr += 1; - ptr = ctx->ParseMessage(_internal_add_frame(), ptr); - CHK_(ptr); - if (!ctx->DataAvailable(ptr)) break; - } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<10>(ptr)); - } else goto handle_unusual; - continue; - // .google.protobuf.Timestamp last_updated = 2; - case 2: - if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 18)) { - ptr = ctx->ParseMessage(_internal_mutable_last_updated(), ptr); - CHK_(ptr); - } else goto handle_unusual; - continue; - // repeated string classNames = 3; - case 3: - if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 26)) { - ptr -= 1; - do { - ptr += 1; - auto str = _internal_add_classnames(); - ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); - CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "libopenshotobjdetect.ObjDetect.classNames")); - CHK_(ptr); - if (!ctx->DataAvailable(ptr)) break; - } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<26>(ptr)); - } else goto handle_unusual; - continue; - default: { - handle_unusual: - if ((tag & 7) == 4 || tag == 0) { - ctx->SetLastTag(tag); - goto success; - } - ptr = UnknownFieldParse(tag, - _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), - ptr, ctx); - CHK_(ptr != nullptr); - continue; - } - } // switch - } // while -success: - return ptr; -failure: - ptr = nullptr; - goto success; -#undef CHK_ -} - -::PROTOBUF_NAMESPACE_ID::uint8* ObjDetect::_InternalSerialize( - ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:libopenshotobjdetect.ObjDetect) - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - // repeated .libopenshotobjdetect.Frame frame = 1; - for (unsigned int i = 0, - n = static_cast(this->_internal_frame_size()); i < n; i++) { - target = stream->EnsureSpace(target); - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: - InternalWriteMessage(1, this->_internal_frame(i), target, stream); - } - - // .google.protobuf.Timestamp last_updated = 2; - if (this->has_last_updated()) { - target = stream->EnsureSpace(target); - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: - InternalWriteMessage( - 2, _Internal::last_updated(this), target, stream); - } - - // repeated string classNames = 3; - for (int i = 0, n = this->_internal_classnames_size(); i < n; i++) { - const auto& s = this->_internal_classnames(i); - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( - s.data(), static_cast(s.length()), - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, - "libopenshotobjdetect.ObjDetect.classNames"); - target = stream->WriteString(3, s, target); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:libopenshotobjdetect.ObjDetect) - return target; -} - -size_t ObjDetect::ByteSizeLong() const { -// @@protoc_insertion_point(message_byte_size_start:libopenshotobjdetect.ObjDetect) - size_t total_size = 0; - - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void) cached_has_bits; - - // repeated .libopenshotobjdetect.Frame frame = 1; - total_size += 1UL * this->_internal_frame_size(); - for (const auto& msg : this->frame_) { - total_size += - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); - } - - // repeated string classNames = 3; - total_size += 1 * - ::PROTOBUF_NAMESPACE_ID::internal::FromIntSize(classnames_.size()); - for (int i = 0, n = classnames_.size(); i < n; i++) { - total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( - classnames_.Get(i)); - } - - // .google.protobuf.Timestamp last_updated = 2; - if (this->has_last_updated()) { - total_size += 1 + - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( - *last_updated_); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( - _internal_metadata_, total_size, &_cached_size_); - } - int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); - SetCachedSize(cached_size); - return total_size; -} - -void ObjDetect::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { -// @@protoc_insertion_point(generalized_merge_from_start:libopenshotobjdetect.ObjDetect) - GOOGLE_DCHECK_NE(&from, this); - const ObjDetect* source = - ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( - &from); - if (source == nullptr) { - // @@protoc_insertion_point(generalized_merge_from_cast_fail:libopenshotobjdetect.ObjDetect) - ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); - } else { - // @@protoc_insertion_point(generalized_merge_from_cast_success:libopenshotobjdetect.ObjDetect) - MergeFrom(*source); - } -} - -void ObjDetect::MergeFrom(const ObjDetect& from) { -// @@protoc_insertion_point(class_specific_merge_from_start:libopenshotobjdetect.ObjDetect) - GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - frame_.MergeFrom(from.frame_); - classnames_.MergeFrom(from.classnames_); - if (from.has_last_updated()) { - _internal_mutable_last_updated()->PROTOBUF_NAMESPACE_ID::Timestamp::MergeFrom(from._internal_last_updated()); - } -} - -void ObjDetect::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { -// @@protoc_insertion_point(generalized_copy_from_start:libopenshotobjdetect.ObjDetect) - if (&from == this) return; - Clear(); - MergeFrom(from); -} - -void ObjDetect::CopyFrom(const ObjDetect& from) { -// @@protoc_insertion_point(class_specific_copy_from_start:libopenshotobjdetect.ObjDetect) - if (&from == this) return; - Clear(); - MergeFrom(from); -} - -bool ObjDetect::IsInitialized() const { - return true; -} - -void ObjDetect::InternalSwap(ObjDetect* other) { - using std::swap; - _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); - frame_.InternalSwap(&other->frame_); - classnames_.InternalSwap(&other->classnames_); - swap(last_updated_, other->last_updated_); -} - -::PROTOBUF_NAMESPACE_ID::Metadata ObjDetect::GetMetadata() const { - return GetMetadataStatic(); -} - - -// @@protoc_insertion_point(namespace_scope) -} // namespace libopenshotobjdetect -PROTOBUF_NAMESPACE_OPEN -template<> PROTOBUF_NOINLINE ::libopenshotobjdetect::Frame_Box* Arena::CreateMaybeMessage< ::libopenshotobjdetect::Frame_Box >(Arena* arena) { - return Arena::CreateMessageInternal< ::libopenshotobjdetect::Frame_Box >(arena); -} -template<> PROTOBUF_NOINLINE ::libopenshotobjdetect::Frame* Arena::CreateMaybeMessage< ::libopenshotobjdetect::Frame >(Arena* arena) { - return Arena::CreateMessageInternal< ::libopenshotobjdetect::Frame >(arena); -} -template<> PROTOBUF_NOINLINE ::libopenshotobjdetect::ObjDetect* Arena::CreateMaybeMessage< ::libopenshotobjdetect::ObjDetect >(Arena* arena) { - return Arena::CreateMessageInternal< ::libopenshotobjdetect::ObjDetect >(arena); -} -PROTOBUF_NAMESPACE_CLOSE - -// @@protoc_insertion_point(global_scope) -#include diff --git a/src/objdetectdata.pb.h b/src/objdetectdata.pb.h deleted file mode 100644 index 48630c17a..000000000 --- a/src/objdetectdata.pb.h +++ /dev/null @@ -1,1020 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: objdetectdata.proto - -#ifndef GOOGLE_PROTOBUF_INCLUDED_objdetectdata_2eproto -#define GOOGLE_PROTOBUF_INCLUDED_objdetectdata_2eproto - -#include -#include - -#include -#if PROTOBUF_VERSION < 3012000 -#error This file was generated by a newer version of protoc which is -#error incompatible with your Protocol Buffer headers. Please update -#error your headers. -#endif -#if 3012003 < PROTOBUF_MIN_PROTOC_VERSION -#error This file was generated by an older version of protoc which is -#error incompatible with your Protocol Buffer headers. Please -#error regenerate this file with a newer version of protoc. -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include // IWYU pragma: export -#include // IWYU pragma: export -#include -#include -// @@protoc_insertion_point(includes) -#include -#define PROTOBUF_INTERNAL_EXPORT_objdetectdata_2eproto -PROTOBUF_NAMESPACE_OPEN -namespace internal { -class AnyMetadata; -} // namespace internal -PROTOBUF_NAMESPACE_CLOSE - -// Internal implementation detail -- do not use these members. -struct TableStruct_objdetectdata_2eproto { - static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[] - PROTOBUF_SECTION_VARIABLE(protodesc_cold); - static const ::PROTOBUF_NAMESPACE_ID::internal::AuxillaryParseTableField aux[] - PROTOBUF_SECTION_VARIABLE(protodesc_cold); - static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[3] - PROTOBUF_SECTION_VARIABLE(protodesc_cold); - static const ::PROTOBUF_NAMESPACE_ID::internal::FieldMetadata field_metadata[]; - static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[]; - static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[]; -}; -extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_objdetectdata_2eproto; -namespace libopenshotobjdetect { -class Frame; -class FrameDefaultTypeInternal; -extern FrameDefaultTypeInternal _Frame_default_instance_; -class Frame_Box; -class Frame_BoxDefaultTypeInternal; -extern Frame_BoxDefaultTypeInternal _Frame_Box_default_instance_; -class ObjDetect; -class ObjDetectDefaultTypeInternal; -extern ObjDetectDefaultTypeInternal _ObjDetect_default_instance_; -} // namespace libopenshotobjdetect -PROTOBUF_NAMESPACE_OPEN -template<> ::libopenshotobjdetect::Frame* Arena::CreateMaybeMessage<::libopenshotobjdetect::Frame>(Arena*); -template<> ::libopenshotobjdetect::Frame_Box* Arena::CreateMaybeMessage<::libopenshotobjdetect::Frame_Box>(Arena*); -template<> ::libopenshotobjdetect::ObjDetect* Arena::CreateMaybeMessage<::libopenshotobjdetect::ObjDetect>(Arena*); -PROTOBUF_NAMESPACE_CLOSE -namespace libopenshotobjdetect { - -// =================================================================== - -class Frame_Box PROTOBUF_FINAL : - public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:libopenshotobjdetect.Frame.Box) */ { - public: - inline Frame_Box() : Frame_Box(nullptr) {}; - virtual ~Frame_Box(); - - Frame_Box(const Frame_Box& from); - Frame_Box(Frame_Box&& from) noexcept - : Frame_Box() { - *this = ::std::move(from); - } - - inline Frame_Box& operator=(const Frame_Box& from) { - CopyFrom(from); - return *this; - } - inline Frame_Box& operator=(Frame_Box&& from) noexcept { - if (GetArena() == from.GetArena()) { - if (this != &from) InternalSwap(&from); - } else { - CopyFrom(from); - } - return *this; - } - - static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { - return GetDescriptor(); - } - static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { - return GetMetadataStatic().descriptor; - } - static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { - return GetMetadataStatic().reflection; - } - static const Frame_Box& default_instance(); - - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY - static inline const Frame_Box* internal_default_instance() { - return reinterpret_cast( - &_Frame_Box_default_instance_); - } - static constexpr int kIndexInFileMessages = - 0; - - friend void swap(Frame_Box& a, Frame_Box& b) { - a.Swap(&b); - } - inline void Swap(Frame_Box* other) { - if (other == this) return; - if (GetArena() == other->GetArena()) { - InternalSwap(other); - } else { - ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); - } - } - void UnsafeArenaSwap(Frame_Box* other) { - if (other == this) return; - GOOGLE_DCHECK(GetArena() == other->GetArena()); - InternalSwap(other); - } - - // implements Message ---------------------------------------------- - - inline Frame_Box* New() const final { - return CreateMaybeMessage(nullptr); - } - - Frame_Box* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { - return CreateMaybeMessage(arena); - } - void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; - void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; - void CopyFrom(const Frame_Box& from); - void MergeFrom(const Frame_Box& from); - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; - bool IsInitialized() const final; - - size_t ByteSizeLong() const final; - const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; - ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( - ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; - int GetCachedSize() const final { return _cached_size_.Get(); } - - private: - inline void SharedCtor(); - inline void SharedDtor(); - void SetCachedSize(int size) const final; - void InternalSwap(Frame_Box* other); - friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; - static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { - return "libopenshotobjdetect.Frame.Box"; - } - protected: - explicit Frame_Box(::PROTOBUF_NAMESPACE_ID::Arena* arena); - private: - static void ArenaDtor(void* object); - inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); - public: - - ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; - private: - static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { - ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_objdetectdata_2eproto); - return ::descriptor_table_objdetectdata_2eproto.file_level_metadata[kIndexInFileMessages]; - } - - public: - - // nested types ---------------------------------------------------- - - // accessors ------------------------------------------------------- - - enum : int { - kXFieldNumber = 1, - kYFieldNumber = 2, - kWFieldNumber = 3, - kHFieldNumber = 4, - kClassIdFieldNumber = 5, - kConfidenceFieldNumber = 6, - }; - // float x = 1; - void clear_x(); - float x() const; - void set_x(float value); - private: - float _internal_x() const; - void _internal_set_x(float value); - public: - - // float y = 2; - void clear_y(); - float y() const; - void set_y(float value); - private: - float _internal_y() const; - void _internal_set_y(float value); - public: - - // float w = 3; - void clear_w(); - float w() const; - void set_w(float value); - private: - float _internal_w() const; - void _internal_set_w(float value); - public: - - // float h = 4; - void clear_h(); - float h() const; - void set_h(float value); - private: - float _internal_h() const; - void _internal_set_h(float value); - public: - - // int32 classId = 5; - void clear_classid(); - ::PROTOBUF_NAMESPACE_ID::int32 classid() const; - void set_classid(::PROTOBUF_NAMESPACE_ID::int32 value); - private: - ::PROTOBUF_NAMESPACE_ID::int32 _internal_classid() const; - void _internal_set_classid(::PROTOBUF_NAMESPACE_ID::int32 value); - public: - - // float confidence = 6; - void clear_confidence(); - float confidence() const; - void set_confidence(float value); - private: - float _internal_confidence() const; - void _internal_set_confidence(float value); - public: - - // @@protoc_insertion_point(class_scope:libopenshotobjdetect.Frame.Box) - private: - class _Internal; - - template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; - typedef void InternalArenaConstructable_; - typedef void DestructorSkippable_; - float x_; - float y_; - float w_; - float h_; - ::PROTOBUF_NAMESPACE_ID::int32 classid_; - float confidence_; - mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; - friend struct ::TableStruct_objdetectdata_2eproto; -}; -// ------------------------------------------------------------------- - -class Frame PROTOBUF_FINAL : - public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:libopenshotobjdetect.Frame) */ { - public: - inline Frame() : Frame(nullptr) {}; - virtual ~Frame(); - - Frame(const Frame& from); - Frame(Frame&& from) noexcept - : Frame() { - *this = ::std::move(from); - } - - inline Frame& operator=(const Frame& from) { - CopyFrom(from); - return *this; - } - inline Frame& operator=(Frame&& from) noexcept { - if (GetArena() == from.GetArena()) { - if (this != &from) InternalSwap(&from); - } else { - CopyFrom(from); - } - return *this; - } - - static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { - return GetDescriptor(); - } - static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { - return GetMetadataStatic().descriptor; - } - static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { - return GetMetadataStatic().reflection; - } - static const Frame& default_instance(); - - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY - static inline const Frame* internal_default_instance() { - return reinterpret_cast( - &_Frame_default_instance_); - } - static constexpr int kIndexInFileMessages = - 1; - - friend void swap(Frame& a, Frame& b) { - a.Swap(&b); - } - inline void Swap(Frame* other) { - if (other == this) return; - if (GetArena() == other->GetArena()) { - InternalSwap(other); - } else { - ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); - } - } - void UnsafeArenaSwap(Frame* other) { - if (other == this) return; - GOOGLE_DCHECK(GetArena() == other->GetArena()); - InternalSwap(other); - } - - // implements Message ---------------------------------------------- - - inline Frame* New() const final { - return CreateMaybeMessage(nullptr); - } - - Frame* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { - return CreateMaybeMessage(arena); - } - void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; - void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; - void CopyFrom(const Frame& from); - void MergeFrom(const Frame& from); - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; - bool IsInitialized() const final; - - size_t ByteSizeLong() const final; - const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; - ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( - ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; - int GetCachedSize() const final { return _cached_size_.Get(); } - - private: - inline void SharedCtor(); - inline void SharedDtor(); - void SetCachedSize(int size) const final; - void InternalSwap(Frame* other); - friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; - static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { - return "libopenshotobjdetect.Frame"; - } - protected: - explicit Frame(::PROTOBUF_NAMESPACE_ID::Arena* arena); - private: - static void ArenaDtor(void* object); - inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); - public: - - ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; - private: - static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { - ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_objdetectdata_2eproto); - return ::descriptor_table_objdetectdata_2eproto.file_level_metadata[kIndexInFileMessages]; - } - - public: - - // nested types ---------------------------------------------------- - - typedef Frame_Box Box; - - // accessors ------------------------------------------------------- - - enum : int { - kBoundingBoxFieldNumber = 2, - kIdFieldNumber = 1, - }; - // repeated .libopenshotobjdetect.Frame.Box bounding_box = 2; - int bounding_box_size() const; - private: - int _internal_bounding_box_size() const; - public: - void clear_bounding_box(); - ::libopenshotobjdetect::Frame_Box* mutable_bounding_box(int index); - ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::libopenshotobjdetect::Frame_Box >* - mutable_bounding_box(); - private: - const ::libopenshotobjdetect::Frame_Box& _internal_bounding_box(int index) const; - ::libopenshotobjdetect::Frame_Box* _internal_add_bounding_box(); - public: - const ::libopenshotobjdetect::Frame_Box& bounding_box(int index) const; - ::libopenshotobjdetect::Frame_Box* add_bounding_box(); - const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::libopenshotobjdetect::Frame_Box >& - bounding_box() const; - - // int32 id = 1; - void clear_id(); - ::PROTOBUF_NAMESPACE_ID::int32 id() const; - void set_id(::PROTOBUF_NAMESPACE_ID::int32 value); - private: - ::PROTOBUF_NAMESPACE_ID::int32 _internal_id() const; - void _internal_set_id(::PROTOBUF_NAMESPACE_ID::int32 value); - public: - - // @@protoc_insertion_point(class_scope:libopenshotobjdetect.Frame) - private: - class _Internal; - - template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; - typedef void InternalArenaConstructable_; - typedef void DestructorSkippable_; - ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::libopenshotobjdetect::Frame_Box > bounding_box_; - ::PROTOBUF_NAMESPACE_ID::int32 id_; - mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; - friend struct ::TableStruct_objdetectdata_2eproto; -}; -// ------------------------------------------------------------------- - -class ObjDetect PROTOBUF_FINAL : - public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:libopenshotobjdetect.ObjDetect) */ { - public: - inline ObjDetect() : ObjDetect(nullptr) {}; - virtual ~ObjDetect(); - - ObjDetect(const ObjDetect& from); - ObjDetect(ObjDetect&& from) noexcept - : ObjDetect() { - *this = ::std::move(from); - } - - inline ObjDetect& operator=(const ObjDetect& from) { - CopyFrom(from); - return *this; - } - inline ObjDetect& operator=(ObjDetect&& from) noexcept { - if (GetArena() == from.GetArena()) { - if (this != &from) InternalSwap(&from); - } else { - CopyFrom(from); - } - return *this; - } - - static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { - return GetDescriptor(); - } - static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { - return GetMetadataStatic().descriptor; - } - static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { - return GetMetadataStatic().reflection; - } - static const ObjDetect& default_instance(); - - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY - static inline const ObjDetect* internal_default_instance() { - return reinterpret_cast( - &_ObjDetect_default_instance_); - } - static constexpr int kIndexInFileMessages = - 2; - - friend void swap(ObjDetect& a, ObjDetect& b) { - a.Swap(&b); - } - inline void Swap(ObjDetect* other) { - if (other == this) return; - if (GetArena() == other->GetArena()) { - InternalSwap(other); - } else { - ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); - } - } - void UnsafeArenaSwap(ObjDetect* other) { - if (other == this) return; - GOOGLE_DCHECK(GetArena() == other->GetArena()); - InternalSwap(other); - } - - // implements Message ---------------------------------------------- - - inline ObjDetect* New() const final { - return CreateMaybeMessage(nullptr); - } - - ObjDetect* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { - return CreateMaybeMessage(arena); - } - void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; - void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; - void CopyFrom(const ObjDetect& from); - void MergeFrom(const ObjDetect& from); - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; - bool IsInitialized() const final; - - size_t ByteSizeLong() const final; - const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; - ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( - ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; - int GetCachedSize() const final { return _cached_size_.Get(); } - - private: - inline void SharedCtor(); - inline void SharedDtor(); - void SetCachedSize(int size) const final; - void InternalSwap(ObjDetect* other); - friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; - static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { - return "libopenshotobjdetect.ObjDetect"; - } - protected: - explicit ObjDetect(::PROTOBUF_NAMESPACE_ID::Arena* arena); - private: - static void ArenaDtor(void* object); - inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); - public: - - ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; - private: - static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { - ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_objdetectdata_2eproto); - return ::descriptor_table_objdetectdata_2eproto.file_level_metadata[kIndexInFileMessages]; - } - - public: - - // nested types ---------------------------------------------------- - - // accessors ------------------------------------------------------- - - enum : int { - kFrameFieldNumber = 1, - kClassNamesFieldNumber = 3, - kLastUpdatedFieldNumber = 2, - }; - // repeated .libopenshotobjdetect.Frame frame = 1; - int frame_size() const; - private: - int _internal_frame_size() const; - public: - void clear_frame(); - ::libopenshotobjdetect::Frame* mutable_frame(int index); - ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::libopenshotobjdetect::Frame >* - mutable_frame(); - private: - const ::libopenshotobjdetect::Frame& _internal_frame(int index) const; - ::libopenshotobjdetect::Frame* _internal_add_frame(); - public: - const ::libopenshotobjdetect::Frame& frame(int index) const; - ::libopenshotobjdetect::Frame* add_frame(); - const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::libopenshotobjdetect::Frame >& - frame() const; - - // repeated string classNames = 3; - int classnames_size() const; - private: - int _internal_classnames_size() const; - public: - void clear_classnames(); - const std::string& classnames(int index) const; - std::string* mutable_classnames(int index); - void set_classnames(int index, const std::string& value); - void set_classnames(int index, std::string&& value); - void set_classnames(int index, const char* value); - void set_classnames(int index, const char* value, size_t size); - std::string* add_classnames(); - void add_classnames(const std::string& value); - void add_classnames(std::string&& value); - void add_classnames(const char* value); - void add_classnames(const char* value, size_t size); - const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField& classnames() const; - ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField* mutable_classnames(); - private: - const std::string& _internal_classnames(int index) const; - std::string* _internal_add_classnames(); - public: - - // .google.protobuf.Timestamp last_updated = 2; - bool has_last_updated() const; - private: - bool _internal_has_last_updated() const; - public: - void clear_last_updated(); - const PROTOBUF_NAMESPACE_ID::Timestamp& last_updated() const; - PROTOBUF_NAMESPACE_ID::Timestamp* release_last_updated(); - PROTOBUF_NAMESPACE_ID::Timestamp* mutable_last_updated(); - void set_allocated_last_updated(PROTOBUF_NAMESPACE_ID::Timestamp* last_updated); - private: - const PROTOBUF_NAMESPACE_ID::Timestamp& _internal_last_updated() const; - PROTOBUF_NAMESPACE_ID::Timestamp* _internal_mutable_last_updated(); - public: - void unsafe_arena_set_allocated_last_updated( - PROTOBUF_NAMESPACE_ID::Timestamp* last_updated); - PROTOBUF_NAMESPACE_ID::Timestamp* unsafe_arena_release_last_updated(); - - // @@protoc_insertion_point(class_scope:libopenshotobjdetect.ObjDetect) - private: - class _Internal; - - template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; - typedef void InternalArenaConstructable_; - typedef void DestructorSkippable_; - ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::libopenshotobjdetect::Frame > frame_; - ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField classnames_; - PROTOBUF_NAMESPACE_ID::Timestamp* last_updated_; - mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; - friend struct ::TableStruct_objdetectdata_2eproto; -}; -// =================================================================== - - -// =================================================================== - -#ifdef __GNUC__ - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wstrict-aliasing" -#endif // __GNUC__ -// Frame_Box - -// float x = 1; -inline void Frame_Box::clear_x() { - x_ = 0; -} -inline float Frame_Box::_internal_x() const { - return x_; -} -inline float Frame_Box::x() const { - // @@protoc_insertion_point(field_get:libopenshotobjdetect.Frame.Box.x) - return _internal_x(); -} -inline void Frame_Box::_internal_set_x(float value) { - - x_ = value; -} -inline void Frame_Box::set_x(float value) { - _internal_set_x(value); - // @@protoc_insertion_point(field_set:libopenshotobjdetect.Frame.Box.x) -} - -// float y = 2; -inline void Frame_Box::clear_y() { - y_ = 0; -} -inline float Frame_Box::_internal_y() const { - return y_; -} -inline float Frame_Box::y() const { - // @@protoc_insertion_point(field_get:libopenshotobjdetect.Frame.Box.y) - return _internal_y(); -} -inline void Frame_Box::_internal_set_y(float value) { - - y_ = value; -} -inline void Frame_Box::set_y(float value) { - _internal_set_y(value); - // @@protoc_insertion_point(field_set:libopenshotobjdetect.Frame.Box.y) -} - -// float w = 3; -inline void Frame_Box::clear_w() { - w_ = 0; -} -inline float Frame_Box::_internal_w() const { - return w_; -} -inline float Frame_Box::w() const { - // @@protoc_insertion_point(field_get:libopenshotobjdetect.Frame.Box.w) - return _internal_w(); -} -inline void Frame_Box::_internal_set_w(float value) { - - w_ = value; -} -inline void Frame_Box::set_w(float value) { - _internal_set_w(value); - // @@protoc_insertion_point(field_set:libopenshotobjdetect.Frame.Box.w) -} - -// float h = 4; -inline void Frame_Box::clear_h() { - h_ = 0; -} -inline float Frame_Box::_internal_h() const { - return h_; -} -inline float Frame_Box::h() const { - // @@protoc_insertion_point(field_get:libopenshotobjdetect.Frame.Box.h) - return _internal_h(); -} -inline void Frame_Box::_internal_set_h(float value) { - - h_ = value; -} -inline void Frame_Box::set_h(float value) { - _internal_set_h(value); - // @@protoc_insertion_point(field_set:libopenshotobjdetect.Frame.Box.h) -} - -// int32 classId = 5; -inline void Frame_Box::clear_classid() { - classid_ = 0; -} -inline ::PROTOBUF_NAMESPACE_ID::int32 Frame_Box::_internal_classid() const { - return classid_; -} -inline ::PROTOBUF_NAMESPACE_ID::int32 Frame_Box::classid() const { - // @@protoc_insertion_point(field_get:libopenshotobjdetect.Frame.Box.classId) - return _internal_classid(); -} -inline void Frame_Box::_internal_set_classid(::PROTOBUF_NAMESPACE_ID::int32 value) { - - classid_ = value; -} -inline void Frame_Box::set_classid(::PROTOBUF_NAMESPACE_ID::int32 value) { - _internal_set_classid(value); - // @@protoc_insertion_point(field_set:libopenshotobjdetect.Frame.Box.classId) -} - -// float confidence = 6; -inline void Frame_Box::clear_confidence() { - confidence_ = 0; -} -inline float Frame_Box::_internal_confidence() const { - return confidence_; -} -inline float Frame_Box::confidence() const { - // @@protoc_insertion_point(field_get:libopenshotobjdetect.Frame.Box.confidence) - return _internal_confidence(); -} -inline void Frame_Box::_internal_set_confidence(float value) { - - confidence_ = value; -} -inline void Frame_Box::set_confidence(float value) { - _internal_set_confidence(value); - // @@protoc_insertion_point(field_set:libopenshotobjdetect.Frame.Box.confidence) -} - -// ------------------------------------------------------------------- - -// Frame - -// int32 id = 1; -inline void Frame::clear_id() { - id_ = 0; -} -inline ::PROTOBUF_NAMESPACE_ID::int32 Frame::_internal_id() const { - return id_; -} -inline ::PROTOBUF_NAMESPACE_ID::int32 Frame::id() const { - // @@protoc_insertion_point(field_get:libopenshotobjdetect.Frame.id) - return _internal_id(); -} -inline void Frame::_internal_set_id(::PROTOBUF_NAMESPACE_ID::int32 value) { - - id_ = value; -} -inline void Frame::set_id(::PROTOBUF_NAMESPACE_ID::int32 value) { - _internal_set_id(value); - // @@protoc_insertion_point(field_set:libopenshotobjdetect.Frame.id) -} - -// repeated .libopenshotobjdetect.Frame.Box bounding_box = 2; -inline int Frame::_internal_bounding_box_size() const { - return bounding_box_.size(); -} -inline int Frame::bounding_box_size() const { - return _internal_bounding_box_size(); -} -inline void Frame::clear_bounding_box() { - bounding_box_.Clear(); -} -inline ::libopenshotobjdetect::Frame_Box* Frame::mutable_bounding_box(int index) { - // @@protoc_insertion_point(field_mutable:libopenshotobjdetect.Frame.bounding_box) - return bounding_box_.Mutable(index); -} -inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::libopenshotobjdetect::Frame_Box >* -Frame::mutable_bounding_box() { - // @@protoc_insertion_point(field_mutable_list:libopenshotobjdetect.Frame.bounding_box) - return &bounding_box_; -} -inline const ::libopenshotobjdetect::Frame_Box& Frame::_internal_bounding_box(int index) const { - return bounding_box_.Get(index); -} -inline const ::libopenshotobjdetect::Frame_Box& Frame::bounding_box(int index) const { - // @@protoc_insertion_point(field_get:libopenshotobjdetect.Frame.bounding_box) - return _internal_bounding_box(index); -} -inline ::libopenshotobjdetect::Frame_Box* Frame::_internal_add_bounding_box() { - return bounding_box_.Add(); -} -inline ::libopenshotobjdetect::Frame_Box* Frame::add_bounding_box() { - // @@protoc_insertion_point(field_add:libopenshotobjdetect.Frame.bounding_box) - return _internal_add_bounding_box(); -} -inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::libopenshotobjdetect::Frame_Box >& -Frame::bounding_box() const { - // @@protoc_insertion_point(field_list:libopenshotobjdetect.Frame.bounding_box) - return bounding_box_; -} - -// ------------------------------------------------------------------- - -// ObjDetect - -// repeated .libopenshotobjdetect.Frame frame = 1; -inline int ObjDetect::_internal_frame_size() const { - return frame_.size(); -} -inline int ObjDetect::frame_size() const { - return _internal_frame_size(); -} -inline void ObjDetect::clear_frame() { - frame_.Clear(); -} -inline ::libopenshotobjdetect::Frame* ObjDetect::mutable_frame(int index) { - // @@protoc_insertion_point(field_mutable:libopenshotobjdetect.ObjDetect.frame) - return frame_.Mutable(index); -} -inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::libopenshotobjdetect::Frame >* -ObjDetect::mutable_frame() { - // @@protoc_insertion_point(field_mutable_list:libopenshotobjdetect.ObjDetect.frame) - return &frame_; -} -inline const ::libopenshotobjdetect::Frame& ObjDetect::_internal_frame(int index) const { - return frame_.Get(index); -} -inline const ::libopenshotobjdetect::Frame& ObjDetect::frame(int index) const { - // @@protoc_insertion_point(field_get:libopenshotobjdetect.ObjDetect.frame) - return _internal_frame(index); -} -inline ::libopenshotobjdetect::Frame* ObjDetect::_internal_add_frame() { - return frame_.Add(); -} -inline ::libopenshotobjdetect::Frame* ObjDetect::add_frame() { - // @@protoc_insertion_point(field_add:libopenshotobjdetect.ObjDetect.frame) - return _internal_add_frame(); -} -inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::libopenshotobjdetect::Frame >& -ObjDetect::frame() const { - // @@protoc_insertion_point(field_list:libopenshotobjdetect.ObjDetect.frame) - return frame_; -} - -// .google.protobuf.Timestamp last_updated = 2; -inline bool ObjDetect::_internal_has_last_updated() const { - return this != internal_default_instance() && last_updated_ != nullptr; -} -inline bool ObjDetect::has_last_updated() const { - return _internal_has_last_updated(); -} -inline const PROTOBUF_NAMESPACE_ID::Timestamp& ObjDetect::_internal_last_updated() const { - const PROTOBUF_NAMESPACE_ID::Timestamp* p = last_updated_; - return p != nullptr ? *p : *reinterpret_cast( - &PROTOBUF_NAMESPACE_ID::_Timestamp_default_instance_); -} -inline const PROTOBUF_NAMESPACE_ID::Timestamp& ObjDetect::last_updated() const { - // @@protoc_insertion_point(field_get:libopenshotobjdetect.ObjDetect.last_updated) - return _internal_last_updated(); -} -inline void ObjDetect::unsafe_arena_set_allocated_last_updated( - PROTOBUF_NAMESPACE_ID::Timestamp* last_updated) { - if (GetArena() == nullptr) { - delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(last_updated_); - } - last_updated_ = last_updated; - if (last_updated) { - - } else { - - } - // @@protoc_insertion_point(field_unsafe_arena_set_allocated:libopenshotobjdetect.ObjDetect.last_updated) -} -inline PROTOBUF_NAMESPACE_ID::Timestamp* ObjDetect::release_last_updated() { - auto temp = unsafe_arena_release_last_updated(); - if (GetArena() != nullptr) { - temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); - } - return temp; -} -inline PROTOBUF_NAMESPACE_ID::Timestamp* ObjDetect::unsafe_arena_release_last_updated() { - // @@protoc_insertion_point(field_release:libopenshotobjdetect.ObjDetect.last_updated) - - PROTOBUF_NAMESPACE_ID::Timestamp* temp = last_updated_; - last_updated_ = nullptr; - return temp; -} -inline PROTOBUF_NAMESPACE_ID::Timestamp* ObjDetect::_internal_mutable_last_updated() { - - if (last_updated_ == nullptr) { - auto* p = CreateMaybeMessage(GetArena()); - last_updated_ = p; - } - return last_updated_; -} -inline PROTOBUF_NAMESPACE_ID::Timestamp* ObjDetect::mutable_last_updated() { - // @@protoc_insertion_point(field_mutable:libopenshotobjdetect.ObjDetect.last_updated) - return _internal_mutable_last_updated(); -} -inline void ObjDetect::set_allocated_last_updated(PROTOBUF_NAMESPACE_ID::Timestamp* last_updated) { - ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArena(); - if (message_arena == nullptr) { - delete reinterpret_cast< ::PROTOBUF_NAMESPACE_ID::MessageLite*>(last_updated_); - } - if (last_updated) { - ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = - reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(last_updated)->GetArena(); - if (message_arena != submessage_arena) { - last_updated = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( - message_arena, last_updated, submessage_arena); - } - - } else { - - } - last_updated_ = last_updated; - // @@protoc_insertion_point(field_set_allocated:libopenshotobjdetect.ObjDetect.last_updated) -} - -// repeated string classNames = 3; -inline int ObjDetect::_internal_classnames_size() const { - return classnames_.size(); -} -inline int ObjDetect::classnames_size() const { - return _internal_classnames_size(); -} -inline void ObjDetect::clear_classnames() { - classnames_.Clear(); -} -inline std::string* ObjDetect::add_classnames() { - // @@protoc_insertion_point(field_add_mutable:libopenshotobjdetect.ObjDetect.classNames) - return _internal_add_classnames(); -} -inline const std::string& ObjDetect::_internal_classnames(int index) const { - return classnames_.Get(index); -} -inline const std::string& ObjDetect::classnames(int index) const { - // @@protoc_insertion_point(field_get:libopenshotobjdetect.ObjDetect.classNames) - return _internal_classnames(index); -} -inline std::string* ObjDetect::mutable_classnames(int index) { - // @@protoc_insertion_point(field_mutable:libopenshotobjdetect.ObjDetect.classNames) - return classnames_.Mutable(index); -} -inline void ObjDetect::set_classnames(int index, const std::string& value) { - // @@protoc_insertion_point(field_set:libopenshotobjdetect.ObjDetect.classNames) - classnames_.Mutable(index)->assign(value); -} -inline void ObjDetect::set_classnames(int index, std::string&& value) { - // @@protoc_insertion_point(field_set:libopenshotobjdetect.ObjDetect.classNames) - classnames_.Mutable(index)->assign(std::move(value)); -} -inline void ObjDetect::set_classnames(int index, const char* value) { - GOOGLE_DCHECK(value != nullptr); - classnames_.Mutable(index)->assign(value); - // @@protoc_insertion_point(field_set_char:libopenshotobjdetect.ObjDetect.classNames) -} -inline void ObjDetect::set_classnames(int index, const char* value, size_t size) { - classnames_.Mutable(index)->assign( - reinterpret_cast(value), size); - // @@protoc_insertion_point(field_set_pointer:libopenshotobjdetect.ObjDetect.classNames) -} -inline std::string* ObjDetect::_internal_add_classnames() { - return classnames_.Add(); -} -inline void ObjDetect::add_classnames(const std::string& value) { - classnames_.Add()->assign(value); - // @@protoc_insertion_point(field_add:libopenshotobjdetect.ObjDetect.classNames) -} -inline void ObjDetect::add_classnames(std::string&& value) { - classnames_.Add(std::move(value)); - // @@protoc_insertion_point(field_add:libopenshotobjdetect.ObjDetect.classNames) -} -inline void ObjDetect::add_classnames(const char* value) { - GOOGLE_DCHECK(value != nullptr); - classnames_.Add()->assign(value); - // @@protoc_insertion_point(field_add_char:libopenshotobjdetect.ObjDetect.classNames) -} -inline void ObjDetect::add_classnames(const char* value, size_t size) { - classnames_.Add()->assign(reinterpret_cast(value), size); - // @@protoc_insertion_point(field_add_pointer:libopenshotobjdetect.ObjDetect.classNames) -} -inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField& -ObjDetect::classnames() const { - // @@protoc_insertion_point(field_list:libopenshotobjdetect.ObjDetect.classNames) - return classnames_; -} -inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField* -ObjDetect::mutable_classnames() { - // @@protoc_insertion_point(field_mutable_list:libopenshotobjdetect.ObjDetect.classNames) - return &classnames_; -} - -#ifdef __GNUC__ - #pragma GCC diagnostic pop -#endif // __GNUC__ -// ------------------------------------------------------------------- - -// ------------------------------------------------------------------- - - -// @@protoc_insertion_point(namespace_scope) - -} // namespace libopenshotobjdetect - -// @@protoc_insertion_point(global_scope) - -#include -#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_objdetectdata_2eproto diff --git a/src/protobuf_messages/CMakeLists.txt b/src/protobuf_messages/CMakeLists.txt new file mode 100644 index 000000000..5752a2160 --- /dev/null +++ b/src/protobuf_messages/CMakeLists.txt @@ -0,0 +1,38 @@ +####################### CMakeLists.txt (libopenshot) ######################### +# @brief CMake build file for libopenshot (used to generate makefiles) +# @author Jonathan Thomas +# @author FeRD (Frank Dana) +# +# @section LICENSE +# +# Copyright (c) 2008-2020 OpenShot Studios, LLC +# . This file is part of +# OpenShot Library (libopenshot), an open-source project dedicated to +# delivering high quality video editing and animation solutions to the +# world. For more information visit . +# +# OpenShot Library (libopenshot) is free software: you can redistribute it +# and/or modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# OpenShot Library (libopenshot) is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with OpenShot Library. If not, see . +################################################################################ + +# Dependencies +find_package(Protobuf 3) + +file(GLOB ProtoFiles "${CMAKE_CURRENT_SOURCE_DIR}/*.proto") +PROTOBUF_GENERATE_CPP(ProtoSources ProtoHeaders ${ProtoFiles}) +add_library(ProtoMessages SHARED ${ProtoSources} ${ProtoHeaders}) + +set(ProtobufMessagePath ${CMAKE_CURRENT_BINARY_DIR} + CACHE INTERNAL "Path to generated protobuf header files.") + +target_link_libraries(ProtoMessages ${Boost_LIBRARIES} ${PROTOBUF_LIBRARY}) diff --git a/src/stabilizedata.pb.cc b/src/stabilizedata.pb.cc deleted file mode 100644 index 081aca108..000000000 --- a/src/stabilizedata.pb.cc +++ /dev/null @@ -1,722 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: stabilizedata.proto - -#include "stabilizedata.pb.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -// @@protoc_insertion_point(includes) -#include -extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2ftimestamp_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Timestamp_google_2fprotobuf_2ftimestamp_2eproto; -extern PROTOBUF_INTERNAL_EXPORT_stabilizedata_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Frame_stabilizedata_2eproto; -namespace libopenshotstabilize { -class FrameDefaultTypeInternal { - public: - ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; -} _Frame_default_instance_; -class StabilizationDefaultTypeInternal { - public: - ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; -} _Stabilization_default_instance_; -} // namespace libopenshotstabilize -static void InitDefaultsscc_info_Frame_stabilizedata_2eproto() { - GOOGLE_PROTOBUF_VERIFY_VERSION; - - { - void* ptr = &::libopenshotstabilize::_Frame_default_instance_; - new (ptr) ::libopenshotstabilize::Frame(); - ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); - } - ::libopenshotstabilize::Frame::InitAsDefaultInstance(); -} - -::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Frame_stabilizedata_2eproto = - {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_Frame_stabilizedata_2eproto}, {}}; - -static void InitDefaultsscc_info_Stabilization_stabilizedata_2eproto() { - GOOGLE_PROTOBUF_VERIFY_VERSION; - - { - void* ptr = &::libopenshotstabilize::_Stabilization_default_instance_; - new (ptr) ::libopenshotstabilize::Stabilization(); - ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); - } - ::libopenshotstabilize::Stabilization::InitAsDefaultInstance(); -} - -::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<2> scc_info_Stabilization_stabilizedata_2eproto = - {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 2, 0, InitDefaultsscc_info_Stabilization_stabilizedata_2eproto}, { - &scc_info_Frame_stabilizedata_2eproto.base, - &scc_info_Timestamp_google_2fprotobuf_2ftimestamp_2eproto.base,}}; - -static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_stabilizedata_2eproto[2]; -static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_stabilizedata_2eproto = nullptr; -static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_stabilizedata_2eproto = nullptr; - -const ::PROTOBUF_NAMESPACE_ID::uint32 TableStruct_stabilizedata_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { - ~0u, // no _has_bits_ - PROTOBUF_FIELD_OFFSET(::libopenshotstabilize::Frame, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - PROTOBUF_FIELD_OFFSET(::libopenshotstabilize::Frame, id_), - PROTOBUF_FIELD_OFFSET(::libopenshotstabilize::Frame, dx_), - PROTOBUF_FIELD_OFFSET(::libopenshotstabilize::Frame, dy_), - PROTOBUF_FIELD_OFFSET(::libopenshotstabilize::Frame, da_), - PROTOBUF_FIELD_OFFSET(::libopenshotstabilize::Frame, x_), - PROTOBUF_FIELD_OFFSET(::libopenshotstabilize::Frame, y_), - PROTOBUF_FIELD_OFFSET(::libopenshotstabilize::Frame, a_), - ~0u, // no _has_bits_ - PROTOBUF_FIELD_OFFSET(::libopenshotstabilize::Stabilization, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - PROTOBUF_FIELD_OFFSET(::libopenshotstabilize::Stabilization, frame_), - PROTOBUF_FIELD_OFFSET(::libopenshotstabilize::Stabilization, last_updated_), -}; -static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { - { 0, -1, sizeof(::libopenshotstabilize::Frame)}, - { 12, -1, sizeof(::libopenshotstabilize::Stabilization)}, -}; - -static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = { - reinterpret_cast(&::libopenshotstabilize::_Frame_default_instance_), - reinterpret_cast(&::libopenshotstabilize::_Stabilization_default_instance_), -}; - -const char descriptor_table_protodef_stabilizedata_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = - "\n\023stabilizedata.proto\022\024libopenshotstabil" - "ize\032\037google/protobuf/timestamp.proto\"X\n\005" - "Frame\022\n\n\002id\030\001 \001(\005\022\n\n\002dx\030\002 \001(\002\022\n\n\002dy\030\003 \001(" - "\002\022\n\n\002da\030\004 \001(\002\022\t\n\001x\030\005 \001(\002\022\t\n\001y\030\006 \001(\002\022\t\n\001a" - "\030\007 \001(\002\"m\n\rStabilization\022*\n\005frame\030\001 \003(\0132\033" - ".libopenshotstabilize.Frame\0220\n\014last_upda" - "ted\030\002 \001(\0132\032.google.protobuf.Timestampb\006p" - "roto3" - ; -static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_stabilizedata_2eproto_deps[1] = { - &::descriptor_table_google_2fprotobuf_2ftimestamp_2eproto, -}; -static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_stabilizedata_2eproto_sccs[2] = { - &scc_info_Frame_stabilizedata_2eproto.base, - &scc_info_Stabilization_stabilizedata_2eproto.base, -}; -static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_stabilizedata_2eproto_once; -const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_stabilizedata_2eproto = { - false, false, descriptor_table_protodef_stabilizedata_2eproto, "stabilizedata.proto", 285, - &descriptor_table_stabilizedata_2eproto_once, descriptor_table_stabilizedata_2eproto_sccs, descriptor_table_stabilizedata_2eproto_deps, 2, 1, - schemas, file_default_instances, TableStruct_stabilizedata_2eproto::offsets, - file_level_metadata_stabilizedata_2eproto, 2, file_level_enum_descriptors_stabilizedata_2eproto, file_level_service_descriptors_stabilizedata_2eproto, -}; - -// Force running AddDescriptors() at dynamic initialization time. -static bool dynamic_init_dummy_stabilizedata_2eproto = (static_cast(::PROTOBUF_NAMESPACE_ID::internal::AddDescriptors(&descriptor_table_stabilizedata_2eproto)), true); -namespace libopenshotstabilize { - -// =================================================================== - -void Frame::InitAsDefaultInstance() { -} -class Frame::_Internal { - public: -}; - -Frame::Frame(::PROTOBUF_NAMESPACE_ID::Arena* arena) - : ::PROTOBUF_NAMESPACE_ID::Message(arena) { - SharedCtor(); - RegisterArenaDtor(arena); - // @@protoc_insertion_point(arena_constructor:libopenshotstabilize.Frame) -} -Frame::Frame(const Frame& from) - : ::PROTOBUF_NAMESPACE_ID::Message() { - _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); - ::memcpy(&id_, &from.id_, - static_cast(reinterpret_cast(&a_) - - reinterpret_cast(&id_)) + sizeof(a_)); - // @@protoc_insertion_point(copy_constructor:libopenshotstabilize.Frame) -} - -void Frame::SharedCtor() { - ::memset(&id_, 0, static_cast( - reinterpret_cast(&a_) - - reinterpret_cast(&id_)) + sizeof(a_)); -} - -Frame::~Frame() { - // @@protoc_insertion_point(destructor:libopenshotstabilize.Frame) - SharedDtor(); - _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); -} - -void Frame::SharedDtor() { - GOOGLE_DCHECK(GetArena() == nullptr); -} - -void Frame::ArenaDtor(void* object) { - Frame* _this = reinterpret_cast< Frame* >(object); - (void)_this; -} -void Frame::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { -} -void Frame::SetCachedSize(int size) const { - _cached_size_.Set(size); -} -const Frame& Frame::default_instance() { - ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Frame_stabilizedata_2eproto.base); - return *internal_default_instance(); -} - - -void Frame::Clear() { -// @@protoc_insertion_point(message_clear_start:libopenshotstabilize.Frame) - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void) cached_has_bits; - - ::memset(&id_, 0, static_cast( - reinterpret_cast(&a_) - - reinterpret_cast(&id_)) + sizeof(a_)); - _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); -} - -const char* Frame::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { -#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure - ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena; - while (!ctx->Done(&ptr)) { - ::PROTOBUF_NAMESPACE_ID::uint32 tag; - ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); - CHK_(ptr); - switch (tag >> 3) { - // int32 id = 1; - case 1: - if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { - id_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); - CHK_(ptr); - } else goto handle_unusual; - continue; - // float dx = 2; - case 2: - if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 21)) { - dx_ = ::PROTOBUF_NAMESPACE_ID::internal::UnalignedLoad(ptr); - ptr += sizeof(float); - } else goto handle_unusual; - continue; - // float dy = 3; - case 3: - if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 29)) { - dy_ = ::PROTOBUF_NAMESPACE_ID::internal::UnalignedLoad(ptr); - ptr += sizeof(float); - } else goto handle_unusual; - continue; - // float da = 4; - case 4: - if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 37)) { - da_ = ::PROTOBUF_NAMESPACE_ID::internal::UnalignedLoad(ptr); - ptr += sizeof(float); - } else goto handle_unusual; - continue; - // float x = 5; - case 5: - if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 45)) { - x_ = ::PROTOBUF_NAMESPACE_ID::internal::UnalignedLoad(ptr); - ptr += sizeof(float); - } else goto handle_unusual; - continue; - // float y = 6; - case 6: - if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 53)) { - y_ = ::PROTOBUF_NAMESPACE_ID::internal::UnalignedLoad(ptr); - ptr += sizeof(float); - } else goto handle_unusual; - continue; - // float a = 7; - case 7: - if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 61)) { - a_ = ::PROTOBUF_NAMESPACE_ID::internal::UnalignedLoad(ptr); - ptr += sizeof(float); - } else goto handle_unusual; - continue; - default: { - handle_unusual: - if ((tag & 7) == 4 || tag == 0) { - ctx->SetLastTag(tag); - goto success; - } - ptr = UnknownFieldParse(tag, - _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), - ptr, ctx); - CHK_(ptr != nullptr); - continue; - } - } // switch - } // while -success: - return ptr; -failure: - ptr = nullptr; - goto success; -#undef CHK_ -} - -::PROTOBUF_NAMESPACE_ID::uint8* Frame::_InternalSerialize( - ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:libopenshotstabilize.Frame) - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - // int32 id = 1; - if (this->id() != 0) { - target = stream->EnsureSpace(target); - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(1, this->_internal_id(), target); - } - - // float dx = 2; - if (!(this->dx() <= 0 && this->dx() >= 0)) { - target = stream->EnsureSpace(target); - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteFloatToArray(2, this->_internal_dx(), target); - } - - // float dy = 3; - if (!(this->dy() <= 0 && this->dy() >= 0)) { - target = stream->EnsureSpace(target); - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteFloatToArray(3, this->_internal_dy(), target); - } - - // float da = 4; - if (!(this->da() <= 0 && this->da() >= 0)) { - target = stream->EnsureSpace(target); - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteFloatToArray(4, this->_internal_da(), target); - } - - // float x = 5; - if (!(this->x() <= 0 && this->x() >= 0)) { - target = stream->EnsureSpace(target); - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteFloatToArray(5, this->_internal_x(), target); - } - - // float y = 6; - if (!(this->y() <= 0 && this->y() >= 0)) { - target = stream->EnsureSpace(target); - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteFloatToArray(6, this->_internal_y(), target); - } - - // float a = 7; - if (!(this->a() <= 0 && this->a() >= 0)) { - target = stream->EnsureSpace(target); - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteFloatToArray(7, this->_internal_a(), target); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:libopenshotstabilize.Frame) - return target; -} - -size_t Frame::ByteSizeLong() const { -// @@protoc_insertion_point(message_byte_size_start:libopenshotstabilize.Frame) - size_t total_size = 0; - - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void) cached_has_bits; - - // int32 id = 1; - if (this->id() != 0) { - total_size += 1 + - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( - this->_internal_id()); - } - - // float dx = 2; - if (!(this->dx() <= 0 && this->dx() >= 0)) { - total_size += 1 + 4; - } - - // float dy = 3; - if (!(this->dy() <= 0 && this->dy() >= 0)) { - total_size += 1 + 4; - } - - // float da = 4; - if (!(this->da() <= 0 && this->da() >= 0)) { - total_size += 1 + 4; - } - - // float x = 5; - if (!(this->x() <= 0 && this->x() >= 0)) { - total_size += 1 + 4; - } - - // float y = 6; - if (!(this->y() <= 0 && this->y() >= 0)) { - total_size += 1 + 4; - } - - // float a = 7; - if (!(this->a() <= 0 && this->a() >= 0)) { - total_size += 1 + 4; - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( - _internal_metadata_, total_size, &_cached_size_); - } - int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); - SetCachedSize(cached_size); - return total_size; -} - -void Frame::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { -// @@protoc_insertion_point(generalized_merge_from_start:libopenshotstabilize.Frame) - GOOGLE_DCHECK_NE(&from, this); - const Frame* source = - ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( - &from); - if (source == nullptr) { - // @@protoc_insertion_point(generalized_merge_from_cast_fail:libopenshotstabilize.Frame) - ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); - } else { - // @@protoc_insertion_point(generalized_merge_from_cast_success:libopenshotstabilize.Frame) - MergeFrom(*source); - } -} - -void Frame::MergeFrom(const Frame& from) { -// @@protoc_insertion_point(class_specific_merge_from_start:libopenshotstabilize.Frame) - GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - if (from.id() != 0) { - _internal_set_id(from._internal_id()); - } - if (!(from.dx() <= 0 && from.dx() >= 0)) { - _internal_set_dx(from._internal_dx()); - } - if (!(from.dy() <= 0 && from.dy() >= 0)) { - _internal_set_dy(from._internal_dy()); - } - if (!(from.da() <= 0 && from.da() >= 0)) { - _internal_set_da(from._internal_da()); - } - if (!(from.x() <= 0 && from.x() >= 0)) { - _internal_set_x(from._internal_x()); - } - if (!(from.y() <= 0 && from.y() >= 0)) { - _internal_set_y(from._internal_y()); - } - if (!(from.a() <= 0 && from.a() >= 0)) { - _internal_set_a(from._internal_a()); - } -} - -void Frame::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { -// @@protoc_insertion_point(generalized_copy_from_start:libopenshotstabilize.Frame) - if (&from == this) return; - Clear(); - MergeFrom(from); -} - -void Frame::CopyFrom(const Frame& from) { -// @@protoc_insertion_point(class_specific_copy_from_start:libopenshotstabilize.Frame) - if (&from == this) return; - Clear(); - MergeFrom(from); -} - -bool Frame::IsInitialized() const { - return true; -} - -void Frame::InternalSwap(Frame* other) { - using std::swap; - _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); - ::PROTOBUF_NAMESPACE_ID::internal::memswap< - PROTOBUF_FIELD_OFFSET(Frame, a_) - + sizeof(Frame::a_) - - PROTOBUF_FIELD_OFFSET(Frame, id_)>( - reinterpret_cast(&id_), - reinterpret_cast(&other->id_)); -} - -::PROTOBUF_NAMESPACE_ID::Metadata Frame::GetMetadata() const { - return GetMetadataStatic(); -} - - -// =================================================================== - -void Stabilization::InitAsDefaultInstance() { - ::libopenshotstabilize::_Stabilization_default_instance_._instance.get_mutable()->last_updated_ = const_cast< PROTOBUF_NAMESPACE_ID::Timestamp*>( - PROTOBUF_NAMESPACE_ID::Timestamp::internal_default_instance()); -} -class Stabilization::_Internal { - public: - static const PROTOBUF_NAMESPACE_ID::Timestamp& last_updated(const Stabilization* msg); -}; - -const PROTOBUF_NAMESPACE_ID::Timestamp& -Stabilization::_Internal::last_updated(const Stabilization* msg) { - return *msg->last_updated_; -} -void Stabilization::clear_last_updated() { - if (GetArena() == nullptr && last_updated_ != nullptr) { - delete last_updated_; - } - last_updated_ = nullptr; -} -Stabilization::Stabilization(::PROTOBUF_NAMESPACE_ID::Arena* arena) - : ::PROTOBUF_NAMESPACE_ID::Message(arena), - frame_(arena) { - SharedCtor(); - RegisterArenaDtor(arena); - // @@protoc_insertion_point(arena_constructor:libopenshotstabilize.Stabilization) -} -Stabilization::Stabilization(const Stabilization& from) - : ::PROTOBUF_NAMESPACE_ID::Message(), - frame_(from.frame_) { - _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); - if (from._internal_has_last_updated()) { - last_updated_ = new PROTOBUF_NAMESPACE_ID::Timestamp(*from.last_updated_); - } else { - last_updated_ = nullptr; - } - // @@protoc_insertion_point(copy_constructor:libopenshotstabilize.Stabilization) -} - -void Stabilization::SharedCtor() { - ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_Stabilization_stabilizedata_2eproto.base); - last_updated_ = nullptr; -} - -Stabilization::~Stabilization() { - // @@protoc_insertion_point(destructor:libopenshotstabilize.Stabilization) - SharedDtor(); - _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); -} - -void Stabilization::SharedDtor() { - GOOGLE_DCHECK(GetArena() == nullptr); - if (this != internal_default_instance()) delete last_updated_; -} - -void Stabilization::ArenaDtor(void* object) { - Stabilization* _this = reinterpret_cast< Stabilization* >(object); - (void)_this; -} -void Stabilization::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { -} -void Stabilization::SetCachedSize(int size) const { - _cached_size_.Set(size); -} -const Stabilization& Stabilization::default_instance() { - ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Stabilization_stabilizedata_2eproto.base); - return *internal_default_instance(); -} - - -void Stabilization::Clear() { -// @@protoc_insertion_point(message_clear_start:libopenshotstabilize.Stabilization) - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void) cached_has_bits; - - frame_.Clear(); - if (GetArena() == nullptr && last_updated_ != nullptr) { - delete last_updated_; - } - last_updated_ = nullptr; - _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); -} - -const char* Stabilization::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { -#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure - ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena; - while (!ctx->Done(&ptr)) { - ::PROTOBUF_NAMESPACE_ID::uint32 tag; - ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); - CHK_(ptr); - switch (tag >> 3) { - // repeated .libopenshotstabilize.Frame frame = 1; - case 1: - if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) { - ptr -= 1; - do { - ptr += 1; - ptr = ctx->ParseMessage(_internal_add_frame(), ptr); - CHK_(ptr); - if (!ctx->DataAvailable(ptr)) break; - } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<10>(ptr)); - } else goto handle_unusual; - continue; - // .google.protobuf.Timestamp last_updated = 2; - case 2: - if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 18)) { - ptr = ctx->ParseMessage(_internal_mutable_last_updated(), ptr); - CHK_(ptr); - } else goto handle_unusual; - continue; - default: { - handle_unusual: - if ((tag & 7) == 4 || tag == 0) { - ctx->SetLastTag(tag); - goto success; - } - ptr = UnknownFieldParse(tag, - _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), - ptr, ctx); - CHK_(ptr != nullptr); - continue; - } - } // switch - } // while -success: - return ptr; -failure: - ptr = nullptr; - goto success; -#undef CHK_ -} - -::PROTOBUF_NAMESPACE_ID::uint8* Stabilization::_InternalSerialize( - ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:libopenshotstabilize.Stabilization) - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - // repeated .libopenshotstabilize.Frame frame = 1; - for (unsigned int i = 0, - n = static_cast(this->_internal_frame_size()); i < n; i++) { - target = stream->EnsureSpace(target); - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: - InternalWriteMessage(1, this->_internal_frame(i), target, stream); - } - - // .google.protobuf.Timestamp last_updated = 2; - if (this->has_last_updated()) { - target = stream->EnsureSpace(target); - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: - InternalWriteMessage( - 2, _Internal::last_updated(this), target, stream); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:libopenshotstabilize.Stabilization) - return target; -} - -size_t Stabilization::ByteSizeLong() const { -// @@protoc_insertion_point(message_byte_size_start:libopenshotstabilize.Stabilization) - size_t total_size = 0; - - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void) cached_has_bits; - - // repeated .libopenshotstabilize.Frame frame = 1; - total_size += 1UL * this->_internal_frame_size(); - for (const auto& msg : this->frame_) { - total_size += - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); - } - - // .google.protobuf.Timestamp last_updated = 2; - if (this->has_last_updated()) { - total_size += 1 + - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( - *last_updated_); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( - _internal_metadata_, total_size, &_cached_size_); - } - int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); - SetCachedSize(cached_size); - return total_size; -} - -void Stabilization::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { -// @@protoc_insertion_point(generalized_merge_from_start:libopenshotstabilize.Stabilization) - GOOGLE_DCHECK_NE(&from, this); - const Stabilization* source = - ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( - &from); - if (source == nullptr) { - // @@protoc_insertion_point(generalized_merge_from_cast_fail:libopenshotstabilize.Stabilization) - ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); - } else { - // @@protoc_insertion_point(generalized_merge_from_cast_success:libopenshotstabilize.Stabilization) - MergeFrom(*source); - } -} - -void Stabilization::MergeFrom(const Stabilization& from) { -// @@protoc_insertion_point(class_specific_merge_from_start:libopenshotstabilize.Stabilization) - GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - frame_.MergeFrom(from.frame_); - if (from.has_last_updated()) { - _internal_mutable_last_updated()->PROTOBUF_NAMESPACE_ID::Timestamp::MergeFrom(from._internal_last_updated()); - } -} - -void Stabilization::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { -// @@protoc_insertion_point(generalized_copy_from_start:libopenshotstabilize.Stabilization) - if (&from == this) return; - Clear(); - MergeFrom(from); -} - -void Stabilization::CopyFrom(const Stabilization& from) { -// @@protoc_insertion_point(class_specific_copy_from_start:libopenshotstabilize.Stabilization) - if (&from == this) return; - Clear(); - MergeFrom(from); -} - -bool Stabilization::IsInitialized() const { - return true; -} - -void Stabilization::InternalSwap(Stabilization* other) { - using std::swap; - _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); - frame_.InternalSwap(&other->frame_); - swap(last_updated_, other->last_updated_); -} - -::PROTOBUF_NAMESPACE_ID::Metadata Stabilization::GetMetadata() const { - return GetMetadataStatic(); -} - - -// @@protoc_insertion_point(namespace_scope) -} // namespace libopenshotstabilize -PROTOBUF_NAMESPACE_OPEN -template<> PROTOBUF_NOINLINE ::libopenshotstabilize::Frame* Arena::CreateMaybeMessage< ::libopenshotstabilize::Frame >(Arena* arena) { - return Arena::CreateMessageInternal< ::libopenshotstabilize::Frame >(arena); -} -template<> PROTOBUF_NOINLINE ::libopenshotstabilize::Stabilization* Arena::CreateMaybeMessage< ::libopenshotstabilize::Stabilization >(Arena* arena) { - return Arena::CreateMessageInternal< ::libopenshotstabilize::Stabilization >(arena); -} -PROTOBUF_NAMESPACE_CLOSE - -// @@protoc_insertion_point(global_scope) -#include diff --git a/src/stabilizedata.pb.h b/src/stabilizedata.pb.h deleted file mode 100644 index 208a4f8f5..000000000 --- a/src/stabilizedata.pb.h +++ /dev/null @@ -1,723 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: stabilizedata.proto - -#ifndef GOOGLE_PROTOBUF_INCLUDED_stabilizedata_2eproto -#define GOOGLE_PROTOBUF_INCLUDED_stabilizedata_2eproto - -#include -#include - -#include -#if PROTOBUF_VERSION < 3012000 -#error This file was generated by a newer version of protoc which is -#error incompatible with your Protocol Buffer headers. Please update -#error your headers. -#endif -#if 3012003 < PROTOBUF_MIN_PROTOC_VERSION -#error This file was generated by an older version of protoc which is -#error incompatible with your Protocol Buffer headers. Please -#error regenerate this file with a newer version of protoc. -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include // IWYU pragma: export -#include // IWYU pragma: export -#include -#include -// @@protoc_insertion_point(includes) -#include -#define PROTOBUF_INTERNAL_EXPORT_stabilizedata_2eproto -PROTOBUF_NAMESPACE_OPEN -namespace internal { -class AnyMetadata; -} // namespace internal -PROTOBUF_NAMESPACE_CLOSE - -// Internal implementation detail -- do not use these members. -struct TableStruct_stabilizedata_2eproto { - static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[] - PROTOBUF_SECTION_VARIABLE(protodesc_cold); - static const ::PROTOBUF_NAMESPACE_ID::internal::AuxillaryParseTableField aux[] - PROTOBUF_SECTION_VARIABLE(protodesc_cold); - static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[2] - PROTOBUF_SECTION_VARIABLE(protodesc_cold); - static const ::PROTOBUF_NAMESPACE_ID::internal::FieldMetadata field_metadata[]; - static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[]; - static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[]; -}; -extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_stabilizedata_2eproto; -namespace libopenshotstabilize { -class Frame; -class FrameDefaultTypeInternal; -extern FrameDefaultTypeInternal _Frame_default_instance_; -class Stabilization; -class StabilizationDefaultTypeInternal; -extern StabilizationDefaultTypeInternal _Stabilization_default_instance_; -} // namespace libopenshotstabilize -PROTOBUF_NAMESPACE_OPEN -template<> ::libopenshotstabilize::Frame* Arena::CreateMaybeMessage<::libopenshotstabilize::Frame>(Arena*); -template<> ::libopenshotstabilize::Stabilization* Arena::CreateMaybeMessage<::libopenshotstabilize::Stabilization>(Arena*); -PROTOBUF_NAMESPACE_CLOSE -namespace libopenshotstabilize { - -// =================================================================== - -class Frame PROTOBUF_FINAL : - public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:libopenshotstabilize.Frame) */ { - public: - inline Frame() : Frame(nullptr) {}; - virtual ~Frame(); - - Frame(const Frame& from); - Frame(Frame&& from) noexcept - : Frame() { - *this = ::std::move(from); - } - - inline Frame& operator=(const Frame& from) { - CopyFrom(from); - return *this; - } - inline Frame& operator=(Frame&& from) noexcept { - if (GetArena() == from.GetArena()) { - if (this != &from) InternalSwap(&from); - } else { - CopyFrom(from); - } - return *this; - } - - static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { - return GetDescriptor(); - } - static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { - return GetMetadataStatic().descriptor; - } - static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { - return GetMetadataStatic().reflection; - } - static const Frame& default_instance(); - - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY - static inline const Frame* internal_default_instance() { - return reinterpret_cast( - &_Frame_default_instance_); - } - static constexpr int kIndexInFileMessages = - 0; - - friend void swap(Frame& a, Frame& b) { - a.Swap(&b); - } - inline void Swap(Frame* other) { - if (other == this) return; - if (GetArena() == other->GetArena()) { - InternalSwap(other); - } else { - ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); - } - } - void UnsafeArenaSwap(Frame* other) { - if (other == this) return; - GOOGLE_DCHECK(GetArena() == other->GetArena()); - InternalSwap(other); - } - - // implements Message ---------------------------------------------- - - inline Frame* New() const final { - return CreateMaybeMessage(nullptr); - } - - Frame* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { - return CreateMaybeMessage(arena); - } - void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; - void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; - void CopyFrom(const Frame& from); - void MergeFrom(const Frame& from); - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; - bool IsInitialized() const final; - - size_t ByteSizeLong() const final; - const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; - ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( - ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; - int GetCachedSize() const final { return _cached_size_.Get(); } - - private: - inline void SharedCtor(); - inline void SharedDtor(); - void SetCachedSize(int size) const final; - void InternalSwap(Frame* other); - friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; - static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { - return "libopenshotstabilize.Frame"; - } - protected: - explicit Frame(::PROTOBUF_NAMESPACE_ID::Arena* arena); - private: - static void ArenaDtor(void* object); - inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); - public: - - ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; - private: - static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { - ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_stabilizedata_2eproto); - return ::descriptor_table_stabilizedata_2eproto.file_level_metadata[kIndexInFileMessages]; - } - - public: - - // nested types ---------------------------------------------------- - - // accessors ------------------------------------------------------- - - enum : int { - kIdFieldNumber = 1, - kDxFieldNumber = 2, - kDyFieldNumber = 3, - kDaFieldNumber = 4, - kXFieldNumber = 5, - kYFieldNumber = 6, - kAFieldNumber = 7, - }; - // int32 id = 1; - void clear_id(); - ::PROTOBUF_NAMESPACE_ID::int32 id() const; - void set_id(::PROTOBUF_NAMESPACE_ID::int32 value); - private: - ::PROTOBUF_NAMESPACE_ID::int32 _internal_id() const; - void _internal_set_id(::PROTOBUF_NAMESPACE_ID::int32 value); - public: - - // float dx = 2; - void clear_dx(); - float dx() const; - void set_dx(float value); - private: - float _internal_dx() const; - void _internal_set_dx(float value); - public: - - // float dy = 3; - void clear_dy(); - float dy() const; - void set_dy(float value); - private: - float _internal_dy() const; - void _internal_set_dy(float value); - public: - - // float da = 4; - void clear_da(); - float da() const; - void set_da(float value); - private: - float _internal_da() const; - void _internal_set_da(float value); - public: - - // float x = 5; - void clear_x(); - float x() const; - void set_x(float value); - private: - float _internal_x() const; - void _internal_set_x(float value); - public: - - // float y = 6; - void clear_y(); - float y() const; - void set_y(float value); - private: - float _internal_y() const; - void _internal_set_y(float value); - public: - - // float a = 7; - void clear_a(); - float a() const; - void set_a(float value); - private: - float _internal_a() const; - void _internal_set_a(float value); - public: - - // @@protoc_insertion_point(class_scope:libopenshotstabilize.Frame) - private: - class _Internal; - - template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; - typedef void InternalArenaConstructable_; - typedef void DestructorSkippable_; - ::PROTOBUF_NAMESPACE_ID::int32 id_; - float dx_; - float dy_; - float da_; - float x_; - float y_; - float a_; - mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; - friend struct ::TableStruct_stabilizedata_2eproto; -}; -// ------------------------------------------------------------------- - -class Stabilization PROTOBUF_FINAL : - public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:libopenshotstabilize.Stabilization) */ { - public: - inline Stabilization() : Stabilization(nullptr) {}; - virtual ~Stabilization(); - - Stabilization(const Stabilization& from); - Stabilization(Stabilization&& from) noexcept - : Stabilization() { - *this = ::std::move(from); - } - - inline Stabilization& operator=(const Stabilization& from) { - CopyFrom(from); - return *this; - } - inline Stabilization& operator=(Stabilization&& from) noexcept { - if (GetArena() == from.GetArena()) { - if (this != &from) InternalSwap(&from); - } else { - CopyFrom(from); - } - return *this; - } - - static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { - return GetDescriptor(); - } - static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { - return GetMetadataStatic().descriptor; - } - static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { - return GetMetadataStatic().reflection; - } - static const Stabilization& default_instance(); - - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY - static inline const Stabilization* internal_default_instance() { - return reinterpret_cast( - &_Stabilization_default_instance_); - } - static constexpr int kIndexInFileMessages = - 1; - - friend void swap(Stabilization& a, Stabilization& b) { - a.Swap(&b); - } - inline void Swap(Stabilization* other) { - if (other == this) return; - if (GetArena() == other->GetArena()) { - InternalSwap(other); - } else { - ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); - } - } - void UnsafeArenaSwap(Stabilization* other) { - if (other == this) return; - GOOGLE_DCHECK(GetArena() == other->GetArena()); - InternalSwap(other); - } - - // implements Message ---------------------------------------------- - - inline Stabilization* New() const final { - return CreateMaybeMessage(nullptr); - } - - Stabilization* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { - return CreateMaybeMessage(arena); - } - void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; - void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; - void CopyFrom(const Stabilization& from); - void MergeFrom(const Stabilization& from); - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; - bool IsInitialized() const final; - - size_t ByteSizeLong() const final; - const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; - ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( - ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; - int GetCachedSize() const final { return _cached_size_.Get(); } - - private: - inline void SharedCtor(); - inline void SharedDtor(); - void SetCachedSize(int size) const final; - void InternalSwap(Stabilization* other); - friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; - static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { - return "libopenshotstabilize.Stabilization"; - } - protected: - explicit Stabilization(::PROTOBUF_NAMESPACE_ID::Arena* arena); - private: - static void ArenaDtor(void* object); - inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); - public: - - ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; - private: - static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { - ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_stabilizedata_2eproto); - return ::descriptor_table_stabilizedata_2eproto.file_level_metadata[kIndexInFileMessages]; - } - - public: - - // nested types ---------------------------------------------------- - - // accessors ------------------------------------------------------- - - enum : int { - kFrameFieldNumber = 1, - kLastUpdatedFieldNumber = 2, - }; - // repeated .libopenshotstabilize.Frame frame = 1; - int frame_size() const; - private: - int _internal_frame_size() const; - public: - void clear_frame(); - ::libopenshotstabilize::Frame* mutable_frame(int index); - ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::libopenshotstabilize::Frame >* - mutable_frame(); - private: - const ::libopenshotstabilize::Frame& _internal_frame(int index) const; - ::libopenshotstabilize::Frame* _internal_add_frame(); - public: - const ::libopenshotstabilize::Frame& frame(int index) const; - ::libopenshotstabilize::Frame* add_frame(); - const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::libopenshotstabilize::Frame >& - frame() const; - - // .google.protobuf.Timestamp last_updated = 2; - bool has_last_updated() const; - private: - bool _internal_has_last_updated() const; - public: - void clear_last_updated(); - const PROTOBUF_NAMESPACE_ID::Timestamp& last_updated() const; - PROTOBUF_NAMESPACE_ID::Timestamp* release_last_updated(); - PROTOBUF_NAMESPACE_ID::Timestamp* mutable_last_updated(); - void set_allocated_last_updated(PROTOBUF_NAMESPACE_ID::Timestamp* last_updated); - private: - const PROTOBUF_NAMESPACE_ID::Timestamp& _internal_last_updated() const; - PROTOBUF_NAMESPACE_ID::Timestamp* _internal_mutable_last_updated(); - public: - void unsafe_arena_set_allocated_last_updated( - PROTOBUF_NAMESPACE_ID::Timestamp* last_updated); - PROTOBUF_NAMESPACE_ID::Timestamp* unsafe_arena_release_last_updated(); - - // @@protoc_insertion_point(class_scope:libopenshotstabilize.Stabilization) - private: - class _Internal; - - template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; - typedef void InternalArenaConstructable_; - typedef void DestructorSkippable_; - ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::libopenshotstabilize::Frame > frame_; - PROTOBUF_NAMESPACE_ID::Timestamp* last_updated_; - mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; - friend struct ::TableStruct_stabilizedata_2eproto; -}; -// =================================================================== - - -// =================================================================== - -#ifdef __GNUC__ - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wstrict-aliasing" -#endif // __GNUC__ -// Frame - -// int32 id = 1; -inline void Frame::clear_id() { - id_ = 0; -} -inline ::PROTOBUF_NAMESPACE_ID::int32 Frame::_internal_id() const { - return id_; -} -inline ::PROTOBUF_NAMESPACE_ID::int32 Frame::id() const { - // @@protoc_insertion_point(field_get:libopenshotstabilize.Frame.id) - return _internal_id(); -} -inline void Frame::_internal_set_id(::PROTOBUF_NAMESPACE_ID::int32 value) { - - id_ = value; -} -inline void Frame::set_id(::PROTOBUF_NAMESPACE_ID::int32 value) { - _internal_set_id(value); - // @@protoc_insertion_point(field_set:libopenshotstabilize.Frame.id) -} - -// float dx = 2; -inline void Frame::clear_dx() { - dx_ = 0; -} -inline float Frame::_internal_dx() const { - return dx_; -} -inline float Frame::dx() const { - // @@protoc_insertion_point(field_get:libopenshotstabilize.Frame.dx) - return _internal_dx(); -} -inline void Frame::_internal_set_dx(float value) { - - dx_ = value; -} -inline void Frame::set_dx(float value) { - _internal_set_dx(value); - // @@protoc_insertion_point(field_set:libopenshotstabilize.Frame.dx) -} - -// float dy = 3; -inline void Frame::clear_dy() { - dy_ = 0; -} -inline float Frame::_internal_dy() const { - return dy_; -} -inline float Frame::dy() const { - // @@protoc_insertion_point(field_get:libopenshotstabilize.Frame.dy) - return _internal_dy(); -} -inline void Frame::_internal_set_dy(float value) { - - dy_ = value; -} -inline void Frame::set_dy(float value) { - _internal_set_dy(value); - // @@protoc_insertion_point(field_set:libopenshotstabilize.Frame.dy) -} - -// float da = 4; -inline void Frame::clear_da() { - da_ = 0; -} -inline float Frame::_internal_da() const { - return da_; -} -inline float Frame::da() const { - // @@protoc_insertion_point(field_get:libopenshotstabilize.Frame.da) - return _internal_da(); -} -inline void Frame::_internal_set_da(float value) { - - da_ = value; -} -inline void Frame::set_da(float value) { - _internal_set_da(value); - // @@protoc_insertion_point(field_set:libopenshotstabilize.Frame.da) -} - -// float x = 5; -inline void Frame::clear_x() { - x_ = 0; -} -inline float Frame::_internal_x() const { - return x_; -} -inline float Frame::x() const { - // @@protoc_insertion_point(field_get:libopenshotstabilize.Frame.x) - return _internal_x(); -} -inline void Frame::_internal_set_x(float value) { - - x_ = value; -} -inline void Frame::set_x(float value) { - _internal_set_x(value); - // @@protoc_insertion_point(field_set:libopenshotstabilize.Frame.x) -} - -// float y = 6; -inline void Frame::clear_y() { - y_ = 0; -} -inline float Frame::_internal_y() const { - return y_; -} -inline float Frame::y() const { - // @@protoc_insertion_point(field_get:libopenshotstabilize.Frame.y) - return _internal_y(); -} -inline void Frame::_internal_set_y(float value) { - - y_ = value; -} -inline void Frame::set_y(float value) { - _internal_set_y(value); - // @@protoc_insertion_point(field_set:libopenshotstabilize.Frame.y) -} - -// float a = 7; -inline void Frame::clear_a() { - a_ = 0; -} -inline float Frame::_internal_a() const { - return a_; -} -inline float Frame::a() const { - // @@protoc_insertion_point(field_get:libopenshotstabilize.Frame.a) - return _internal_a(); -} -inline void Frame::_internal_set_a(float value) { - - a_ = value; -} -inline void Frame::set_a(float value) { - _internal_set_a(value); - // @@protoc_insertion_point(field_set:libopenshotstabilize.Frame.a) -} - -// ------------------------------------------------------------------- - -// Stabilization - -// repeated .libopenshotstabilize.Frame frame = 1; -inline int Stabilization::_internal_frame_size() const { - return frame_.size(); -} -inline int Stabilization::frame_size() const { - return _internal_frame_size(); -} -inline void Stabilization::clear_frame() { - frame_.Clear(); -} -inline ::libopenshotstabilize::Frame* Stabilization::mutable_frame(int index) { - // @@protoc_insertion_point(field_mutable:libopenshotstabilize.Stabilization.frame) - return frame_.Mutable(index); -} -inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::libopenshotstabilize::Frame >* -Stabilization::mutable_frame() { - // @@protoc_insertion_point(field_mutable_list:libopenshotstabilize.Stabilization.frame) - return &frame_; -} -inline const ::libopenshotstabilize::Frame& Stabilization::_internal_frame(int index) const { - return frame_.Get(index); -} -inline const ::libopenshotstabilize::Frame& Stabilization::frame(int index) const { - // @@protoc_insertion_point(field_get:libopenshotstabilize.Stabilization.frame) - return _internal_frame(index); -} -inline ::libopenshotstabilize::Frame* Stabilization::_internal_add_frame() { - return frame_.Add(); -} -inline ::libopenshotstabilize::Frame* Stabilization::add_frame() { - // @@protoc_insertion_point(field_add:libopenshotstabilize.Stabilization.frame) - return _internal_add_frame(); -} -inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::libopenshotstabilize::Frame >& -Stabilization::frame() const { - // @@protoc_insertion_point(field_list:libopenshotstabilize.Stabilization.frame) - return frame_; -} - -// .google.protobuf.Timestamp last_updated = 2; -inline bool Stabilization::_internal_has_last_updated() const { - return this != internal_default_instance() && last_updated_ != nullptr; -} -inline bool Stabilization::has_last_updated() const { - return _internal_has_last_updated(); -} -inline const PROTOBUF_NAMESPACE_ID::Timestamp& Stabilization::_internal_last_updated() const { - const PROTOBUF_NAMESPACE_ID::Timestamp* p = last_updated_; - return p != nullptr ? *p : *reinterpret_cast( - &PROTOBUF_NAMESPACE_ID::_Timestamp_default_instance_); -} -inline const PROTOBUF_NAMESPACE_ID::Timestamp& Stabilization::last_updated() const { - // @@protoc_insertion_point(field_get:libopenshotstabilize.Stabilization.last_updated) - return _internal_last_updated(); -} -inline void Stabilization::unsafe_arena_set_allocated_last_updated( - PROTOBUF_NAMESPACE_ID::Timestamp* last_updated) { - if (GetArena() == nullptr) { - delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(last_updated_); - } - last_updated_ = last_updated; - if (last_updated) { - - } else { - - } - // @@protoc_insertion_point(field_unsafe_arena_set_allocated:libopenshotstabilize.Stabilization.last_updated) -} -inline PROTOBUF_NAMESPACE_ID::Timestamp* Stabilization::release_last_updated() { - auto temp = unsafe_arena_release_last_updated(); - if (GetArena() != nullptr) { - temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); - } - return temp; -} -inline PROTOBUF_NAMESPACE_ID::Timestamp* Stabilization::unsafe_arena_release_last_updated() { - // @@protoc_insertion_point(field_release:libopenshotstabilize.Stabilization.last_updated) - - PROTOBUF_NAMESPACE_ID::Timestamp* temp = last_updated_; - last_updated_ = nullptr; - return temp; -} -inline PROTOBUF_NAMESPACE_ID::Timestamp* Stabilization::_internal_mutable_last_updated() { - - if (last_updated_ == nullptr) { - auto* p = CreateMaybeMessage(GetArena()); - last_updated_ = p; - } - return last_updated_; -} -inline PROTOBUF_NAMESPACE_ID::Timestamp* Stabilization::mutable_last_updated() { - // @@protoc_insertion_point(field_mutable:libopenshotstabilize.Stabilization.last_updated) - return _internal_mutable_last_updated(); -} -inline void Stabilization::set_allocated_last_updated(PROTOBUF_NAMESPACE_ID::Timestamp* last_updated) { - ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArena(); - if (message_arena == nullptr) { - delete reinterpret_cast< ::PROTOBUF_NAMESPACE_ID::MessageLite*>(last_updated_); - } - if (last_updated) { - ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = - reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(last_updated)->GetArena(); - if (message_arena != submessage_arena) { - last_updated = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( - message_arena, last_updated, submessage_arena); - } - - } else { - - } - last_updated_ = last_updated; - // @@protoc_insertion_point(field_set_allocated:libopenshotstabilize.Stabilization.last_updated) -} - -#ifdef __GNUC__ - #pragma GCC diagnostic pop -#endif // __GNUC__ -// ------------------------------------------------------------------- - - -// @@protoc_insertion_point(namespace_scope) - -} // namespace libopenshotstabilize - -// @@protoc_insertion_point(global_scope) - -#include -#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_stabilizedata_2eproto diff --git a/src/trackerdata.pb.cc b/src/trackerdata.pb.cc deleted file mode 100644 index 8536f4594..000000000 --- a/src/trackerdata.pb.cc +++ /dev/null @@ -1,961 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: trackerdata.proto - -#include "trackerdata.pb.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -// @@protoc_insertion_point(includes) -#include -extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2ftimestamp_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Timestamp_google_2fprotobuf_2ftimestamp_2eproto; -extern PROTOBUF_INTERNAL_EXPORT_trackerdata_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_Frame_trackerdata_2eproto; -extern PROTOBUF_INTERNAL_EXPORT_trackerdata_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Frame_Box_trackerdata_2eproto; -namespace libopenshottracker { -class Frame_BoxDefaultTypeInternal { - public: - ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; -} _Frame_Box_default_instance_; -class FrameDefaultTypeInternal { - public: - ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; -} _Frame_default_instance_; -class TrackerDefaultTypeInternal { - public: - ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; -} _Tracker_default_instance_; -} // namespace libopenshottracker -static void InitDefaultsscc_info_Frame_trackerdata_2eproto() { - GOOGLE_PROTOBUF_VERIFY_VERSION; - - { - void* ptr = &::libopenshottracker::_Frame_default_instance_; - new (ptr) ::libopenshottracker::Frame(); - ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); - } - ::libopenshottracker::Frame::InitAsDefaultInstance(); -} - -::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_Frame_trackerdata_2eproto = - {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_Frame_trackerdata_2eproto}, { - &scc_info_Frame_Box_trackerdata_2eproto.base,}}; - -static void InitDefaultsscc_info_Frame_Box_trackerdata_2eproto() { - GOOGLE_PROTOBUF_VERIFY_VERSION; - - { - void* ptr = &::libopenshottracker::_Frame_Box_default_instance_; - new (ptr) ::libopenshottracker::Frame_Box(); - ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); - } - ::libopenshottracker::Frame_Box::InitAsDefaultInstance(); -} - -::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Frame_Box_trackerdata_2eproto = - {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_Frame_Box_trackerdata_2eproto}, {}}; - -static void InitDefaultsscc_info_Tracker_trackerdata_2eproto() { - GOOGLE_PROTOBUF_VERIFY_VERSION; - - { - void* ptr = &::libopenshottracker::_Tracker_default_instance_; - new (ptr) ::libopenshottracker::Tracker(); - ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); - } - ::libopenshottracker::Tracker::InitAsDefaultInstance(); -} - -::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<2> scc_info_Tracker_trackerdata_2eproto = - {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 2, 0, InitDefaultsscc_info_Tracker_trackerdata_2eproto}, { - &scc_info_Frame_trackerdata_2eproto.base, - &scc_info_Timestamp_google_2fprotobuf_2ftimestamp_2eproto.base,}}; - -static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_trackerdata_2eproto[3]; -static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_trackerdata_2eproto = nullptr; -static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_trackerdata_2eproto = nullptr; - -const ::PROTOBUF_NAMESPACE_ID::uint32 TableStruct_trackerdata_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { - ~0u, // no _has_bits_ - PROTOBUF_FIELD_OFFSET(::libopenshottracker::Frame_Box, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - PROTOBUF_FIELD_OFFSET(::libopenshottracker::Frame_Box, x1_), - PROTOBUF_FIELD_OFFSET(::libopenshottracker::Frame_Box, y1_), - PROTOBUF_FIELD_OFFSET(::libopenshottracker::Frame_Box, x2_), - PROTOBUF_FIELD_OFFSET(::libopenshottracker::Frame_Box, y2_), - ~0u, // no _has_bits_ - PROTOBUF_FIELD_OFFSET(::libopenshottracker::Frame, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - PROTOBUF_FIELD_OFFSET(::libopenshottracker::Frame, id_), - PROTOBUF_FIELD_OFFSET(::libopenshottracker::Frame, rotation_), - PROTOBUF_FIELD_OFFSET(::libopenshottracker::Frame, bounding_box_), - ~0u, // no _has_bits_ - PROTOBUF_FIELD_OFFSET(::libopenshottracker::Tracker, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - PROTOBUF_FIELD_OFFSET(::libopenshottracker::Tracker, frame_), - PROTOBUF_FIELD_OFFSET(::libopenshottracker::Tracker, last_updated_), -}; -static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { - { 0, -1, sizeof(::libopenshottracker::Frame_Box)}, - { 9, -1, sizeof(::libopenshottracker::Frame)}, - { 17, -1, sizeof(::libopenshottracker::Tracker)}, -}; - -static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = { - reinterpret_cast(&::libopenshottracker::_Frame_Box_default_instance_), - reinterpret_cast(&::libopenshottracker::_Frame_default_instance_), - reinterpret_cast(&::libopenshottracker::_Tracker_default_instance_), -}; - -const char descriptor_table_protodef_trackerdata_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = - "\n\021trackerdata.proto\022\022libopenshottracker\032" - "\037google/protobuf/timestamp.proto\"\221\001\n\005Fra" - "me\022\n\n\002id\030\001 \001(\005\022\020\n\010rotation\030\002 \001(\002\0223\n\014boun" - "ding_box\030\003 \001(\0132\035.libopenshottracker.Fram" - "e.Box\0325\n\003Box\022\n\n\002x1\030\001 \001(\002\022\n\n\002y1\030\002 \001(\002\022\n\n\002" - "x2\030\003 \001(\002\022\n\n\002y2\030\004 \001(\002\"e\n\007Tracker\022(\n\005frame" - "\030\001 \003(\0132\031.libopenshottracker.Frame\0220\n\014las" - "t_updated\030\002 \001(\0132\032.google.protobuf.Timest" - "ampb\006proto3" - ; -static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_trackerdata_2eproto_deps[1] = { - &::descriptor_table_google_2fprotobuf_2ftimestamp_2eproto, -}; -static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_trackerdata_2eproto_sccs[3] = { - &scc_info_Frame_trackerdata_2eproto.base, - &scc_info_Frame_Box_trackerdata_2eproto.base, - &scc_info_Tracker_trackerdata_2eproto.base, -}; -static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_trackerdata_2eproto_once; -const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_trackerdata_2eproto = { - false, false, descriptor_table_protodef_trackerdata_2eproto, "trackerdata.proto", 331, - &descriptor_table_trackerdata_2eproto_once, descriptor_table_trackerdata_2eproto_sccs, descriptor_table_trackerdata_2eproto_deps, 3, 1, - schemas, file_default_instances, TableStruct_trackerdata_2eproto::offsets, - file_level_metadata_trackerdata_2eproto, 3, file_level_enum_descriptors_trackerdata_2eproto, file_level_service_descriptors_trackerdata_2eproto, -}; - -// Force running AddDescriptors() at dynamic initialization time. -static bool dynamic_init_dummy_trackerdata_2eproto = (static_cast(::PROTOBUF_NAMESPACE_ID::internal::AddDescriptors(&descriptor_table_trackerdata_2eproto)), true); -namespace libopenshottracker { - -// =================================================================== - -void Frame_Box::InitAsDefaultInstance() { -} -class Frame_Box::_Internal { - public: -}; - -Frame_Box::Frame_Box(::PROTOBUF_NAMESPACE_ID::Arena* arena) - : ::PROTOBUF_NAMESPACE_ID::Message(arena) { - SharedCtor(); - RegisterArenaDtor(arena); - // @@protoc_insertion_point(arena_constructor:libopenshottracker.Frame.Box) -} -Frame_Box::Frame_Box(const Frame_Box& from) - : ::PROTOBUF_NAMESPACE_ID::Message() { - _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); - ::memcpy(&x1_, &from.x1_, - static_cast(reinterpret_cast(&y2_) - - reinterpret_cast(&x1_)) + sizeof(y2_)); - // @@protoc_insertion_point(copy_constructor:libopenshottracker.Frame.Box) -} - -void Frame_Box::SharedCtor() { - ::memset(&x1_, 0, static_cast( - reinterpret_cast(&y2_) - - reinterpret_cast(&x1_)) + sizeof(y2_)); -} - -Frame_Box::~Frame_Box() { - // @@protoc_insertion_point(destructor:libopenshottracker.Frame.Box) - SharedDtor(); - _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); -} - -void Frame_Box::SharedDtor() { - GOOGLE_DCHECK(GetArena() == nullptr); -} - -void Frame_Box::ArenaDtor(void* object) { - Frame_Box* _this = reinterpret_cast< Frame_Box* >(object); - (void)_this; -} -void Frame_Box::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { -} -void Frame_Box::SetCachedSize(int size) const { - _cached_size_.Set(size); -} -const Frame_Box& Frame_Box::default_instance() { - ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Frame_Box_trackerdata_2eproto.base); - return *internal_default_instance(); -} - - -void Frame_Box::Clear() { -// @@protoc_insertion_point(message_clear_start:libopenshottracker.Frame.Box) - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void) cached_has_bits; - - ::memset(&x1_, 0, static_cast( - reinterpret_cast(&y2_) - - reinterpret_cast(&x1_)) + sizeof(y2_)); - _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); -} - -const char* Frame_Box::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { -#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure - ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena; - while (!ctx->Done(&ptr)) { - ::PROTOBUF_NAMESPACE_ID::uint32 tag; - ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); - CHK_(ptr); - switch (tag >> 3) { - // float x1 = 1; - case 1: - if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 13)) { - x1_ = ::PROTOBUF_NAMESPACE_ID::internal::UnalignedLoad(ptr); - ptr += sizeof(float); - } else goto handle_unusual; - continue; - // float y1 = 2; - case 2: - if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 21)) { - y1_ = ::PROTOBUF_NAMESPACE_ID::internal::UnalignedLoad(ptr); - ptr += sizeof(float); - } else goto handle_unusual; - continue; - // float x2 = 3; - case 3: - if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 29)) { - x2_ = ::PROTOBUF_NAMESPACE_ID::internal::UnalignedLoad(ptr); - ptr += sizeof(float); - } else goto handle_unusual; - continue; - // float y2 = 4; - case 4: - if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 37)) { - y2_ = ::PROTOBUF_NAMESPACE_ID::internal::UnalignedLoad(ptr); - ptr += sizeof(float); - } else goto handle_unusual; - continue; - default: { - handle_unusual: - if ((tag & 7) == 4 || tag == 0) { - ctx->SetLastTag(tag); - goto success; - } - ptr = UnknownFieldParse(tag, - _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), - ptr, ctx); - CHK_(ptr != nullptr); - continue; - } - } // switch - } // while -success: - return ptr; -failure: - ptr = nullptr; - goto success; -#undef CHK_ -} - -::PROTOBUF_NAMESPACE_ID::uint8* Frame_Box::_InternalSerialize( - ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:libopenshottracker.Frame.Box) - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - // float x1 = 1; - if (!(this->x1() <= 0 && this->x1() >= 0)) { - target = stream->EnsureSpace(target); - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteFloatToArray(1, this->_internal_x1(), target); - } - - // float y1 = 2; - if (!(this->y1() <= 0 && this->y1() >= 0)) { - target = stream->EnsureSpace(target); - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteFloatToArray(2, this->_internal_y1(), target); - } - - // float x2 = 3; - if (!(this->x2() <= 0 && this->x2() >= 0)) { - target = stream->EnsureSpace(target); - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteFloatToArray(3, this->_internal_x2(), target); - } - - // float y2 = 4; - if (!(this->y2() <= 0 && this->y2() >= 0)) { - target = stream->EnsureSpace(target); - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteFloatToArray(4, this->_internal_y2(), target); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:libopenshottracker.Frame.Box) - return target; -} - -size_t Frame_Box::ByteSizeLong() const { -// @@protoc_insertion_point(message_byte_size_start:libopenshottracker.Frame.Box) - size_t total_size = 0; - - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void) cached_has_bits; - - // float x1 = 1; - if (!(this->x1() <= 0 && this->x1() >= 0)) { - total_size += 1 + 4; - } - - // float y1 = 2; - if (!(this->y1() <= 0 && this->y1() >= 0)) { - total_size += 1 + 4; - } - - // float x2 = 3; - if (!(this->x2() <= 0 && this->x2() >= 0)) { - total_size += 1 + 4; - } - - // float y2 = 4; - if (!(this->y2() <= 0 && this->y2() >= 0)) { - total_size += 1 + 4; - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( - _internal_metadata_, total_size, &_cached_size_); - } - int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); - SetCachedSize(cached_size); - return total_size; -} - -void Frame_Box::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { -// @@protoc_insertion_point(generalized_merge_from_start:libopenshottracker.Frame.Box) - GOOGLE_DCHECK_NE(&from, this); - const Frame_Box* source = - ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( - &from); - if (source == nullptr) { - // @@protoc_insertion_point(generalized_merge_from_cast_fail:libopenshottracker.Frame.Box) - ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); - } else { - // @@protoc_insertion_point(generalized_merge_from_cast_success:libopenshottracker.Frame.Box) - MergeFrom(*source); - } -} - -void Frame_Box::MergeFrom(const Frame_Box& from) { -// @@protoc_insertion_point(class_specific_merge_from_start:libopenshottracker.Frame.Box) - GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - if (!(from.x1() <= 0 && from.x1() >= 0)) { - _internal_set_x1(from._internal_x1()); - } - if (!(from.y1() <= 0 && from.y1() >= 0)) { - _internal_set_y1(from._internal_y1()); - } - if (!(from.x2() <= 0 && from.x2() >= 0)) { - _internal_set_x2(from._internal_x2()); - } - if (!(from.y2() <= 0 && from.y2() >= 0)) { - _internal_set_y2(from._internal_y2()); - } -} - -void Frame_Box::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { -// @@protoc_insertion_point(generalized_copy_from_start:libopenshottracker.Frame.Box) - if (&from == this) return; - Clear(); - MergeFrom(from); -} - -void Frame_Box::CopyFrom(const Frame_Box& from) { -// @@protoc_insertion_point(class_specific_copy_from_start:libopenshottracker.Frame.Box) - if (&from == this) return; - Clear(); - MergeFrom(from); -} - -bool Frame_Box::IsInitialized() const { - return true; -} - -void Frame_Box::InternalSwap(Frame_Box* other) { - using std::swap; - _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); - ::PROTOBUF_NAMESPACE_ID::internal::memswap< - PROTOBUF_FIELD_OFFSET(Frame_Box, y2_) - + sizeof(Frame_Box::y2_) - - PROTOBUF_FIELD_OFFSET(Frame_Box, x1_)>( - reinterpret_cast(&x1_), - reinterpret_cast(&other->x1_)); -} - -::PROTOBUF_NAMESPACE_ID::Metadata Frame_Box::GetMetadata() const { - return GetMetadataStatic(); -} - - -// =================================================================== - -void Frame::InitAsDefaultInstance() { - ::libopenshottracker::_Frame_default_instance_._instance.get_mutable()->bounding_box_ = const_cast< ::libopenshottracker::Frame_Box*>( - ::libopenshottracker::Frame_Box::internal_default_instance()); -} -class Frame::_Internal { - public: - static const ::libopenshottracker::Frame_Box& bounding_box(const Frame* msg); -}; - -const ::libopenshottracker::Frame_Box& -Frame::_Internal::bounding_box(const Frame* msg) { - return *msg->bounding_box_; -} -Frame::Frame(::PROTOBUF_NAMESPACE_ID::Arena* arena) - : ::PROTOBUF_NAMESPACE_ID::Message(arena) { - SharedCtor(); - RegisterArenaDtor(arena); - // @@protoc_insertion_point(arena_constructor:libopenshottracker.Frame) -} -Frame::Frame(const Frame& from) - : ::PROTOBUF_NAMESPACE_ID::Message() { - _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); - if (from._internal_has_bounding_box()) { - bounding_box_ = new ::libopenshottracker::Frame_Box(*from.bounding_box_); - } else { - bounding_box_ = nullptr; - } - ::memcpy(&id_, &from.id_, - static_cast(reinterpret_cast(&rotation_) - - reinterpret_cast(&id_)) + sizeof(rotation_)); - // @@protoc_insertion_point(copy_constructor:libopenshottracker.Frame) -} - -void Frame::SharedCtor() { - ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_Frame_trackerdata_2eproto.base); - ::memset(&bounding_box_, 0, static_cast( - reinterpret_cast(&rotation_) - - reinterpret_cast(&bounding_box_)) + sizeof(rotation_)); -} - -Frame::~Frame() { - // @@protoc_insertion_point(destructor:libopenshottracker.Frame) - SharedDtor(); - _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); -} - -void Frame::SharedDtor() { - GOOGLE_DCHECK(GetArena() == nullptr); - if (this != internal_default_instance()) delete bounding_box_; -} - -void Frame::ArenaDtor(void* object) { - Frame* _this = reinterpret_cast< Frame* >(object); - (void)_this; -} -void Frame::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { -} -void Frame::SetCachedSize(int size) const { - _cached_size_.Set(size); -} -const Frame& Frame::default_instance() { - ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Frame_trackerdata_2eproto.base); - return *internal_default_instance(); -} - - -void Frame::Clear() { -// @@protoc_insertion_point(message_clear_start:libopenshottracker.Frame) - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void) cached_has_bits; - - if (GetArena() == nullptr && bounding_box_ != nullptr) { - delete bounding_box_; - } - bounding_box_ = nullptr; - ::memset(&id_, 0, static_cast( - reinterpret_cast(&rotation_) - - reinterpret_cast(&id_)) + sizeof(rotation_)); - _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); -} - -const char* Frame::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { -#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure - ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena; - while (!ctx->Done(&ptr)) { - ::PROTOBUF_NAMESPACE_ID::uint32 tag; - ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); - CHK_(ptr); - switch (tag >> 3) { - // int32 id = 1; - case 1: - if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { - id_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); - CHK_(ptr); - } else goto handle_unusual; - continue; - // float rotation = 2; - case 2: - if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 21)) { - rotation_ = ::PROTOBUF_NAMESPACE_ID::internal::UnalignedLoad(ptr); - ptr += sizeof(float); - } else goto handle_unusual; - continue; - // .libopenshottracker.Frame.Box bounding_box = 3; - case 3: - if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 26)) { - ptr = ctx->ParseMessage(_internal_mutable_bounding_box(), ptr); - CHK_(ptr); - } else goto handle_unusual; - continue; - default: { - handle_unusual: - if ((tag & 7) == 4 || tag == 0) { - ctx->SetLastTag(tag); - goto success; - } - ptr = UnknownFieldParse(tag, - _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), - ptr, ctx); - CHK_(ptr != nullptr); - continue; - } - } // switch - } // while -success: - return ptr; -failure: - ptr = nullptr; - goto success; -#undef CHK_ -} - -::PROTOBUF_NAMESPACE_ID::uint8* Frame::_InternalSerialize( - ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:libopenshottracker.Frame) - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - // int32 id = 1; - if (this->id() != 0) { - target = stream->EnsureSpace(target); - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(1, this->_internal_id(), target); - } - - // float rotation = 2; - if (!(this->rotation() <= 0 && this->rotation() >= 0)) { - target = stream->EnsureSpace(target); - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteFloatToArray(2, this->_internal_rotation(), target); - } - - // .libopenshottracker.Frame.Box bounding_box = 3; - if (this->has_bounding_box()) { - target = stream->EnsureSpace(target); - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: - InternalWriteMessage( - 3, _Internal::bounding_box(this), target, stream); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:libopenshottracker.Frame) - return target; -} - -size_t Frame::ByteSizeLong() const { -// @@protoc_insertion_point(message_byte_size_start:libopenshottracker.Frame) - size_t total_size = 0; - - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void) cached_has_bits; - - // .libopenshottracker.Frame.Box bounding_box = 3; - if (this->has_bounding_box()) { - total_size += 1 + - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( - *bounding_box_); - } - - // int32 id = 1; - if (this->id() != 0) { - total_size += 1 + - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( - this->_internal_id()); - } - - // float rotation = 2; - if (!(this->rotation() <= 0 && this->rotation() >= 0)) { - total_size += 1 + 4; - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( - _internal_metadata_, total_size, &_cached_size_); - } - int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); - SetCachedSize(cached_size); - return total_size; -} - -void Frame::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { -// @@protoc_insertion_point(generalized_merge_from_start:libopenshottracker.Frame) - GOOGLE_DCHECK_NE(&from, this); - const Frame* source = - ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( - &from); - if (source == nullptr) { - // @@protoc_insertion_point(generalized_merge_from_cast_fail:libopenshottracker.Frame) - ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); - } else { - // @@protoc_insertion_point(generalized_merge_from_cast_success:libopenshottracker.Frame) - MergeFrom(*source); - } -} - -void Frame::MergeFrom(const Frame& from) { -// @@protoc_insertion_point(class_specific_merge_from_start:libopenshottracker.Frame) - GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - if (from.has_bounding_box()) { - _internal_mutable_bounding_box()->::libopenshottracker::Frame_Box::MergeFrom(from._internal_bounding_box()); - } - if (from.id() != 0) { - _internal_set_id(from._internal_id()); - } - if (!(from.rotation() <= 0 && from.rotation() >= 0)) { - _internal_set_rotation(from._internal_rotation()); - } -} - -void Frame::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { -// @@protoc_insertion_point(generalized_copy_from_start:libopenshottracker.Frame) - if (&from == this) return; - Clear(); - MergeFrom(from); -} - -void Frame::CopyFrom(const Frame& from) { -// @@protoc_insertion_point(class_specific_copy_from_start:libopenshottracker.Frame) - if (&from == this) return; - Clear(); - MergeFrom(from); -} - -bool Frame::IsInitialized() const { - return true; -} - -void Frame::InternalSwap(Frame* other) { - using std::swap; - _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); - ::PROTOBUF_NAMESPACE_ID::internal::memswap< - PROTOBUF_FIELD_OFFSET(Frame, rotation_) - + sizeof(Frame::rotation_) - - PROTOBUF_FIELD_OFFSET(Frame, bounding_box_)>( - reinterpret_cast(&bounding_box_), - reinterpret_cast(&other->bounding_box_)); -} - -::PROTOBUF_NAMESPACE_ID::Metadata Frame::GetMetadata() const { - return GetMetadataStatic(); -} - - -// =================================================================== - -void Tracker::InitAsDefaultInstance() { - ::libopenshottracker::_Tracker_default_instance_._instance.get_mutable()->last_updated_ = const_cast< PROTOBUF_NAMESPACE_ID::Timestamp*>( - PROTOBUF_NAMESPACE_ID::Timestamp::internal_default_instance()); -} -class Tracker::_Internal { - public: - static const PROTOBUF_NAMESPACE_ID::Timestamp& last_updated(const Tracker* msg); -}; - -const PROTOBUF_NAMESPACE_ID::Timestamp& -Tracker::_Internal::last_updated(const Tracker* msg) { - return *msg->last_updated_; -} -void Tracker::clear_last_updated() { - if (GetArena() == nullptr && last_updated_ != nullptr) { - delete last_updated_; - } - last_updated_ = nullptr; -} -Tracker::Tracker(::PROTOBUF_NAMESPACE_ID::Arena* arena) - : ::PROTOBUF_NAMESPACE_ID::Message(arena), - frame_(arena) { - SharedCtor(); - RegisterArenaDtor(arena); - // @@protoc_insertion_point(arena_constructor:libopenshottracker.Tracker) -} -Tracker::Tracker(const Tracker& from) - : ::PROTOBUF_NAMESPACE_ID::Message(), - frame_(from.frame_) { - _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); - if (from._internal_has_last_updated()) { - last_updated_ = new PROTOBUF_NAMESPACE_ID::Timestamp(*from.last_updated_); - } else { - last_updated_ = nullptr; - } - // @@protoc_insertion_point(copy_constructor:libopenshottracker.Tracker) -} - -void Tracker::SharedCtor() { - ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_Tracker_trackerdata_2eproto.base); - last_updated_ = nullptr; -} - -Tracker::~Tracker() { - // @@protoc_insertion_point(destructor:libopenshottracker.Tracker) - SharedDtor(); - _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); -} - -void Tracker::SharedDtor() { - GOOGLE_DCHECK(GetArena() == nullptr); - if (this != internal_default_instance()) delete last_updated_; -} - -void Tracker::ArenaDtor(void* object) { - Tracker* _this = reinterpret_cast< Tracker* >(object); - (void)_this; -} -void Tracker::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { -} -void Tracker::SetCachedSize(int size) const { - _cached_size_.Set(size); -} -const Tracker& Tracker::default_instance() { - ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Tracker_trackerdata_2eproto.base); - return *internal_default_instance(); -} - - -void Tracker::Clear() { -// @@protoc_insertion_point(message_clear_start:libopenshottracker.Tracker) - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void) cached_has_bits; - - frame_.Clear(); - if (GetArena() == nullptr && last_updated_ != nullptr) { - delete last_updated_; - } - last_updated_ = nullptr; - _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); -} - -const char* Tracker::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { -#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure - ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena; - while (!ctx->Done(&ptr)) { - ::PROTOBUF_NAMESPACE_ID::uint32 tag; - ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); - CHK_(ptr); - switch (tag >> 3) { - // repeated .libopenshottracker.Frame frame = 1; - case 1: - if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) { - ptr -= 1; - do { - ptr += 1; - ptr = ctx->ParseMessage(_internal_add_frame(), ptr); - CHK_(ptr); - if (!ctx->DataAvailable(ptr)) break; - } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<10>(ptr)); - } else goto handle_unusual; - continue; - // .google.protobuf.Timestamp last_updated = 2; - case 2: - if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 18)) { - ptr = ctx->ParseMessage(_internal_mutable_last_updated(), ptr); - CHK_(ptr); - } else goto handle_unusual; - continue; - default: { - handle_unusual: - if ((tag & 7) == 4 || tag == 0) { - ctx->SetLastTag(tag); - goto success; - } - ptr = UnknownFieldParse(tag, - _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), - ptr, ctx); - CHK_(ptr != nullptr); - continue; - } - } // switch - } // while -success: - return ptr; -failure: - ptr = nullptr; - goto success; -#undef CHK_ -} - -::PROTOBUF_NAMESPACE_ID::uint8* Tracker::_InternalSerialize( - ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { - // @@protoc_insertion_point(serialize_to_array_start:libopenshottracker.Tracker) - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - // repeated .libopenshottracker.Frame frame = 1; - for (unsigned int i = 0, - n = static_cast(this->_internal_frame_size()); i < n; i++) { - target = stream->EnsureSpace(target); - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: - InternalWriteMessage(1, this->_internal_frame(i), target, stream); - } - - // .google.protobuf.Timestamp last_updated = 2; - if (this->has_last_updated()) { - target = stream->EnsureSpace(target); - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: - InternalWriteMessage( - 2, _Internal::last_updated(this), target, stream); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( - _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); - } - // @@protoc_insertion_point(serialize_to_array_end:libopenshottracker.Tracker) - return target; -} - -size_t Tracker::ByteSizeLong() const { -// @@protoc_insertion_point(message_byte_size_start:libopenshottracker.Tracker) - size_t total_size = 0; - - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - // Prevent compiler warnings about cached_has_bits being unused - (void) cached_has_bits; - - // repeated .libopenshottracker.Frame frame = 1; - total_size += 1UL * this->_internal_frame_size(); - for (const auto& msg : this->frame_) { - total_size += - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); - } - - // .google.protobuf.Timestamp last_updated = 2; - if (this->has_last_updated()) { - total_size += 1 + - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( - *last_updated_); - } - - if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { - return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( - _internal_metadata_, total_size, &_cached_size_); - } - int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); - SetCachedSize(cached_size); - return total_size; -} - -void Tracker::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { -// @@protoc_insertion_point(generalized_merge_from_start:libopenshottracker.Tracker) - GOOGLE_DCHECK_NE(&from, this); - const Tracker* source = - ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( - &from); - if (source == nullptr) { - // @@protoc_insertion_point(generalized_merge_from_cast_fail:libopenshottracker.Tracker) - ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); - } else { - // @@protoc_insertion_point(generalized_merge_from_cast_success:libopenshottracker.Tracker) - MergeFrom(*source); - } -} - -void Tracker::MergeFrom(const Tracker& from) { -// @@protoc_insertion_point(class_specific_merge_from_start:libopenshottracker.Tracker) - GOOGLE_DCHECK_NE(&from, this); - _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); - ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; - (void) cached_has_bits; - - frame_.MergeFrom(from.frame_); - if (from.has_last_updated()) { - _internal_mutable_last_updated()->PROTOBUF_NAMESPACE_ID::Timestamp::MergeFrom(from._internal_last_updated()); - } -} - -void Tracker::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { -// @@protoc_insertion_point(generalized_copy_from_start:libopenshottracker.Tracker) - if (&from == this) return; - Clear(); - MergeFrom(from); -} - -void Tracker::CopyFrom(const Tracker& from) { -// @@protoc_insertion_point(class_specific_copy_from_start:libopenshottracker.Tracker) - if (&from == this) return; - Clear(); - MergeFrom(from); -} - -bool Tracker::IsInitialized() const { - return true; -} - -void Tracker::InternalSwap(Tracker* other) { - using std::swap; - _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); - frame_.InternalSwap(&other->frame_); - swap(last_updated_, other->last_updated_); -} - -::PROTOBUF_NAMESPACE_ID::Metadata Tracker::GetMetadata() const { - return GetMetadataStatic(); -} - - -// @@protoc_insertion_point(namespace_scope) -} // namespace libopenshottracker -PROTOBUF_NAMESPACE_OPEN -template<> PROTOBUF_NOINLINE ::libopenshottracker::Frame_Box* Arena::CreateMaybeMessage< ::libopenshottracker::Frame_Box >(Arena* arena) { - return Arena::CreateMessageInternal< ::libopenshottracker::Frame_Box >(arena); -} -template<> PROTOBUF_NOINLINE ::libopenshottracker::Frame* Arena::CreateMaybeMessage< ::libopenshottracker::Frame >(Arena* arena) { - return Arena::CreateMessageInternal< ::libopenshottracker::Frame >(arena); -} -template<> PROTOBUF_NOINLINE ::libopenshottracker::Tracker* Arena::CreateMaybeMessage< ::libopenshottracker::Tracker >(Arena* arena) { - return Arena::CreateMessageInternal< ::libopenshottracker::Tracker >(arena); -} -PROTOBUF_NAMESPACE_CLOSE - -// @@protoc_insertion_point(global_scope) -#include diff --git a/src/trackerdata.pb.h b/src/trackerdata.pb.h deleted file mode 100644 index d30c6ef10..000000000 --- a/src/trackerdata.pb.h +++ /dev/null @@ -1,931 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: trackerdata.proto - -#ifndef GOOGLE_PROTOBUF_INCLUDED_trackerdata_2eproto -#define GOOGLE_PROTOBUF_INCLUDED_trackerdata_2eproto - -#include -#include - -#include -#if PROTOBUF_VERSION < 3012000 -#error This file was generated by a newer version of protoc which is -#error incompatible with your Protocol Buffer headers. Please update -#error your headers. -#endif -#if 3012003 < PROTOBUF_MIN_PROTOC_VERSION -#error This file was generated by an older version of protoc which is -#error incompatible with your Protocol Buffer headers. Please -#error regenerate this file with a newer version of protoc. -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include // IWYU pragma: export -#include // IWYU pragma: export -#include -#include -// @@protoc_insertion_point(includes) -#include -#define PROTOBUF_INTERNAL_EXPORT_trackerdata_2eproto -PROTOBUF_NAMESPACE_OPEN -namespace internal { -class AnyMetadata; -} // namespace internal -PROTOBUF_NAMESPACE_CLOSE - -// Internal implementation detail -- do not use these members. -struct TableStruct_trackerdata_2eproto { - static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[] - PROTOBUF_SECTION_VARIABLE(protodesc_cold); - static const ::PROTOBUF_NAMESPACE_ID::internal::AuxillaryParseTableField aux[] - PROTOBUF_SECTION_VARIABLE(protodesc_cold); - static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[3] - PROTOBUF_SECTION_VARIABLE(protodesc_cold); - static const ::PROTOBUF_NAMESPACE_ID::internal::FieldMetadata field_metadata[]; - static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[]; - static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[]; -}; -extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_trackerdata_2eproto; -namespace libopenshottracker { -class Frame; -class FrameDefaultTypeInternal; -extern FrameDefaultTypeInternal _Frame_default_instance_; -class Frame_Box; -class Frame_BoxDefaultTypeInternal; -extern Frame_BoxDefaultTypeInternal _Frame_Box_default_instance_; -class Tracker; -class TrackerDefaultTypeInternal; -extern TrackerDefaultTypeInternal _Tracker_default_instance_; -} // namespace libopenshottracker -PROTOBUF_NAMESPACE_OPEN -template<> ::libopenshottracker::Frame* Arena::CreateMaybeMessage<::libopenshottracker::Frame>(Arena*); -template<> ::libopenshottracker::Frame_Box* Arena::CreateMaybeMessage<::libopenshottracker::Frame_Box>(Arena*); -template<> ::libopenshottracker::Tracker* Arena::CreateMaybeMessage<::libopenshottracker::Tracker>(Arena*); -PROTOBUF_NAMESPACE_CLOSE -namespace libopenshottracker { - -// =================================================================== - -class Frame_Box PROTOBUF_FINAL : - public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:libopenshottracker.Frame.Box) */ { - public: - inline Frame_Box() : Frame_Box(nullptr) {}; - virtual ~Frame_Box(); - - Frame_Box(const Frame_Box& from); - Frame_Box(Frame_Box&& from) noexcept - : Frame_Box() { - *this = ::std::move(from); - } - - inline Frame_Box& operator=(const Frame_Box& from) { - CopyFrom(from); - return *this; - } - inline Frame_Box& operator=(Frame_Box&& from) noexcept { - if (GetArena() == from.GetArena()) { - if (this != &from) InternalSwap(&from); - } else { - CopyFrom(from); - } - return *this; - } - - static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { - return GetDescriptor(); - } - static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { - return GetMetadataStatic().descriptor; - } - static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { - return GetMetadataStatic().reflection; - } - static const Frame_Box& default_instance(); - - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY - static inline const Frame_Box* internal_default_instance() { - return reinterpret_cast( - &_Frame_Box_default_instance_); - } - static constexpr int kIndexInFileMessages = - 0; - - friend void swap(Frame_Box& a, Frame_Box& b) { - a.Swap(&b); - } - inline void Swap(Frame_Box* other) { - if (other == this) return; - if (GetArena() == other->GetArena()) { - InternalSwap(other); - } else { - ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); - } - } - void UnsafeArenaSwap(Frame_Box* other) { - if (other == this) return; - GOOGLE_DCHECK(GetArena() == other->GetArena()); - InternalSwap(other); - } - - // implements Message ---------------------------------------------- - - inline Frame_Box* New() const final { - return CreateMaybeMessage(nullptr); - } - - Frame_Box* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { - return CreateMaybeMessage(arena); - } - void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; - void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; - void CopyFrom(const Frame_Box& from); - void MergeFrom(const Frame_Box& from); - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; - bool IsInitialized() const final; - - size_t ByteSizeLong() const final; - const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; - ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( - ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; - int GetCachedSize() const final { return _cached_size_.Get(); } - - private: - inline void SharedCtor(); - inline void SharedDtor(); - void SetCachedSize(int size) const final; - void InternalSwap(Frame_Box* other); - friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; - static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { - return "libopenshottracker.Frame.Box"; - } - protected: - explicit Frame_Box(::PROTOBUF_NAMESPACE_ID::Arena* arena); - private: - static void ArenaDtor(void* object); - inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); - public: - - ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; - private: - static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { - ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_trackerdata_2eproto); - return ::descriptor_table_trackerdata_2eproto.file_level_metadata[kIndexInFileMessages]; - } - - public: - - // nested types ---------------------------------------------------- - - // accessors ------------------------------------------------------- - - enum : int { - kX1FieldNumber = 1, - kY1FieldNumber = 2, - kX2FieldNumber = 3, - kY2FieldNumber = 4, - }; - // float x1 = 1; - void clear_x1(); - float x1() const; - void set_x1(float value); - private: - float _internal_x1() const; - void _internal_set_x1(float value); - public: - - // float y1 = 2; - void clear_y1(); - float y1() const; - void set_y1(float value); - private: - float _internal_y1() const; - void _internal_set_y1(float value); - public: - - // float x2 = 3; - void clear_x2(); - float x2() const; - void set_x2(float value); - private: - float _internal_x2() const; - void _internal_set_x2(float value); - public: - - // float y2 = 4; - void clear_y2(); - float y2() const; - void set_y2(float value); - private: - float _internal_y2() const; - void _internal_set_y2(float value); - public: - - // @@protoc_insertion_point(class_scope:libopenshottracker.Frame.Box) - private: - class _Internal; - - template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; - typedef void InternalArenaConstructable_; - typedef void DestructorSkippable_; - float x1_; - float y1_; - float x2_; - float y2_; - mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; - friend struct ::TableStruct_trackerdata_2eproto; -}; -// ------------------------------------------------------------------- - -class Frame PROTOBUF_FINAL : - public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:libopenshottracker.Frame) */ { - public: - inline Frame() : Frame(nullptr) {}; - virtual ~Frame(); - - Frame(const Frame& from); - Frame(Frame&& from) noexcept - : Frame() { - *this = ::std::move(from); - } - - inline Frame& operator=(const Frame& from) { - CopyFrom(from); - return *this; - } - inline Frame& operator=(Frame&& from) noexcept { - if (GetArena() == from.GetArena()) { - if (this != &from) InternalSwap(&from); - } else { - CopyFrom(from); - } - return *this; - } - - static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { - return GetDescriptor(); - } - static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { - return GetMetadataStatic().descriptor; - } - static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { - return GetMetadataStatic().reflection; - } - static const Frame& default_instance(); - - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY - static inline const Frame* internal_default_instance() { - return reinterpret_cast( - &_Frame_default_instance_); - } - static constexpr int kIndexInFileMessages = - 1; - - friend void swap(Frame& a, Frame& b) { - a.Swap(&b); - } - inline void Swap(Frame* other) { - if (other == this) return; - if (GetArena() == other->GetArena()) { - InternalSwap(other); - } else { - ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); - } - } - void UnsafeArenaSwap(Frame* other) { - if (other == this) return; - GOOGLE_DCHECK(GetArena() == other->GetArena()); - InternalSwap(other); - } - - // implements Message ---------------------------------------------- - - inline Frame* New() const final { - return CreateMaybeMessage(nullptr); - } - - Frame* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { - return CreateMaybeMessage(arena); - } - void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; - void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; - void CopyFrom(const Frame& from); - void MergeFrom(const Frame& from); - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; - bool IsInitialized() const final; - - size_t ByteSizeLong() const final; - const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; - ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( - ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; - int GetCachedSize() const final { return _cached_size_.Get(); } - - private: - inline void SharedCtor(); - inline void SharedDtor(); - void SetCachedSize(int size) const final; - void InternalSwap(Frame* other); - friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; - static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { - return "libopenshottracker.Frame"; - } - protected: - explicit Frame(::PROTOBUF_NAMESPACE_ID::Arena* arena); - private: - static void ArenaDtor(void* object); - inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); - public: - - ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; - private: - static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { - ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_trackerdata_2eproto); - return ::descriptor_table_trackerdata_2eproto.file_level_metadata[kIndexInFileMessages]; - } - - public: - - // nested types ---------------------------------------------------- - - typedef Frame_Box Box; - - // accessors ------------------------------------------------------- - - enum : int { - kBoundingBoxFieldNumber = 3, - kIdFieldNumber = 1, - kRotationFieldNumber = 2, - }; - // .libopenshottracker.Frame.Box bounding_box = 3; - bool has_bounding_box() const; - private: - bool _internal_has_bounding_box() const; - public: - void clear_bounding_box(); - const ::libopenshottracker::Frame_Box& bounding_box() const; - ::libopenshottracker::Frame_Box* release_bounding_box(); - ::libopenshottracker::Frame_Box* mutable_bounding_box(); - void set_allocated_bounding_box(::libopenshottracker::Frame_Box* bounding_box); - private: - const ::libopenshottracker::Frame_Box& _internal_bounding_box() const; - ::libopenshottracker::Frame_Box* _internal_mutable_bounding_box(); - public: - void unsafe_arena_set_allocated_bounding_box( - ::libopenshottracker::Frame_Box* bounding_box); - ::libopenshottracker::Frame_Box* unsafe_arena_release_bounding_box(); - - // int32 id = 1; - void clear_id(); - ::PROTOBUF_NAMESPACE_ID::int32 id() const; - void set_id(::PROTOBUF_NAMESPACE_ID::int32 value); - private: - ::PROTOBUF_NAMESPACE_ID::int32 _internal_id() const; - void _internal_set_id(::PROTOBUF_NAMESPACE_ID::int32 value); - public: - - // float rotation = 2; - void clear_rotation(); - float rotation() const; - void set_rotation(float value); - private: - float _internal_rotation() const; - void _internal_set_rotation(float value); - public: - - // @@protoc_insertion_point(class_scope:libopenshottracker.Frame) - private: - class _Internal; - - template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; - typedef void InternalArenaConstructable_; - typedef void DestructorSkippable_; - ::libopenshottracker::Frame_Box* bounding_box_; - ::PROTOBUF_NAMESPACE_ID::int32 id_; - float rotation_; - mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; - friend struct ::TableStruct_trackerdata_2eproto; -}; -// ------------------------------------------------------------------- - -class Tracker PROTOBUF_FINAL : - public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:libopenshottracker.Tracker) */ { - public: - inline Tracker() : Tracker(nullptr) {}; - virtual ~Tracker(); - - Tracker(const Tracker& from); - Tracker(Tracker&& from) noexcept - : Tracker() { - *this = ::std::move(from); - } - - inline Tracker& operator=(const Tracker& from) { - CopyFrom(from); - return *this; - } - inline Tracker& operator=(Tracker&& from) noexcept { - if (GetArena() == from.GetArena()) { - if (this != &from) InternalSwap(&from); - } else { - CopyFrom(from); - } - return *this; - } - - static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { - return GetDescriptor(); - } - static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { - return GetMetadataStatic().descriptor; - } - static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { - return GetMetadataStatic().reflection; - } - static const Tracker& default_instance(); - - static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY - static inline const Tracker* internal_default_instance() { - return reinterpret_cast( - &_Tracker_default_instance_); - } - static constexpr int kIndexInFileMessages = - 2; - - friend void swap(Tracker& a, Tracker& b) { - a.Swap(&b); - } - inline void Swap(Tracker* other) { - if (other == this) return; - if (GetArena() == other->GetArena()) { - InternalSwap(other); - } else { - ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); - } - } - void UnsafeArenaSwap(Tracker* other) { - if (other == this) return; - GOOGLE_DCHECK(GetArena() == other->GetArena()); - InternalSwap(other); - } - - // implements Message ---------------------------------------------- - - inline Tracker* New() const final { - return CreateMaybeMessage(nullptr); - } - - Tracker* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { - return CreateMaybeMessage(arena); - } - void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; - void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; - void CopyFrom(const Tracker& from); - void MergeFrom(const Tracker& from); - PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; - bool IsInitialized() const final; - - size_t ByteSizeLong() const final; - const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; - ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( - ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; - int GetCachedSize() const final { return _cached_size_.Get(); } - - private: - inline void SharedCtor(); - inline void SharedDtor(); - void SetCachedSize(int size) const final; - void InternalSwap(Tracker* other); - friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; - static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { - return "libopenshottracker.Tracker"; - } - protected: - explicit Tracker(::PROTOBUF_NAMESPACE_ID::Arena* arena); - private: - static void ArenaDtor(void* object); - inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); - public: - - ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; - private: - static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { - ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_trackerdata_2eproto); - return ::descriptor_table_trackerdata_2eproto.file_level_metadata[kIndexInFileMessages]; - } - - public: - - // nested types ---------------------------------------------------- - - // accessors ------------------------------------------------------- - - enum : int { - kFrameFieldNumber = 1, - kLastUpdatedFieldNumber = 2, - }; - // repeated .libopenshottracker.Frame frame = 1; - int frame_size() const; - private: - int _internal_frame_size() const; - public: - void clear_frame(); - ::libopenshottracker::Frame* mutable_frame(int index); - ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::libopenshottracker::Frame >* - mutable_frame(); - private: - const ::libopenshottracker::Frame& _internal_frame(int index) const; - ::libopenshottracker::Frame* _internal_add_frame(); - public: - const ::libopenshottracker::Frame& frame(int index) const; - ::libopenshottracker::Frame* add_frame(); - const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::libopenshottracker::Frame >& - frame() const; - - // .google.protobuf.Timestamp last_updated = 2; - bool has_last_updated() const; - private: - bool _internal_has_last_updated() const; - public: - void clear_last_updated(); - const PROTOBUF_NAMESPACE_ID::Timestamp& last_updated() const; - PROTOBUF_NAMESPACE_ID::Timestamp* release_last_updated(); - PROTOBUF_NAMESPACE_ID::Timestamp* mutable_last_updated(); - void set_allocated_last_updated(PROTOBUF_NAMESPACE_ID::Timestamp* last_updated); - private: - const PROTOBUF_NAMESPACE_ID::Timestamp& _internal_last_updated() const; - PROTOBUF_NAMESPACE_ID::Timestamp* _internal_mutable_last_updated(); - public: - void unsafe_arena_set_allocated_last_updated( - PROTOBUF_NAMESPACE_ID::Timestamp* last_updated); - PROTOBUF_NAMESPACE_ID::Timestamp* unsafe_arena_release_last_updated(); - - // @@protoc_insertion_point(class_scope:libopenshottracker.Tracker) - private: - class _Internal; - - template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; - typedef void InternalArenaConstructable_; - typedef void DestructorSkippable_; - ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::libopenshottracker::Frame > frame_; - PROTOBUF_NAMESPACE_ID::Timestamp* last_updated_; - mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; - friend struct ::TableStruct_trackerdata_2eproto; -}; -// =================================================================== - - -// =================================================================== - -#ifdef __GNUC__ - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wstrict-aliasing" -#endif // __GNUC__ -// Frame_Box - -// float x1 = 1; -inline void Frame_Box::clear_x1() { - x1_ = 0; -} -inline float Frame_Box::_internal_x1() const { - return x1_; -} -inline float Frame_Box::x1() const { - // @@protoc_insertion_point(field_get:libopenshottracker.Frame.Box.x1) - return _internal_x1(); -} -inline void Frame_Box::_internal_set_x1(float value) { - - x1_ = value; -} -inline void Frame_Box::set_x1(float value) { - _internal_set_x1(value); - // @@protoc_insertion_point(field_set:libopenshottracker.Frame.Box.x1) -} - -// float y1 = 2; -inline void Frame_Box::clear_y1() { - y1_ = 0; -} -inline float Frame_Box::_internal_y1() const { - return y1_; -} -inline float Frame_Box::y1() const { - // @@protoc_insertion_point(field_get:libopenshottracker.Frame.Box.y1) - return _internal_y1(); -} -inline void Frame_Box::_internal_set_y1(float value) { - - y1_ = value; -} -inline void Frame_Box::set_y1(float value) { - _internal_set_y1(value); - // @@protoc_insertion_point(field_set:libopenshottracker.Frame.Box.y1) -} - -// float x2 = 3; -inline void Frame_Box::clear_x2() { - x2_ = 0; -} -inline float Frame_Box::_internal_x2() const { - return x2_; -} -inline float Frame_Box::x2() const { - // @@protoc_insertion_point(field_get:libopenshottracker.Frame.Box.x2) - return _internal_x2(); -} -inline void Frame_Box::_internal_set_x2(float value) { - - x2_ = value; -} -inline void Frame_Box::set_x2(float value) { - _internal_set_x2(value); - // @@protoc_insertion_point(field_set:libopenshottracker.Frame.Box.x2) -} - -// float y2 = 4; -inline void Frame_Box::clear_y2() { - y2_ = 0; -} -inline float Frame_Box::_internal_y2() const { - return y2_; -} -inline float Frame_Box::y2() const { - // @@protoc_insertion_point(field_get:libopenshottracker.Frame.Box.y2) - return _internal_y2(); -} -inline void Frame_Box::_internal_set_y2(float value) { - - y2_ = value; -} -inline void Frame_Box::set_y2(float value) { - _internal_set_y2(value); - // @@protoc_insertion_point(field_set:libopenshottracker.Frame.Box.y2) -} - -// ------------------------------------------------------------------- - -// Frame - -// int32 id = 1; -inline void Frame::clear_id() { - id_ = 0; -} -inline ::PROTOBUF_NAMESPACE_ID::int32 Frame::_internal_id() const { - return id_; -} -inline ::PROTOBUF_NAMESPACE_ID::int32 Frame::id() const { - // @@protoc_insertion_point(field_get:libopenshottracker.Frame.id) - return _internal_id(); -} -inline void Frame::_internal_set_id(::PROTOBUF_NAMESPACE_ID::int32 value) { - - id_ = value; -} -inline void Frame::set_id(::PROTOBUF_NAMESPACE_ID::int32 value) { - _internal_set_id(value); - // @@protoc_insertion_point(field_set:libopenshottracker.Frame.id) -} - -// float rotation = 2; -inline void Frame::clear_rotation() { - rotation_ = 0; -} -inline float Frame::_internal_rotation() const { - return rotation_; -} -inline float Frame::rotation() const { - // @@protoc_insertion_point(field_get:libopenshottracker.Frame.rotation) - return _internal_rotation(); -} -inline void Frame::_internal_set_rotation(float value) { - - rotation_ = value; -} -inline void Frame::set_rotation(float value) { - _internal_set_rotation(value); - // @@protoc_insertion_point(field_set:libopenshottracker.Frame.rotation) -} - -// .libopenshottracker.Frame.Box bounding_box = 3; -inline bool Frame::_internal_has_bounding_box() const { - return this != internal_default_instance() && bounding_box_ != nullptr; -} -inline bool Frame::has_bounding_box() const { - return _internal_has_bounding_box(); -} -inline void Frame::clear_bounding_box() { - if (GetArena() == nullptr && bounding_box_ != nullptr) { - delete bounding_box_; - } - bounding_box_ = nullptr; -} -inline const ::libopenshottracker::Frame_Box& Frame::_internal_bounding_box() const { - const ::libopenshottracker::Frame_Box* p = bounding_box_; - return p != nullptr ? *p : *reinterpret_cast( - &::libopenshottracker::_Frame_Box_default_instance_); -} -inline const ::libopenshottracker::Frame_Box& Frame::bounding_box() const { - // @@protoc_insertion_point(field_get:libopenshottracker.Frame.bounding_box) - return _internal_bounding_box(); -} -inline void Frame::unsafe_arena_set_allocated_bounding_box( - ::libopenshottracker::Frame_Box* bounding_box) { - if (GetArena() == nullptr) { - delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(bounding_box_); - } - bounding_box_ = bounding_box; - if (bounding_box) { - - } else { - - } - // @@protoc_insertion_point(field_unsafe_arena_set_allocated:libopenshottracker.Frame.bounding_box) -} -inline ::libopenshottracker::Frame_Box* Frame::release_bounding_box() { - auto temp = unsafe_arena_release_bounding_box(); - if (GetArena() != nullptr) { - temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); - } - return temp; -} -inline ::libopenshottracker::Frame_Box* Frame::unsafe_arena_release_bounding_box() { - // @@protoc_insertion_point(field_release:libopenshottracker.Frame.bounding_box) - - ::libopenshottracker::Frame_Box* temp = bounding_box_; - bounding_box_ = nullptr; - return temp; -} -inline ::libopenshottracker::Frame_Box* Frame::_internal_mutable_bounding_box() { - - if (bounding_box_ == nullptr) { - auto* p = CreateMaybeMessage<::libopenshottracker::Frame_Box>(GetArena()); - bounding_box_ = p; - } - return bounding_box_; -} -inline ::libopenshottracker::Frame_Box* Frame::mutable_bounding_box() { - // @@protoc_insertion_point(field_mutable:libopenshottracker.Frame.bounding_box) - return _internal_mutable_bounding_box(); -} -inline void Frame::set_allocated_bounding_box(::libopenshottracker::Frame_Box* bounding_box) { - ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArena(); - if (message_arena == nullptr) { - delete bounding_box_; - } - if (bounding_box) { - ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = - ::PROTOBUF_NAMESPACE_ID::Arena::GetArena(bounding_box); - if (message_arena != submessage_arena) { - bounding_box = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( - message_arena, bounding_box, submessage_arena); - } - - } else { - - } - bounding_box_ = bounding_box; - // @@protoc_insertion_point(field_set_allocated:libopenshottracker.Frame.bounding_box) -} - -// ------------------------------------------------------------------- - -// Tracker - -// repeated .libopenshottracker.Frame frame = 1; -inline int Tracker::_internal_frame_size() const { - return frame_.size(); -} -inline int Tracker::frame_size() const { - return _internal_frame_size(); -} -inline void Tracker::clear_frame() { - frame_.Clear(); -} -inline ::libopenshottracker::Frame* Tracker::mutable_frame(int index) { - // @@protoc_insertion_point(field_mutable:libopenshottracker.Tracker.frame) - return frame_.Mutable(index); -} -inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::libopenshottracker::Frame >* -Tracker::mutable_frame() { - // @@protoc_insertion_point(field_mutable_list:libopenshottracker.Tracker.frame) - return &frame_; -} -inline const ::libopenshottracker::Frame& Tracker::_internal_frame(int index) const { - return frame_.Get(index); -} -inline const ::libopenshottracker::Frame& Tracker::frame(int index) const { - // @@protoc_insertion_point(field_get:libopenshottracker.Tracker.frame) - return _internal_frame(index); -} -inline ::libopenshottracker::Frame* Tracker::_internal_add_frame() { - return frame_.Add(); -} -inline ::libopenshottracker::Frame* Tracker::add_frame() { - // @@protoc_insertion_point(field_add:libopenshottracker.Tracker.frame) - return _internal_add_frame(); -} -inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::libopenshottracker::Frame >& -Tracker::frame() const { - // @@protoc_insertion_point(field_list:libopenshottracker.Tracker.frame) - return frame_; -} - -// .google.protobuf.Timestamp last_updated = 2; -inline bool Tracker::_internal_has_last_updated() const { - return this != internal_default_instance() && last_updated_ != nullptr; -} -inline bool Tracker::has_last_updated() const { - return _internal_has_last_updated(); -} -inline const PROTOBUF_NAMESPACE_ID::Timestamp& Tracker::_internal_last_updated() const { - const PROTOBUF_NAMESPACE_ID::Timestamp* p = last_updated_; - return p != nullptr ? *p : *reinterpret_cast( - &PROTOBUF_NAMESPACE_ID::_Timestamp_default_instance_); -} -inline const PROTOBUF_NAMESPACE_ID::Timestamp& Tracker::last_updated() const { - // @@protoc_insertion_point(field_get:libopenshottracker.Tracker.last_updated) - return _internal_last_updated(); -} -inline void Tracker::unsafe_arena_set_allocated_last_updated( - PROTOBUF_NAMESPACE_ID::Timestamp* last_updated) { - if (GetArena() == nullptr) { - delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(last_updated_); - } - last_updated_ = last_updated; - if (last_updated) { - - } else { - - } - // @@protoc_insertion_point(field_unsafe_arena_set_allocated:libopenshottracker.Tracker.last_updated) -} -inline PROTOBUF_NAMESPACE_ID::Timestamp* Tracker::release_last_updated() { - auto temp = unsafe_arena_release_last_updated(); - if (GetArena() != nullptr) { - temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); - } - return temp; -} -inline PROTOBUF_NAMESPACE_ID::Timestamp* Tracker::unsafe_arena_release_last_updated() { - // @@protoc_insertion_point(field_release:libopenshottracker.Tracker.last_updated) - - PROTOBUF_NAMESPACE_ID::Timestamp* temp = last_updated_; - last_updated_ = nullptr; - return temp; -} -inline PROTOBUF_NAMESPACE_ID::Timestamp* Tracker::_internal_mutable_last_updated() { - - if (last_updated_ == nullptr) { - auto* p = CreateMaybeMessage(GetArena()); - last_updated_ = p; - } - return last_updated_; -} -inline PROTOBUF_NAMESPACE_ID::Timestamp* Tracker::mutable_last_updated() { - // @@protoc_insertion_point(field_mutable:libopenshottracker.Tracker.last_updated) - return _internal_mutable_last_updated(); -} -inline void Tracker::set_allocated_last_updated(PROTOBUF_NAMESPACE_ID::Timestamp* last_updated) { - ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArena(); - if (message_arena == nullptr) { - delete reinterpret_cast< ::PROTOBUF_NAMESPACE_ID::MessageLite*>(last_updated_); - } - if (last_updated) { - ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = - reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(last_updated)->GetArena(); - if (message_arena != submessage_arena) { - last_updated = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( - message_arena, last_updated, submessage_arena); - } - - } else { - - } - last_updated_ = last_updated; - // @@protoc_insertion_point(field_set_allocated:libopenshottracker.Tracker.last_updated) -} - -#ifdef __GNUC__ - #pragma GCC diagnostic pop -#endif // __GNUC__ -// ------------------------------------------------------------------- - -// ------------------------------------------------------------------- - - -// @@protoc_insertion_point(namespace_scope) - -} // namespace libopenshottracker - -// @@protoc_insertion_point(global_scope) - -#include -#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_trackerdata_2eproto From 60cec478d32547fab065ec6667ef243d1163d565 Mon Sep 17 00:00:00 2001 From: Brenno Date: Sat, 12 Dec 2020 20:23:34 -0300 Subject: [PATCH 10/84] Refactored KeyframeBBox -Moved the methods that handles protobuf data from Tracker to KeyframeBBox -Displacement and scale keyframes are now properties of KeyframeBBox -Changed interface that updates the KeyframeBBox properties. --- src/EffectBase.h | 8 + src/KeyFrameBBox.cpp | 659 ++++++++++++++++++++------------------- src/KeyFrameBBox.h | 203 ++++++------ src/effects/Tracker.cpp | 223 ++++++------- src/effects/Tracker.h | 52 +-- tests/KeyFrame_Tests.cpp | 53 ++-- 6 files changed, 589 insertions(+), 609 deletions(-) diff --git a/src/EffectBase.h b/src/EffectBase.h index 353e18177..090637e7e 100644 --- a/src/EffectBase.h +++ b/src/EffectBase.h @@ -97,6 +97,14 @@ namespace openshot virtual void SetJson(const std::string value) = 0; ///< Load JSON string into this object virtual Json::Value JsonValue() const = 0; ///< Generate Json::Value for this object virtual void SetJsonValue(const Json::Value root) = 0; ///< Load Json::Value into this object + + virtual std::string Json(int64_t requested_frame) const{ + return {}; + }; + virtual void SetJson(int64_t requested_frame, const std::string value) { + return; + }; + Json::Value JsonInfo() const; ///< Generate JSON object of meta data / info /// Get the order that this effect should be executed. diff --git a/src/KeyFrameBBox.cpp b/src/KeyFrameBBox.cpp index 870506a8e..2a8610145 100644 --- a/src/KeyFrameBBox.cpp +++ b/src/KeyFrameBBox.cpp @@ -30,441 +30,456 @@ #include "KeyFrameBBox.h" #include +#include +#include #include -//#include "Point.h" -//#include + +//#define PI 3.14159265 using namespace std; using namespace openshot; -namespace { - bool IsPointBeforeX(Point const & p, double const x) { - return p.co.X < x; - } - - double InterpolateLinearCurve(Point const & left, Point const & right, double const target) { - double const diff_Y = right.co.Y - left.co.Y; - double const diff_X = right.co.X - left.co.X; - double const slope = diff_Y / diff_X; - return left.co.Y + slope * (target - left.co.X); - } - - double InterpolateBezierCurve(Point const & left, Point const & right, double const target, double const allowed_error) { - double const X_diff = right.co.X - left.co.X; - double const Y_diff = right.co.Y - left.co.Y; - Coordinate const p0 = left.co; - Coordinate const p1 = Coordinate(p0.X + left.handle_right.X * X_diff, p0.Y + left.handle_right.Y * Y_diff); - Coordinate const p2 = Coordinate(p0.X + right.handle_left.X * X_diff, p0.Y + right.handle_left.Y * Y_diff); - Coordinate const p3 = right.co; - - double t = 0.5; - double t_step = 0.25; - do { - // Bernstein polynoms - double B[4] = {1, 3, 3, 1}; - double oneMinTExp = 1; - double tExp = 1; - for (int i = 0; i < 4; ++i, tExp *= t) { - B[i] *= tExp; - } - for (int i = 0; i < 4; ++i, oneMinTExp *= 1 - t) { - B[4 - i - 1] *= oneMinTExp; - } - double const x = p0.X * B[0] + p1.X * B[1] + p2.X * B[2] + p3.X * B[3]; - double const y = p0.Y * B[0] + p1.Y * B[1] + p2.Y * B[2] + p3.Y * B[3]; - if (fabs(target - x) < allowed_error) { - return y; - } - if (x > target) { - t -= t_step; - } - else { - t += t_step; - } - t_step /= 2; - } while (true); - } - - - double InterpolateBetween(Point const & left, Point const & right, double target, double allowed_error) { - assert(left.co.X < target); - assert(target <= right.co.X); - switch (right.interpolation) { - case CONSTANT: return left.co.Y; - case LINEAR: return InterpolateLinearCurve(left, right, target); - case BEZIER: return InterpolateBezierCurve(left, right, target, allowed_error); - } - } - - - template - int64_t SearchBetweenPoints(Point const & left, Point const & right, int64_t const current, Check check) { - int64_t start = left.co.X; - int64_t stop = right.co.X; - while (start < stop) { - int64_t const mid = (start + stop + 1) / 2; - double const value = InterpolateBetween(left, right, mid, 0.01); - if (check(round(value), current)) { - start = mid; - } else { - stop = mid - 1; - } - } - return start; - } -} - -/* -KeyFrameBBox::KeyFrameBBox(): delta_x(0.0), delta_y(0.0), scale_x(0.0), scale_y(0.0), rotation(0.0) { - this->TimeScale = 1.0; - return; -} -*/ - - -KeyFrameBBox::KeyFrameBBox(){ - this->TimeScale = 1.0; - return; -} -/* -void KeyFrameBBox::AddDisplacement(int64_t frame_num, double _delta_x, double _delta_y){ - if (!this->Contains((int64_t) frame_num)) - return; - - double time = this->FrameNToTime(frame_num, 1.0); +namespace openshot +{ + bool IsPointBeforeX(Point const &p, double const x) + { + return p.co.X < x; + } - if (_delta_x != 0.0) - delta_x.AddPoint(time, _delta_x, openshot::InterpolationType::LINEAR); - if (_delta_y != 0.0) - delta_y.AddPoint(time, _delta_y, openshot::InterpolationType::LINEAR); + double InterpolateLinearCurve(Point const &left, Point const &right, double const target) + { + double const diff_Y = right.co.Y - left.co.Y; + double const diff_X = right.co.X - left.co.X; + double const slope = diff_Y / diff_X; + return left.co.Y + slope * (target - left.co.X); + } - return; -} + double InterpolateBezierCurve(Point const &left, Point const &right, double const target, double const allowed_error) + { + double const X_diff = right.co.X - left.co.X; + double const Y_diff = right.co.Y - left.co.Y; + Coordinate const p0 = left.co; + Coordinate const p1 = Coordinate(p0.X + left.handle_right.X * X_diff, p0.Y + left.handle_right.Y * Y_diff); + Coordinate const p2 = Coordinate(p0.X + right.handle_left.X * X_diff, p0.Y + right.handle_left.Y * Y_diff); + Coordinate const p3 = right.co; + + double t = 0.5; + double t_step = 0.25; + do + { + // Bernstein polynoms + double B[4] = {1, 3, 3, 1}; + double oneMinTExp = 1; + double tExp = 1; + for (int i = 0; i < 4; ++i, tExp *= t) + { + B[i] *= tExp; + } + for (int i = 0; i < 4; ++i, oneMinTExp *= 1 - t) + { + B[4 - i - 1] *= oneMinTExp; + } + double const x = p0.X * B[0] + p1.X * B[1] + p2.X * B[2] + p3.X * B[3]; + double const y = p0.Y * B[0] + p1.Y * B[1] + p2.Y * B[2] + p3.Y * B[3]; + if (fabs(target - x) < allowed_error) + { + return y; + } + if (x > target) + { + t -= t_step; + } + else + { + t += t_step; + } + t_step /= 2; + } while (true); + } -void KeyFrameBBox::AddScale(int64_t frame_num, double _scale_x, double _scale_y){ - if (!this->Contains((double) frame_num)) - return; + double InterpolateBetween(Point const &left, Point const &right, double target, double allowed_error) + { + assert(left.co.X < target); + assert(target <= right.co.X); + switch (right.interpolation) + { + case CONSTANT: + return left.co.Y; + case LINEAR: + return InterpolateLinearCurve(left, right, target); + case BEZIER: + return InterpolateBezierCurve(left, right, target, allowed_error); + } + } - double time = this->FrameNToTime(frame_num, 1.0); + template + int64_t SearchBetweenPoints(Point const &left, Point const &right, int64_t const current, Check check) + { + int64_t start = left.co.X; + int64_t stop = right.co.X; + while (start < stop) + { + int64_t const mid = (start + stop + 1) / 2; + double const value = InterpolateBetween(left, right, mid, 0.01); + if (check(round(value), current)) + { + start = mid; + } + else + { + stop = mid - 1; + } + } + return start; + } +} // namespace openshot - if (_scale_x != 0.0) - scale_x.AddPoint(time, _scale_x, openshot::InterpolationType::LINEAR); - if (_scale_y != 0.0) - scale_y.AddPoint(time, _scale_y, openshot::InterpolationType::LINEAR); - +// Default Constructor that sets the bounding-box displacement as 0 and the scales as 1 for the first frame +KeyFrameBBox::KeyFrameBBox() : delta_x(0.0), delta_y(0.0), scale_x(1.0), scale_y(1.0), rotation(0.0) +{ + this->TimeScale = 1.0; return; } -void KeyFrameBBox::AddRotation(int64_t _frame_num, double rot){ - if (!this->Contains((double) _frame_num)) - return; - - double time = this->FrameNToTime(_frame_num, 1.0); - - rotation.AddPoint(time, rot, openshot::InterpolationType::LINEAR); -} -*/ -void KeyFrameBBox::AddBox(int64_t _frame_num , float _x1, float _y1, float _width, float _height){ - +// Add a BBox to the BoxVec map +void KeyFrameBBox::AddBox(int64_t _frame_num, float _x1, float _y1, float _width, float _height) +{ + // Check if the given frame number is valid if (_frame_num < 0) return; - BBox box = BBox(_x1, _y1, _width, _height); + // Instantiate a new bounding-box + BBox newBBox = BBox(_x1, _y1, _width, _height); + // Get the time of given frame double time = this->FrameNToTime(_frame_num, 1.0); - - auto it = BoxVec.find(time); - if (it != BoxVec.end()) - it->second = box; + // Create an iterator that points to the BoxVec pair indexed by the time of given frame + auto BBoxIterator = BoxVec.find(time); + + if (BBoxIterator != BoxVec.end()) + { + // There is a bounding-box indexed by the time of given frame, update-it + BBoxIterator->second = newBBox; + } else - BoxVec.insert({time, box}); + { + // There isn't a bounding-box indexed by the time of given frame, insert a new one + BoxVec.insert({time, newBBox}); + } } -int64_t KeyFrameBBox::GetLength() const{ - - if (BoxVec.empty()) +// Get the size of BoxVec map +int64_t KeyFrameBBox::GetLength() const +{ + if (BoxVec.empty()) return 0; - if (BoxVec.size() == 1) + if (BoxVec.size() == 1) return 1; - return BoxVec.size(); } -bool KeyFrameBBox::Contains(int64_t frame_num) { - +// Check if there is a bounding-box in the given frame +bool KeyFrameBBox::Contains(int64_t frame_num) +{ + // 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()) + // BoxVec pair not found return false; - return true; } -void KeyFrameBBox::RemovePoint(int64_t frame_number){ - +// Remove a bounding-box from the BoxVec map +void KeyFrameBBox::RemoveBox(int64_t frame_number) +{ + // Get the time of given frame double time = this->FrameNToTime(frame_number, 1.0); - + // Create an iterator that points to the BoxVec pair indexed by the time of given frame auto it = BoxVec.find(time); - if (it != BoxVec.end()){ + if (it != BoxVec.end()) + { + // The BoxVec pair exists, so remove it BoxVec.erase(time); - - //RemoveDelta(time); - //RemoveScale(time); } return; } -/* -void KeyFrameBBox::RemoveDelta(int64_t frame_number) { - - double time = this->FrameNToTime(frame_number, 1.0); - - double attr_x = this->delta_x.GetValue(time); - Point point_x = this->delta_x.GetClosestPoint(Point((double) time, attr_x)); - if (point_x.co.X == (double) time) - this->delta_x.RemovePoint(point_x); - - double attr_y = this->delta_y.GetValue(time); - Point point_y = this->delta_y.GetClosestPoint(Point((double) time, attr_y)); - if (point_y.co.X == (double) time) - this->delta_y.RemovePoint(point_y); - - - return; -} - -void KeyFrameBBox::RemoveRotation(int64_t frame_number) { - - double time = this->FrameNToTime(frame_number, 1.0); - - double rot = this->rotation.GetValue(time); - Point point_rot = this->rotation.GetClosestPoint(Point((double) time, rot)); - if (point_rot.co.X == (double) time) - this->rotation.RemovePoint(point_rot); - - return; -} - - - -void KeyFrameBBox::PrintParams() { - std::cout << "delta_x "; - this->delta_x.PrintPoints(); - - std::cout << "delta_y "; - this->delta_y.PrintPoints(); - - std::cout << "scale_x "; - this->scale_x.PrintPoints(); - - std::cout << "scale_y "; - this->scale_y.PrintPoints(); - - std::cout << "rotation "; - this->rotation.PrintPoints(); - -} +// Return a bounding-box from BoxVec with it's properties adjusted by the Keyframes +BBox KeyFrameBBox::GetValue(int64_t frame_number) +{ + // Get the time position of the given frame. + double time = this->FrameNToTime(frame_number, this->TimeScale); -void KeyFrameBBox::RemoveScale(int64_t frame_number) { - - double time = this->FrameNToTime(frame_number, 1.0); - - double attr_x = this->scale_x.GetValue(time); - Point point_x = this->scale_x.GetClosestPoint(Point((double) time, attr_x)); - if (point_x.co.X == (double) time) - this->scale_x.RemovePoint(point_x); - - double attr_y = this->scale_y.GetValue(time); - Point point_y = this->scale_y.GetClosestPoint(Point((double) time, attr_y)); - if (point_y.co.X == (double) time) - this->scale_y.RemovePoint(point_y); - - - return; -} -*/ + // Return a iterator pointing to the BoxVec pair indexed by time or to the pair indexed + // by the closest upper time value. + auto currentBBoxIterator = BoxVec.lower_bound(time); -BBox KeyFrameBBox::GetValue(int64_t frame_number){ - double time = this->FrameNToTime(frame_number, this->TimeScale); - auto it = BoxVec.lower_bound(time); - - if (it == BoxVec.end()){ - BBox resp; - return resp; + // Check if there is a pair indexed by time, returns an empty bbox if there isn't. + if (currentBBoxIterator == BoxVec.end()) + { + // Create and return an empty bounding-box object + BBox emptyBBox; + return emptyBBox; } - - if ((it->first == time) || (it == BoxVec.begin())){ - BBox res = it->second; - /*res.x1 += this->delta_x.GetValue(it->first); - res.y1 += this->delta_y.GetValue(it->first); - res.height += this->scale_y.GetValue(it->first); - res.width += this->scale_x.GetValue(it->first); + + // Check if the iterator matches a BBox indexed by time or points to the first element of BoxVec + if ((currentBBoxIterator->first == time) || (currentBBoxIterator == BoxVec.begin())) + { + // Get the BBox indexed by time + BBox currentBBox = currentBBoxIterator->second; + + // Adjust the BBox properties by the Keyframes values + currentBBox.x1 += this->delta_x.GetValue(frame_number); + currentBBox.y1 += this->delta_y.GetValue(frame_number); + currentBBox.width *= this->scale_x.GetValue(frame_number); + currentBBox.height *= this->scale_y.GetValue(frame_number); + + /* TODO - Add rotation + (x1,y1) -> current point + (x1',y1') -> transformed point + (xc, yc) -> center of the BBox + (xc, yc) = (x1 + w/2, y1 + h/2) + rot -> rotation angle [radians] + x1' = xc + (x1 - xc)*cos(rot) - (y1-yc)*sin(rot) + y1' = yc + (x1 - xc)*sin(rot) + (y1-yc)*cos(rot) + *** + x1' = (x1 + w/2) + (-w/2)*cos(rot) - (-h/2)*sin(rot) + y1' = (y1 + h/2) + (-w/2)*sin(rot) + (-h/2)*cos(rot) + currentBBox.x1 += currentBBox.width/2 - (currentBBox.width/2)*cos(rot*PI/180) + (currentBBox.height)*sin(rot*PI/180); + currentBBox.y1 += currentBBox.height/2 - (currentBBox.width/2)*sin(rot*PI/180) - (currentBBox.height)*cos(rot*PI/180); */ - return res; + return currentBBox; } - - BBox second_ref = it->second; - BBox first_ref = prev(it, 1)->second; - BBox res = InterpolateBoxes(prev(it, 1)->first, it->first, first_ref, second_ref, time); - - /*later add rotation transform to these points*/ - /* - res.x1 += this->delta_x.GetValue(time); - res.y1 += this->delta_y.GetValue(time); - res.height += this->scale_y.GetValue(time); - res.width += this->scale_x.GetValue(time); - */ - return res; - + // BBox indexed by the closest upper time + BBox currentBBox = currentBBoxIterator->second; + // BBox indexed by the closet lower time + BBox previousBBox = prev(currentBBoxIterator, 1)->second; + // Interpolate a BBox in the middle of previousBBox and currentBBox + BBox interpolatedBBox = InterpolateBoxes(prev(currentBBoxIterator, 1)->first, currentBBoxIterator->first, + previousBBox, currentBBox, time); + + // Adjust the BBox properties by the Keyframes values + interpolatedBBox.x1 += this->delta_x.GetValue(frame_number); + interpolatedBBox.y1 += this->delta_y.GetValue(frame_number); + interpolatedBBox.width *= this->scale_x.GetValue(frame_number); + interpolatedBBox.height *= this->scale_y.GetValue(frame_number); + + return interpolatedBBox; } -BBox KeyFrameBBox::InterpolateBoxes(double t1, double t2, BBox left, BBox right, double target){ +// Interpolate the bouding-boxes properties +BBox KeyFrameBBox::InterpolateBoxes(double t1, double t2, BBox left, BBox right, double target) +{ Point p1_left(t1, left.x1, openshot::InterpolationType::LINEAR); Point p1_right(t2, right.x1, openshot::InterpolationType::LINEAR); - Point p1 = InterpolateBetween(p1_left, p1_right, target, 0.01); - + Point p2_left(t1, left.y1, openshot::InterpolationType::LINEAR); Point p2_right(t2, right.y1, openshot::InterpolationType::LINEAR); - Point p2 = InterpolateBetween(p2_left, p2_right, target, 0.01); - + Point p3_left(t1, left.height, openshot::InterpolationType::LINEAR); Point p3_right(t2, right.height, openshot::InterpolationType::LINEAR); - Point p3 = InterpolateBetween(p3_left, p3_right, target, 0.01); Point p4_left(t1, left.width, openshot::InterpolationType::LINEAR); Point p4_right(t2, right.width, openshot::InterpolationType::LINEAR); - Point p4 = InterpolateBetween(p4_left, p4_right, target, 0.01); - + BBox ans(p1.co.Y, p2.co.Y, p4.co.Y, p3.co.Y); return ans; } - +// Update object's BaseFps void KeyFrameBBox::SetBaseFPS(Fraction fps){ this->BaseFps = fps; return; } +// Return the object's BaseFps Fraction KeyFrameBBox::GetBaseFPS(){ return BaseFps; } +// Get the time of the given frame double KeyFrameBBox::FrameNToTime(int64_t frame_number, double time_scale){ - double time = ((double) frame_number) * this->BaseFps.Reciprocal().ToDouble() * (1.0 / time_scale); + double time = ((double)frame_number) * this->BaseFps.Reciprocal().ToDouble() * (1.0 / time_scale); return time; } +// Update the TimeScale member variable void KeyFrameBBox::ScalePoints(double time_scale){ this->TimeScale = time_scale; } +// Load the bounding-boxes information from the protobuf file +bool KeyFrameBBox::LoadBoxData(std::string inputFilePath) +{ + // Variable to hold the loaded data + libopenshottracker::Tracker bboxMessage; -// Generate JSON string of this object -std::string KeyFrameBBox::Json() { + // Read the existing tracker message. + fstream input(inputFilePath, ios::in | ios::binary); + + //Check if it was able to read the protobuf data + if (!bboxMessage.ParseFromIstream(&input)) + { + cerr << "Failed to parse protobuf message." << endl; + return false; + } + + this->clear(); + + // Iterate over all frames of the saved message + for (size_t i = 0; i < bboxMessage.frame_size(); i++) + { + // Get data of the i-th frame + const libopenshottracker::Frame &pbFrameData = bboxMessage.frame(i); - // Return formatted string - return JsonValue().toStyledString(); + // Get frame number + size_t frame_number = pbFrameData.id(); + + // Get bounding box data from current frame + const libopenshottracker::Frame::Box &box = pbFrameData.bounding_box(); + + float x1 = box.x1(); + float y1 = box.y1(); + float x2 = box.x2(); + float y2 = box.y2(); + + if ( (x1 >= 0.0) && (y1 >= 0.0) && (x2 >= 0.0) && (y2 >= 0.0) ) + { + // The bounding-box properties are valid, so add it to the BoxVec map + this->AddBox(frame_number, x1, y1, (x2 - x1), (y2 - y1)); + } + } + + // Show the time stamp from the last update in tracker data file + if (bboxMessage.has_last_updated()) + { + cout << " Loaded Data. Saved Time Stamp: " << TimeUtil::ToString(bboxMessage.last_updated()) << endl; + } + + // Delete all global objects allocated by libprotobuf. + google::protobuf::ShutdownProtobufLibrary(); + + return true; } -// Generate Json::Value for this object -Json::Value KeyFrameBBox::JsonValue() { +// Generate JSON string of this object +std::string KeyFrameBBox::Json() +{ + // Return formatted string + return JsonValue().toStyledString(); +} - // Create root json object - Json::Value root; - //root["Points"] = Json::Value(Json::arrayValue); +// Generate Json::Value for this object +Json::Value KeyFrameBBox::JsonValue() +{ + // Create root json object + Json::Value root; root["BaseFPS"]["num"] = BaseFps.num; - root["BaseFPS"]["den"] = BaseFps.den; + root["BaseFPS"]["den"] = BaseFps.den; root["TimeScale"] = this->TimeScale; - root["boxes"] = Json::Value(Json::arrayValue); - - // loop through points - for (auto const& x : BoxVec){ - Json::Value elem; - elem["key"] = x.first; - elem["val"] = x.second.JsonValue(); - root["boxes"].append(elem); + root["Boxes"] = Json::Value(Json::arrayValue); + + // Loop through the BoxVec map and save the BBox data + for (auto const &x : BoxVec) + { + Json::Value box; + box["time"] = x.first; + box["data"] = x.second.JsonValue(); + root["Boxes"].append(box); } - -/* + // Get the Keyframe's Json strings root["delta_x"] = delta_x.JsonValue(); root["delta_y"] = delta_y.JsonValue(); root["scale_x"] = scale_x.JsonValue(); root["scale_y"] = scale_y.JsonValue(); root["rotation"] = rotation.JsonValue(); -*/ - // return JsonValue - return root; + + // return JsonValue + return root; } // Load JSON string into this object -void KeyFrameBBox::SetJson(const std::string value) { - - // Parse JSON string into JSON objects - try - { - const Json::Value root = openshot::stringToJson(value); - // Set all values that match - SetJsonValue(root); - } - catch (const std::exception& e) - { - // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); - } - - return; +void KeyFrameBBox::SetJson(const std::string value) +{ + // Parse JSON string into JSON objects + try + { + const Json::Value root = openshot::stringToJson(value); + // Set all values that match + SetJsonValue(root); + } + catch (const std::exception &e) + { + // Error parsing JSON (or missing keys) + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); + } + return; } -void KeyFrameBBox::clear(){ - BoxVec.clear(); +// Clear the BoxVec map +void KeyFrameBBox::clear() +{ + BoxVec.clear(); } - - // Load Json::Value into this object -void KeyFrameBBox::SetJsonValue(const Json::Value root) { - // Clear existing points - BoxVec.clear(); -/* - delta_x.SetJsonValue(root["delta_x"]); - delta_y.SetJsonValue(root["delta_y"]); - scale_x.SetJsonValue(root["scale_x"]); - scale_y.SetJsonValue(root["scale_y"]); - rotation.SetJsonValue(root["rotation"]); -*/ - - if (!root["BaseFPS"].isNull() && root["BaseFPS"].isObject()) { +void KeyFrameBBox::SetJsonValue(const Json::Value root) +{ + // Clear BoxVec + this->clear(); + + if (!root["BaseFPS"].isNull() && root["BaseFPS"].isObject()) + { + // Set the BaseFps by the given JSON object if (!root["BaseFPS"]["num"].isNull()) - BaseFps.num = (int) root["BaseFPS"]["num"].asInt(); + BaseFps.num = (int)root["BaseFPS"]["num"].asInt(); if (!root["BaseFPS"]["den"].isNull()) - BaseFps.den = (int) root["BaseFPS"]["den"].asInt(); - } - if (!root["TimeScale"].isNull()) { - double scale = (double) root["TimeScale"].asDouble(); + BaseFps.den = (int)root["BaseFPS"]["den"].asInt(); + } + + if (!root["TimeScale"].isNull()) + { + // Set the TimeScale by the given JSON object + double scale = (double)root["TimeScale"].asDouble(); this->ScalePoints(scale); - } - - if (!root["boxes"].isNull()){ - // loop through points - for (const auto existing_point : root["boxes"]) { - // Create Point + } + + if (!root["Boxes"].isNull()) + { + // Loop through the BBoxes data + for (const auto existing_point : root["Boxes"]) + { + // Insert BBox into the BoxVec map BBox box; - box.SetJsonValue(existing_point["val"]); - - BoxVec.insert({existing_point["key"].asDouble(), box}); + box.SetJsonValue(existing_point["data"]); + //BoxVec.insert({existing_point["time"].asDouble(), box}); + BoxVec[existing_point["time"].asDouble()] = box; } } - + + // Set the Keyframes by the given JSON object + if (!root["delta_x"].isNull()) + delta_x.SetJsonValue(root["delta_x"]); + if (!root["delta_y"].isNull()) + delta_y.SetJsonValue(root["delta_y"]); + if (!root["scale_x"].isNull()) + scale_x.SetJsonValue(root["scale_x"]); + if (!root["scale_y"].isNull()) + scale_y.SetJsonValue(root["scale_y"]); + if (!root["rotation"].isNull()) + rotation.SetJsonValue(root["rotation"]); + return; } \ No newline at end of file diff --git a/src/KeyFrameBBox.h b/src/KeyFrameBBox.h index 9828812fd..fb7fc16a4 100644 --- a/src/KeyFrameBBox.h +++ b/src/KeyFrameBBox.h @@ -6,7 +6,6 @@ * @ref License */ - /* LICENSE * * Copyright (c) 2008-2019 OpenShot Studios, LLC @@ -44,53 +43,56 @@ #include "Json.h" #include "IKeyFrame.h" #include "KeyFrame.h" +#include "trackerdata.pb.h" +#include +using google::protobuf::util::TimeUtil; - -namespace openshot { - /** - * @brief A Keyframe is a collection of Point instances, which is used to vary a number or property over time. +namespace openshot +{ + /** + * @brief This struct holds the information of a bounding-box: a rectangular shape that enclosures an object or a + * desired set of pixels in a digital image. * - * Keyframes are used to animate and interpolate values of properties over time. For example, a single property - * can use a Keyframe instead of a constant value. Assume you want to slide an image (from left to right) over - * a video. You can create a Keyframe which will adjust the X value of the image over 100 frames (or however many - * frames the animation needs to last) from the value of 0 to 640. - * - * \endcode + * The bounding-box structure holds four floating-point properties: the x and y coordinates of the rectangle's + * top left corner (x1, y1), the rectangle's width and the rectangle's height. */ + struct BBox + { + float x1 = -1; ///< x-coordinate of the top left corner + float y1 = -1; ///< y-coordinate of the top left corner + float width = -1; ///< bounding box width + float height = -1; ///< bounding box height - - struct BBox{ - float x1 = -1; - float y1 = -1; - float width = -1; - float height = -1; - - // Constructors - BBox(){ + /// Blank constructor + BBox() + { return; } - BBox(float _x1, float _y1, float _width, float _height){ - //frame_num = _frame_num; + /// Default constructor, which takes the bounding box top-left corner coordinates, width and height. + /// @param _x1 X-coordinate of the top left corner + /// @param _y1 Y-coordinate of the top left corner + /// @param _width Bounding box width + /// @param _height Bouding box height + BBox(float _x1, float _y1, float _width, float _height) + { x1 = _x1; y1 = _y1; width = _width; height = _height; } - - - std::string Json() const { - // Return formatted string + /// Generate JSON string of this object + std::string Json() const + { return JsonValue().toStyledString(); } - // Generate Json::Value for this object - Json::Value JsonValue() const { - - // Create root json object + /// Generate Json::Value for this object + Json::Value JsonValue() const + { Json::Value root; root["x1"] = x1; root["y1"] = y1; @@ -100,9 +102,9 @@ namespace openshot { return root; } - // Load JSON string into this object - void SetJson(const std::string value) { - + /// Load JSON string into this object + void SetJson(const std::string value) + { // Parse JSON string into JSON objects try { @@ -110,15 +112,16 @@ namespace openshot { // Set all values that match SetJsonValue(root); } - catch (const std::exception& e) + catch (const std::exception &e) { // Error parsing JSON (or missing keys) throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } } - // Load Json::Value into this object - void SetJsonValue(const Json::Value root) { + /// Load Json::Value into this object + void SetJsonValue(const Json::Value root) + { // Set data from Json (if key is found) if (!root["x1"].isNull()) @@ -132,69 +135,83 @@ namespace openshot { } }; + /** + * @brief This class holds the information of a bounding-box (mapped by time) over the frames that contain + * the object enclosured by it. + * + * The bounding-box displacement in X and Y directions and it's width and height variation over the frames + * are set as openshot::Keyframe objects + * + * The bounding-box information over the clip's frames are saved into a protobuf file and loaded into an + * object of this class. + */ + + class KeyFrameBBox + { + private: + bool visible; + Fraction BaseFps; + double TimeScale; + + public: + std::map BoxVec; ///< Index the bounding-box by time of each frame + Keyframe delta_x; ///< X-direction displacement Keyframe + Keyframe delta_y; ///< Y-direction displacement Keyframe + Keyframe scale_x; ///< X-direction scale Keyframe + Keyframe scale_y; ///< Y-direction scale Keyframe + Keyframe rotation; ///< Rotation Keyframe + std::string protobufDataPath; ///< Path to the protobuf file that holds the bbox points across the frames + + /// Default Constructor + KeyFrameBBox(); + + /// Add a BBox to the BoxVec map + void AddBox(int64_t _frame_num, float _x1, float _y1, float _width, float _height); + + /// Update object's BaseFps + void SetBaseFPS(Fraction fps); + + /// Return the object's BaseFps + Fraction GetBaseFPS(); + + /// Update the TimeScale member variable + void ScalePoints(double scale); + + /// Check if there is a bounding-box in the given frame + bool Contains(int64_t frame_number); + + /// Get the size of BoxVec map + int64_t GetLength() const; + + /// Remove a bounding-box from the BoxVec map + void RemoveBox(int64_t frame_number); + + /// Return a bounding-box from BoxVec with it's properties adjusted by the Keyframes + BBox GetValue(int64_t frame_number) const + { + return const_cast(this)->GetValue(frame_number); + } + BBox GetValue(int64_t frame_number); - class KeyFrameBBox { - private: - bool visible; - Fraction BaseFps; - double TimeScale; - std::map BoxVec; - public: - //Keyframe delta_x; - //Keyframe delta_y; - //Keyframe scale_x; - //Keyframe scale_y; - //Keyframe rotation; - - - - KeyFrameBBox(); - - //void AddDisplacement(int64_t _frame_num, double _delta_x, double _delta_y); - //void AddScale(int64_t _frame_num, double _delta_x, double _delta_y); - void AddBox(int64_t _frame_num, float _x1, float _y1, float _width, float _height); - //void AddRotation(int64_t _frame_num, double rot); - - void SetBaseFPS(Fraction fps); - Fraction GetBaseFPS(); - - void ScalePoints(double scale); - - bool Contains(int64_t frame_number); - //double GetDelta(int64_t index) const ; - int64_t GetLength() const; - - /// Remove a points by frame_number - void RemovePoint(int64_t frame_number); - //void RemoveDelta(int64_t frame_number); - //void RemoveScale(int64_t frame_number); - //void RemoveRotation(int64_t frame_number); - - BBox GetValue(int64_t frame_number) const - { - return const_cast(this)->GetValue(frame_number); - } - - BBox GetValue(int64_t frame_number); - - - /// Print collection of points - //void PrintParams(); - - double FrameNToTime(int64_t frame_number, double time_scale); - BBox InterpolateBoxes(double t1, double t2, BBox left, BBox right, double target); + /// Load the bounding-boxes information from the protobuf file + bool LoadBoxData(std::string inputFilePath); - /// Get and Set JSON methods - std::string Json(); ///< Generate JSON string of this object - Json::Value JsonValue(); ///< Generate Json::Value for this object - void SetJson(const std::string value); ///< Load JSON string into this object - void SetJsonValue(const Json::Value root); ///< Load Json::Value into this object + /// Get the time of the given frame + double FrameNToTime(int64_t frame_number, double time_scale); - void clear(); //clear all fields + /// Interpolate the bouding-boxes properties + BBox InterpolateBoxes(double t1, double t2, BBox left, BBox right, double target); + /// Get and Set JSON methods + std::string Json(); ///< Generate JSON string of this object + Json::Value JsonValue(); ///< Generate Json::Value for this object + void SetJson(const std::string value); ///< Load JSON string into this object + void SetJsonValue(const Json::Value root); ///< Load Json::Value into this object + /// Clear the BoxVec map + void clear(); }; -} +} // namespace openshot #endif \ No newline at end of file diff --git a/src/effects/Tracker.cpp b/src/effects/Tracker.cpp index 17e234615..d3965ed6f 100644 --- a/src/effects/Tracker.cpp +++ b/src/effects/Tracker.cpp @@ -33,20 +33,19 @@ using namespace openshot; /// Blank constructor, useful when using Json to load the effect properties -Tracker::Tracker(std::string clipTrackerDataPath): delta_x(0.0), delta_y(0.0), scale_x(1.0), scale_y(1.0), rotation(0.0) +Tracker::Tracker(std::string clipTrackerDataPath) { // Init effect properties init_effect_details(); - // Tries to load the tracker data from protobuf - LoadTrackedData(clipTrackerDataPath); + // Tries to load the tracked object's data from protobuf file + trackedData.LoadBoxData(clipTrackerDataPath); } // Default constructor -Tracker::Tracker(): delta_x(0.0), delta_y(0.0), scale_x(1.0), scale_y(1.0), rotation(0.0) +Tracker::Tracker() { // Init effect properties init_effect_details(); - } @@ -70,7 +69,6 @@ void Tracker::init_effect_details() // modified openshot::Frame object std::shared_ptr Tracker::GetFrame(std::shared_ptr frame, int64_t frame_number) { - // Get the frame's image cv::Mat frame_image = frame->GetImageCV(); @@ -80,27 +78,18 @@ std::shared_ptr Tracker::GetFrame(std::shared_ptr frame, int64_t f // Check if track data exists for the requested frame if (trackedData.Contains(frame_number)) { + // Get the width and height of the image float fw = frame_image.size().width; float fh = frame_image.size().height; - double scale_x = this->scale_x.GetValue(frame_number); - double scale_y = this->scale_y.GetValue(frame_number); - double delta_x = this->delta_x.GetValue(frame_number); - double delta_y = this->delta_y.GetValue(frame_number); - - // convert to [cx, cy, width, height]. Apply scale and translation + // Get the bounding-box of given frame BBox fd = this->trackedData.GetValue(frame_number); - float cx = fd.x1 + (fd.width/2) + delta_x; - float cy = fd.y1 + (fd.height/2) + delta_y; - float width = fd.width * scale_x; - float height = fd.height * scale_y; - - // Draw box on image - cv::Rect2d box((int)( (cx - (width/2) ) * fw ), - (int)( (cy - (height/2) ) * fh ), - (int)( (width) * fw), - (int)( (height) * fh) ); + // Draw the bounding-box on the image + cv::Rect2d box((int)( (fd.x1 ) * fw ), + (int)( (fd.y1 ) * fh ), + (int)( (fd.width) * fw), + (int)( (fd.height) * fh) ); cv::rectangle(frame_image, box, cv::Scalar( 255, 0, 0 ), 2, 1 ); } } @@ -112,64 +101,6 @@ std::shared_ptr Tracker::GetFrame(std::shared_ptr frame, int64_t f return frame; } -// Load protobuf data file -bool Tracker::LoadTrackedData(std::string inputFilePath){ - // Create tracker message - libopenshottracker::Tracker trackerMessage; - - { - // Read the existing tracker message. - fstream input(inputFilePath, ios::in | ios::binary); - if (!trackerMessage.ParseFromIstream(&input)) { - cerr << "Failed to parse protobuf message." << endl; - return false; - } - } - - // Make sure the trackedData is empty - //trackedDataById.clear(); - trackedData.clear(); - - - // Iterate over all frames of the saved message - for (size_t i = 0; i < trackerMessage.frame_size(); i++) { - const libopenshottracker::Frame& pbFrameData = trackerMessage.frame(i); - - // Load frame and rotation data - size_t id = pbFrameData.id(); - float rotation = pbFrameData.rotation(); - - // Load bounding box data - const libopenshottracker::Frame::Box& box = pbFrameData.bounding_box(); - float x1 = box.x1(); - float y1 = box.y1(); - float x2 = box.x2(); - float y2 = box.y2(); - - // Assign data to tracker map - //trackedDataById[id] = EffectFrameData(id, rotation, x1, y1, x2, y2); - if ((x1 >= 0.0) && (y1 >= 0.0) && (x2 >= 0.0) && (y2 >= 0.0)){ - trackedData.AddBox(id, x1, y1, (x2-x1), (y2-y1)); - //trackedData.AddRotation(id, rotation); - } - } - - // Show the time stamp from the last update in tracker data file - if (trackerMessage.has_last_updated()) { - cout << " Loaded Data. Saved Time Stamp: " << TimeUtil::ToString(trackerMessage.last_updated()) << endl; - } - - // Delete all global objects allocated by libprotobuf. - google::protobuf::ShutdownProtobufLibrary(); - - return true; -} - -// Get tracker info for the desired frame -BBox Tracker::GetTrackedData(size_t frameId){ - return this->trackedData.GetValue(frameId); -} - // Generate JSON string of this object std::string Tracker::Json() const { @@ -187,13 +118,6 @@ Json::Value Tracker::JsonValue() const { root["BaseFPS"]["num"] = BaseFPS.num; root["BaseFPS"]["den"] = BaseFPS.den; root["TimeScale"] = this->TimeScale; - - root["delta_x"] = delta_x.JsonValue(); - root["delta_y"] = delta_y.JsonValue(); - root["scale_x"] = scale_x.JsonValue(); - root["scale_y"] = scale_y.JsonValue(); - root["rotation"] = rotation.JsonValue(); - // return JsonValue return root; } @@ -221,50 +145,45 @@ void Tracker::SetJsonValue(const Json::Value root) { // Set parent data EffectBase::SetJsonValue(root); - if (!root["BaseFPS"].isNull() && root["BaseFPS"].isObject()) { + if (!root["BaseFPS"].isNull() && root["BaseFPS"].isObject()) + { if (!root["BaseFPS"]["num"].isNull()) + { BaseFPS.num = (int) root["BaseFPS"]["num"].asInt(); + } if (!root["BaseFPS"]["den"].isNull()) - BaseFPS.den = (int) root["BaseFPS"]["den"].asInt(); + { + BaseFPS.den = (int) root["BaseFPS"]["den"].asInt(); + } } - if (!root["TimeScale"].isNull()){ + if (!root["TimeScale"].isNull()) TimeScale = (double) root["TimeScale"].asDouble(); - } trackedData.SetBaseFPS(this->BaseFPS); trackedData.ScalePoints(TimeScale); // Set data from Json (if key is found) - if (!root["protobuf_data_path"].isNull()){ + if (!root["protobuf_data_path"].isNull()) + { protobuf_data_path = (root["protobuf_data_path"].asString()); - - if(!LoadTrackedData(protobuf_data_path)){ + if(!trackedData.LoadBoxData(protobuf_data_path)) + { std::cout<<"Invalid protobuf data path"; protobuf_data_path = ""; } } - - if (!root["delta_x"].isNull()) - delta_x.SetJsonValue(root["delta_x"]); - if (!root["delta_y"].isNull()) - delta_y.SetJsonValue(root["delta_y"]); - if (!root["scale_x"].isNull()) - scale_x.SetJsonValue(root["scale_x"]); - if (!root["scale_y"].isNull()) - scale_y.SetJsonValue(root["scale_y"]); - if (!root["rotation"].isNull()) - rotation.SetJsonValue(root["rotation"]); - - } // Get all properties for a specific frame std::string Tracker::PropertiesJSON(int64_t requested_frame) const { - + // Generate JSON properties list Json::Value root; + + // Effect's properties + root["name"] = add_property_json("Tracker", 0.0, "string", "", NULL, -1, -1, true, requested_frame); root["id"] = add_property_json("ID", 0.0, "string", Id(), NULL, -1, -1, true, requested_frame); root["position"] = add_property_json("Position", Position(), "float", "", NULL, 0, 1000 * 60 * 30, false, requested_frame); root["layer"] = add_property_json("Track", Layer(), "int", "", NULL, 0, 20, false, requested_frame); @@ -272,29 +191,73 @@ std::string Tracker::PropertiesJSON(int64_t requested_frame) const { root["end"] = add_property_json("End", End(), "float", "", NULL, 0, 1000 * 60 * 30, false, requested_frame); root["duration"] = add_property_json("Duration", Duration(), "float", "", NULL, 0, 1000 * 60 * 30, true, requested_frame); - // Keyframes - float scale_x_value = this->scale_x.GetValue(requested_frame); - float scale_y_value = this->scale_y.GetValue(requested_frame); - float delta_x_value = this->delta_x.GetValue(requested_frame); - float delta_y_value = this->delta_y.GetValue(requested_frame); - root["delta_x"] = add_property_json("Displacement X-axis", this->delta_x.GetValue(requested_frame), "float", "", &delta_x, -1.0, 1.0, false, requested_frame); - root["delta_y"] = add_property_json("Displacement Y-axis", this->delta_y.GetValue(requested_frame), "float", "", &delta_y, -1.0, 1.0, false, requested_frame); - root["scale_x"] = add_property_json("Scale (Width)", this->scale_x.GetValue(requested_frame), "float", "", &scale_x, 0.0, 1.0, false, requested_frame); - root["scale_y"] = add_property_json("Scale (Height)", this->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); - - // TODO: use p1, p2 convention instead of [x1, y1, width, height] - BBox fd = this->trackedData.GetValue(requested_frame); - float cx = fd.x1 + (fd.width/2) + delta_x_value; - float cy = fd.y1 + (fd.height/2) + delta_y_value; - float width = fd.width * scale_x_value; - float height = fd.height * scale_y_value; - - root["x1"] = add_property_json("X1", cx-(width/2), "float", "", NULL, 0.0, 1.0, false, requested_frame); - root["y1"] = add_property_json("Y1", cy-(height/2), "float", "", NULL, 0.0, 1.0, false, requested_frame); - root["x2"] = add_property_json("X2", cx+(width/2), "float", "", NULL, 0.0, 1.0, false, requested_frame); - root["y2"] = add_property_json("Y2", cy+(height/2), "float", "", NULL, 0.0, 1.0, false, requested_frame); + // Get the bounding-box for the given-frame + BBox fd = trackedData.GetValue(requested_frame); + // Add the data of given frame bounding-box to the JSON object + root["x1"] = add_property_json("X1", fd.x1, "float", "", NULL, 0.0, 1.0, false, requested_frame); + root["y1"] = add_property_json("Y1", fd.y1, "float", "", NULL, 0.0, 1.0, false, requested_frame); + root["x2"] = add_property_json("X2", fd.x1+fd.width, "float", "", NULL, 0.0, 1.0, false, requested_frame); + root["y2"] = add_property_json("Y2", fd.y1+fd.height, "float", "", NULL, 0.0, 1.0, false, requested_frame); + + // Add the bounding-box Keyframes to the JSON object + root["delta_x"] = add_property_json("Displacement X-axis", trackedData.delta_x.GetValue(requested_frame), "float", "", &trackedData.delta_x, -1.0, 1.0, false, requested_frame); + root["delta_y"] = add_property_json("Displacement Y-axis", trackedData.delta_y.GetValue(requested_frame), "float", "", &trackedData.delta_y, -1.0, 1.0, false, requested_frame); + root["scale_x"] = add_property_json("Scale (Width)", trackedData.scale_x.GetValue(requested_frame), "float", "", &trackedData.scale_x, -1.0, 1.0, false, requested_frame); + root["scale_y"] = add_property_json("Scale (Height)", trackedData.scale_y.GetValue(requested_frame), "float", "", &trackedData.scale_y, -1.0, 1.0, false, requested_frame); + root["rotation"] = add_property_json("Rotation", trackedData.rotation.GetValue(requested_frame), "float", "", &trackedData.rotation, 0, 360, false, requested_frame); // Return formatted string return root.toStyledString(); } + +// Generate JSON string of the trackedData object passing the frame number +std::string Tracker::Json(int64_t requested_frame) const { + + // Generate JSON properties list + Json::Value root; + + // Add the KeyframeBBox class properties to the JSON object + root["type"] = info.class_name; + root["protobuf_data_path"] = protobuf_data_path; + root["BaseFPS"]["num"] = BaseFPS.num; + root["BaseFPS"]["den"] = BaseFPS.den; + root["TimeScale"] = this->TimeScale; + + // Add the bounding-box Keyframes to the JSON object + root["delta_x"] = trackedData.delta_x.JsonValue(); + root["delta_y"] = trackedData.delta_y.JsonValue(); + root["scale_x"] = trackedData.scale_x.JsonValue(); + root["scale_y"] = trackedData.scale_y.JsonValue(); + root["rotation"] = trackedData.rotation.JsonValue(); + + return root.toStyledString(); +} + +// Set the tracketData object properties by a JSON string +void Tracker::SetJson(int64_t requested_frame, const std::string value) +{ + // Parse JSON string into JSON objects + try + { + const Json::Value root = openshot::stringToJson(value); + + // Set all values that match + if (!root["delta_x"].isNull()) + trackedData.delta_x.SetJsonValue(root["delta_x"]); + if (!root["delta_y"].isNull()) + trackedData.delta_y.SetJsonValue(root["delta_y"]); + if (!root["scale_x"].isNull()) + trackedData.scale_x.SetJsonValue(root["scale_x"]); + if (!root["scale_y"].isNull()) + trackedData.scale_y.SetJsonValue(root["scale_y"]); + if (!root["rotation"].isNull()) + trackedData.rotation.SetJsonValue(root["rotation"]); + } + + catch (const std::exception& e) + { + // Error parsing JSON (or missing keys) + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); + } + return; +} \ No newline at end of file diff --git a/src/effects/Tracker.h b/src/effects/Tracker.h index 34408a7ae..57a8b8b10 100644 --- a/src/effects/Tracker.h +++ b/src/effects/Tracker.h @@ -49,35 +49,6 @@ using namespace std; using google::protobuf::util::TimeUtil; - -// Tracking info struct -struct EffectFrameData{ - size_t frame_id = -1; - float rotation = 0; - float x1 = -1; - float y1 = -1; - float x2 = -1; - float y2 = -1; - - // Constructors - EffectFrameData() - {} - - EffectFrameData( int _frame_id) - {frame_id = _frame_id;} - - EffectFrameData( int _frame_id , float _rotation, float _x1, float _y1, float _x2, float _y2) - { - frame_id = _frame_id; - rotation = _rotation; - x1 = _x1; - y1 = _y1; - x2 = _x2; - y2 = _y2; - } -}; - - namespace openshot { /** @@ -90,20 +61,13 @@ namespace openshot private: /// Init effect settings void init_effect_details(); - std::string protobuf_data_path; + Fraction BaseFPS; double TimeScale; public: - Keyframe delta_x; - Keyframe delta_y; - Keyframe scale_x; - Keyframe scale_y; - Keyframe rotation; - - std::map trackedDataById; // Save object tracking box data - - KeyFrameBBox trackedData; + std::string protobuf_data_path; ///< Path to the protobuf file that holds the bounding-box data + KeyFrameBBox trackedData; ///< Object that holds the bounding-box data and it's Keyframes /// Blank constructor, useful when using Json to load the effect properties Tracker(std::string clipTrackerDataPath); @@ -122,12 +86,6 @@ namespace openshot /// @param frame_number The frame number (starting at 1) of the effect on the timeline. std::shared_ptr GetFrame(std::shared_ptr frame, int64_t frame_number) override; std::shared_ptr GetFrame(int64_t frame_number) override { return GetFrame(std::shared_ptr (new Frame()), frame_number); } - - // Load protobuf data file - bool LoadTrackedData(std::string inputFilePath); - - // Get tracker info for the desired frame - BBox GetTrackedData(size_t frameId); /// Get and Set JSON methods std::string Json() const override; ///< Generate JSON string of this object @@ -138,8 +96,10 @@ namespace openshot /// Get all properties for a specific frame (perfect for a UI to display the current state /// of all properties at any time) std::string PropertiesJSON(int64_t requested_frame) const override; - }; + std::string Json(int64_t requested_frame) const override; ///< Generate JSON string of the trackedData object passing the frame number + void SetJson(int64_t requested_frame, const std::string value) override; ///< Set the tracketData object properties by a JSON string + }; } #endif diff --git a/tests/KeyFrame_Tests.cpp b/tests/KeyFrame_Tests.cpp index c5d5b6da7..50ce041b3 100644 --- a/tests/KeyFrame_Tests.cpp +++ b/tests/KeyFrame_Tests.cpp @@ -510,9 +510,7 @@ TEST(KeyFrameBBox_addBox_test) { CHECK_EQUAL(true, kfb.Contains(1)); CHECK_EQUAL(1, kfb.GetLength()); - //kfb.PrintParams(); - - kfb.RemovePoint(1); + kfb.RemoveBox(1); CHECK_EQUAL(false, kfb.Contains(1)); CHECK_EQUAL(0, kfb.GetLength()); @@ -524,15 +522,12 @@ TEST(KeyFrameBBox_GetVal_test) { kfb.AddBox(1, 10.0, 10.0, 100.0, 100.0); - //kfb.AddDisplacement(1, 20.0, 20.0); - //kfb.AddScale(1, 30, 30); - BBox val = kfb.GetValue(1); CHECK_EQUAL(10.0, val.x1); CHECK_EQUAL(10.0, val.y1); CHECK_EQUAL(100.0,val.width); - CHECK_EQUAL(100.0, val.height); + CHECK_EQUAL(100.0,val.height); } @@ -543,10 +538,6 @@ TEST(KeyFrameBBox_GetVal_Interpolation) { kfb.AddBox(11, 20.0, 20.0, 100.0, 100.0); kfb.AddBox(21, 30.0, 30.0, 100.0, 100.0); kfb.AddBox(31, 40.0, 40.0, 100.0, 100.0); - - - //kfb.AddDisplacement(1, 20.0, 20.0); - //kfb.AddScale(1, 30, 30); BBox val = kfb.GetValue(5); @@ -575,20 +566,46 @@ TEST(KeyFrameBBox_GetVal_Interpolation) { TEST(KeyFrameBBox_Json_set) { KeyFrameBBox kfb; - kfb.AddBox(0, 10.0, 10.0, 100.0, 100.0); + kfb.AddBox(1, 10.0, 10.0, 100.0, 100.0); kfb.AddBox(10, 20.0, 20.0, 100.0, 100.0); kfb.AddBox(20, 30.0, 30.0, 100.0, 100.0); kfb.AddBox(30, 40.0, 40.0, 100.0, 100.0); + kfb.scale_x.AddPoint(1, 2.0); + kfb.scale_x.AddPoint(10, 3.0); + kfb.SetBaseFPS(Fraction(24.0, 1.0)); - kfb.ScalePoints(1.2); - auto data = kfb.Json(); + + auto dataJSON = kfb.Json(); + KeyFrameBBox fromJSON_kfb; + fromJSON_kfb.SetJson(dataJSON); + + std::cout << fromJSON_kfb.Json() << std::endl; + + CHECK_EQUAL(kfb.GetBaseFPS().num, fromJSON_kfb.GetBaseFPS().num); - KeyFrameBBox from_json; - from_json.SetJson(data); + double time_kfb = kfb.FrameNToTime(1, 1.0); + double time_fromJSON_kfb = fromJSON_kfb.FrameNToTime(1, 1.0); + CHECK_EQUAL(time_kfb, time_fromJSON_kfb); - std::cout << from_json.Json() << std::endl; + BBox kfb_bbox = kfb.BoxVec[time_kfb]; + BBox fromJSON_bbox = fromJSON_kfb.BoxVec[time_fromJSON_kfb]; - CHECK_EQUAL(kfb.GetBaseFPS().num, from_json.GetBaseFPS().num); + CHECK_EQUAL(kfb_bbox.x1, fromJSON_bbox.x1); + CHECK_EQUAL(kfb_bbox.y1, fromJSON_bbox.y1); + CHECK_EQUAL(kfb_bbox.width, fromJSON_bbox.width); + CHECK_EQUAL(kfb_bbox.height, fromJSON_bbox.height); } +TEST(KeyFrameBBox_Scale_test){ + KeyFrameBBox kfb; + + kfb.AddBox(1, 10.0, 10.0, 10.0, 10.0); + kfb.scale_x.AddPoint(1.0, 2.0); + kfb.scale_y.AddPoint(1.0, 3.0); + + BBox bbox = kfb.GetValue(1); + + CHECK_EQUAL(20.0, bbox.width); + CHECK_EQUAL(30.0, bbox.height); +} \ No newline at end of file From 4fdd325ea3eb23c700c7aaa3a18f27a8f63aa949 Mon Sep 17 00:00:00 2001 From: Brenno Date: Mon, 14 Dec 2020 18:08:44 -0300 Subject: [PATCH 11/84] Added rotation transform to the tracker bounding-box. Changed the bounding-box struct point convention to (cx, cy, width, height, angle). The GetFrame member function from Tracker class now uses the cv::RotatedRect object to represent the bounding-box and draw it on screen. The JSON and Protobuf communication between the backend and frontend still uses the (x1,y1)(x2,y2) point convention, the backend performs the adequate transformations. --- src/KeyFrameBBox.cpp | 96 ++++++++++++++++++++-------------------- src/KeyFrameBBox.h | 47 +++++++++++--------- src/effects/Tracker.cpp | 36 ++++++++------- tests/KeyFrame_Tests.cpp | 46 ++++++++++--------- 4 files changed, 119 insertions(+), 106 deletions(-) diff --git a/src/KeyFrameBBox.cpp b/src/KeyFrameBBox.cpp index 2a8610145..7109101df 100644 --- a/src/KeyFrameBBox.cpp +++ b/src/KeyFrameBBox.cpp @@ -142,14 +142,14 @@ KeyFrameBBox::KeyFrameBBox() : delta_x(0.0), delta_y(0.0), scale_x(1.0), scale_y } // Add a BBox to the BoxVec map -void KeyFrameBBox::AddBox(int64_t _frame_num, float _x1, float _y1, float _width, float _height) +void KeyFrameBBox::AddBox(int64_t _frame_num, float _cx, float _cy, float _width, float _height, float _angle) { // Check if the given frame number is valid if (_frame_num < 0) return; // Instantiate a new bounding-box - BBox newBBox = BBox(_x1, _y1, _width, _height); + BBox newBBox = BBox(_cx, _cy, _width, _height, _angle); // Get the time of given frame double time = this->FrameNToTime(_frame_num, 1.0); @@ -231,25 +231,12 @@ BBox KeyFrameBBox::GetValue(int64_t frame_number) BBox currentBBox = currentBBoxIterator->second; // Adjust the BBox properties by the Keyframes values - currentBBox.x1 += this->delta_x.GetValue(frame_number); - currentBBox.y1 += this->delta_y.GetValue(frame_number); + currentBBox.cx += this->delta_x.GetValue(frame_number); + currentBBox.cy += this->delta_y.GetValue(frame_number); currentBBox.width *= this->scale_x.GetValue(frame_number); currentBBox.height *= this->scale_y.GetValue(frame_number); + currentBBox.angle += this->rotation.GetValue(frame_number); - /* TODO - Add rotation - (x1,y1) -> current point - (x1',y1') -> transformed point - (xc, yc) -> center of the BBox - (xc, yc) = (x1 + w/2, y1 + h/2) - rot -> rotation angle [radians] - x1' = xc + (x1 - xc)*cos(rot) - (y1-yc)*sin(rot) - y1' = yc + (x1 - xc)*sin(rot) + (y1-yc)*cos(rot) - *** - x1' = (x1 + w/2) + (-w/2)*cos(rot) - (-h/2)*sin(rot) - y1' = (y1 + h/2) + (-w/2)*sin(rot) + (-h/2)*cos(rot) - currentBBox.x1 += currentBBox.width/2 - (currentBBox.width/2)*cos(rot*PI/180) + (currentBBox.height)*sin(rot*PI/180); - currentBBox.y1 += currentBBox.height/2 - (currentBBox.width/2)*sin(rot*PI/180) - (currentBBox.height)*cos(rot*PI/180); - */ return currentBBox; } @@ -263,10 +250,11 @@ BBox KeyFrameBBox::GetValue(int64_t frame_number) previousBBox, currentBBox, time); // Adjust the BBox properties by the Keyframes values - interpolatedBBox.x1 += this->delta_x.GetValue(frame_number); - interpolatedBBox.y1 += this->delta_y.GetValue(frame_number); + interpolatedBBox.cx += this->delta_x.GetValue(frame_number); + interpolatedBBox.cy += this->delta_y.GetValue(frame_number); interpolatedBBox.width *= this->scale_x.GetValue(frame_number); interpolatedBBox.height *= this->scale_y.GetValue(frame_number); + interpolatedBBox.angle += this->rotation.GetValue(frame_number); return interpolatedBBox; } @@ -274,26 +262,35 @@ BBox KeyFrameBBox::GetValue(int64_t frame_number) // Interpolate the bouding-boxes properties BBox KeyFrameBBox::InterpolateBoxes(double t1, double t2, BBox left, BBox right, double target) { - - Point p1_left(t1, left.x1, openshot::InterpolationType::LINEAR); - Point p1_right(t2, right.x1, openshot::InterpolationType::LINEAR); - Point p1 = InterpolateBetween(p1_left, p1_right, target, 0.01); - - Point p2_left(t1, left.y1, openshot::InterpolationType::LINEAR); - Point p2_right(t2, right.y1, openshot::InterpolationType::LINEAR); - Point p2 = InterpolateBetween(p2_left, p2_right, target, 0.01); - - Point p3_left(t1, left.height, openshot::InterpolationType::LINEAR); - Point p3_right(t2, right.height, openshot::InterpolationType::LINEAR); - Point p3 = InterpolateBetween(p3_left, p3_right, target, 0.01); - - Point p4_left(t1, left.width, openshot::InterpolationType::LINEAR); - Point p4_right(t2, right.width, openshot::InterpolationType::LINEAR); - Point p4 = InterpolateBetween(p4_left, p4_right, target, 0.01); - - BBox ans(p1.co.Y, p2.co.Y, p4.co.Y, p3.co.Y); - - return ans; + // Interpolate the x-coordinate of the center point + Point cx_left(t1, left.cx, openshot::InterpolationType::LINEAR); + Point cx_right(t2, right.cx, openshot::InterpolationType::LINEAR); + Point cx = InterpolateBetween(cx_left, cx_right, target, 0.01); + + // Interpolate de y-coordinate of the center point + Point cy_left(t1, left.cy, openshot::InterpolationType::LINEAR); + Point cy_right(t2, right.cy, openshot::InterpolationType::LINEAR); + Point cy = InterpolateBetween(cy_left, cy_right, target, 0.01); + + // Interpolate the width + Point width_left(t1, left.width, openshot::InterpolationType::LINEAR); + Point width_right(t2, right.width, openshot::InterpolationType::LINEAR); + Point width = InterpolateBetween(width_left, width_right, target, 0.01); + + // Interpolate the height + Point height_left(t1, left.height, openshot::InterpolationType::LINEAR); + Point height_right(t2, right.height, openshot::InterpolationType::LINEAR); + Point height = InterpolateBetween(height_left, height_right, target, 0.01); + + // Interpolate the rotation angle + Point angle_left(t1, left.angle, openshot::InterpolationType::LINEAR); + Point angle_right(t1, right.angle, openshot::InterpolationType::LINEAR); + Point angle = InterpolateBetween(angle_left, angle_right, target, 0.01); + + // Create a bounding box with the interpolated points + BBox interpolatedBox(cx.co.Y, cy.co.Y, width.co.Y, height.co.Y, angle.co.Y); + + return interpolatedBox; } // Update object's BaseFps @@ -348,16 +345,18 @@ bool KeyFrameBBox::LoadBoxData(std::string inputFilePath) // Get bounding box data from current frame const libopenshottracker::Frame::Box &box = pbFrameData.bounding_box(); - - float x1 = box.x1(); - float y1 = box.y1(); - float x2 = box.x2(); - float y2 = box.y2(); - if ( (x1 >= 0.0) && (y1 >= 0.0) && (x2 >= 0.0) && (y2 >= 0.0) ) + float width = box.x2() - box.x1(); + float height = box.y2() - box.y1(); + float cx = box.x1() + width/2; + float cy = box.y1() + height/2; + float angle = 0.0; + + + if ( (cx >= 0.0) && (cy >= 0.0) && (width >= 0.0) && (height >= 0.0) ) { // The bounding-box properties are valid, so add it to the BoxVec map - this->AddBox(frame_number, x1, y1, (x2 - x1), (y2 - y1)); + this->AddBox(frame_number, cx, cy, width, height, angle); } } @@ -464,7 +463,6 @@ void KeyFrameBBox::SetJsonValue(const Json::Value root) // Insert BBox into the BoxVec map BBox box; box.SetJsonValue(existing_point["data"]); - //BoxVec.insert({existing_point["time"].asDouble(), box}); BoxVec[existing_point["time"].asDouble()] = box; } } @@ -482,4 +480,4 @@ void KeyFrameBBox::SetJsonValue(const Json::Value root) rotation.SetJsonValue(root["rotation"]); return; -} \ No newline at end of file +} diff --git a/src/KeyFrameBBox.h b/src/KeyFrameBBox.h index fb7fc16a4..4480bddbf 100644 --- a/src/KeyFrameBBox.h +++ b/src/KeyFrameBBox.h @@ -60,10 +60,11 @@ namespace openshot struct BBox { - float x1 = -1; ///< x-coordinate of the top left corner - float y1 = -1; ///< y-coordinate of the top left corner + float cx = -1; ///< x-coordinate of the bounding box center + float cy = -1; ///< y-coordinate of the bounding box center float width = -1; ///< bounding box width float height = -1; ///< bounding box height + float angle = -1; ///< bounding box rotation angle [degrees] /// Blank constructor BBox() @@ -72,18 +73,21 @@ namespace openshot } /// Default constructor, which takes the bounding box top-left corner coordinates, width and height. - /// @param _x1 X-coordinate of the top left corner - /// @param _y1 Y-coordinate of the top left corner + /// @param _cx X-coordinate of the bounding box center + /// @param _cy Y-coordinate of the bounding box center /// @param _width Bounding box width - /// @param _height Bouding box height - BBox(float _x1, float _y1, float _width, float _height) + /// @param _height Bounding box height + /// @param _angle Bounding box rotation angle [degrees] + BBox(float _cx, float _cy, float _width, float _height, float _angle) { - x1 = _x1; - y1 = _y1; + cx = _cx; + cy = _cy; width = _width; height = _height; + angle = _angle; } + /// Generate JSON string of this object std::string Json() const { @@ -94,10 +98,11 @@ namespace openshot Json::Value JsonValue() const { Json::Value root; - root["x1"] = x1; - root["y1"] = y1; - root["height"] = height; + root["cx"] = cx; + root["cy"] = cy; root["width"] = width; + root["height"] = height; + root["angle"] = angle; return root; } @@ -124,15 +129,17 @@ namespace openshot { // Set data from Json (if key is found) - if (!root["x1"].isNull()) - x1 = root["x1"].asDouble(); - if (!root["y1"].isNull()) - y1 = root["y1"].asDouble(); - if (!root["height"].isNull()) - height = root["height"].asDouble(); + if (!root["cx"].isNull()) + cx = root["cx"].asDouble(); + if (!root["cy"].isNull()) + cy = root["cy"].asDouble(); if (!root["width"].isNull()) width = root["width"].asDouble(); - } + if (!root["height"].isNull()) + height = root["height"].asDouble(); + if (!root["angle"].isNull()) + angle = root["angle"].asDouble(); + } }; /** @@ -166,7 +173,7 @@ namespace openshot KeyFrameBBox(); /// Add a BBox to the BoxVec map - void AddBox(int64_t _frame_num, float _x1, float _y1, float _width, float _height); + void AddBox(int64_t _frame_num, float _cx, float _cy, float _width, float _height, float _angle); /// Update object's BaseFps void SetBaseFPS(Fraction fps); @@ -214,4 +221,4 @@ namespace openshot } // namespace openshot -#endif \ No newline at end of file +#endif diff --git a/src/effects/Tracker.cpp b/src/effects/Tracker.cpp index d3965ed6f..6833b7f0e 100644 --- a/src/effects/Tracker.cpp +++ b/src/effects/Tracker.cpp @@ -73,11 +73,11 @@ std::shared_ptr Tracker::GetFrame(std::shared_ptr frame, int64_t f cv::Mat frame_image = frame->GetImageCV(); // Check if frame isn't NULL - if(!frame_image.empty()){ - + if(!frame_image.empty()) + { // Check if track data exists for the requested frame - if (trackedData.Contains(frame_number)) { - + if (trackedData.Contains(frame_number)) + { // Get the width and height of the image float fw = frame_image.size().width; float fh = frame_image.size().height; @@ -85,12 +85,18 @@ std::shared_ptr Tracker::GetFrame(std::shared_ptr frame, int64_t f // Get the bounding-box of given frame BBox fd = this->trackedData.GetValue(frame_number); - // Draw the bounding-box on the image - cv::Rect2d box((int)( (fd.x1 ) * fw ), - (int)( (fd.y1 ) * fh ), - (int)( (fd.width) * fw), - (int)( (fd.height) * fh) ); - cv::rectangle(frame_image, box, cv::Scalar( 255, 0, 0 ), 2, 1 ); + // 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); + // 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); + } } } @@ -194,10 +200,10 @@ std::string Tracker::PropertiesJSON(int64_t requested_frame) const { // Get the bounding-box for the given-frame BBox fd = trackedData.GetValue(requested_frame); // Add the data of given frame bounding-box to the JSON object - root["x1"] = add_property_json("X1", fd.x1, "float", "", NULL, 0.0, 1.0, false, requested_frame); - root["y1"] = add_property_json("Y1", fd.y1, "float", "", NULL, 0.0, 1.0, false, requested_frame); - root["x2"] = add_property_json("X2", fd.x1+fd.width, "float", "", NULL, 0.0, 1.0, false, requested_frame); - root["y2"] = add_property_json("Y2", fd.y1+fd.height, "float", "", NULL, 0.0, 1.0, false, requested_frame); + root["x1"] = add_property_json("X1", fd.cx-(fd.width/2), "float", "", NULL, 0.0, 1.0, false, requested_frame); + root["y1"] = add_property_json("Y1", fd.cy-(fd.height/2), "float", "", NULL, 0.0, 1.0, false, requested_frame); + root["x2"] = add_property_json("X2", fd.cx+(fd.width/2), "float", "", NULL, 0.0, 1.0, false, requested_frame); + root["y2"] = add_property_json("Y2", fd.cy+(fd.height/2), "float", "", NULL, 0.0, 1.0, false, requested_frame); // Add the bounding-box Keyframes to the JSON object root["delta_x"] = add_property_json("Displacement X-axis", trackedData.delta_x.GetValue(requested_frame), "float", "", &trackedData.delta_x, -1.0, 1.0, false, requested_frame); @@ -260,4 +266,4 @@ void Tracker::SetJson(int64_t requested_frame, const std::string value) throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } return; -} \ No newline at end of file +} diff --git a/tests/KeyFrame_Tests.cpp b/tests/KeyFrame_Tests.cpp index 50ce041b3..05cd5109f 100644 --- a/tests/KeyFrame_Tests.cpp +++ b/tests/KeyFrame_Tests.cpp @@ -505,7 +505,7 @@ TEST(KeyFrameBBox_init_test) { TEST(KeyFrameBBox_addBox_test) { KeyFrameBBox kfb; - kfb.AddBox(1, 10.0, 10.0, 100.0, 100.0); + kfb.AddBox(1, 10.0, 10.0, 100.0, 100.0, 0.0); CHECK_EQUAL(true, kfb.Contains(1)); CHECK_EQUAL(1, kfb.GetLength()); @@ -520,43 +520,44 @@ TEST(KeyFrameBBox_addBox_test) { TEST(KeyFrameBBox_GetVal_test) { KeyFrameBBox kfb; - kfb.AddBox(1, 10.0, 10.0, 100.0, 100.0); + kfb.AddBox(1, 10.0, 10.0, 100.0, 100.0, 0.0); BBox val = kfb.GetValue(1); - CHECK_EQUAL(10.0, val.x1); - CHECK_EQUAL(10.0, val.y1); + CHECK_EQUAL(10.0, val.cx); + CHECK_EQUAL(10.0, val.cy); CHECK_EQUAL(100.0,val.width); CHECK_EQUAL(100.0,val.height); + CHECK_EQUAL(0.0, val.angle); } TEST(KeyFrameBBox_GetVal_Interpolation) { KeyFrameBBox kfb; - kfb.AddBox(1, 10.0, 10.0, 100.0, 100.0); - kfb.AddBox(11, 20.0, 20.0, 100.0, 100.0); - kfb.AddBox(21, 30.0, 30.0, 100.0, 100.0); - kfb.AddBox(31, 40.0, 40.0, 100.0, 100.0); + kfb.AddBox(1, 10.0, 10.0, 100.0, 100.0, 0.0); + kfb.AddBox(11, 20.0, 20.0, 100.0, 100.0, 0.0); + kfb.AddBox(21, 30.0, 30.0, 100.0, 100.0, 0.0); + kfb.AddBox(31, 40.0, 40.0, 100.0, 100.0, 0.0); BBox val = kfb.GetValue(5); - CHECK_EQUAL(14.0, val.x1); - CHECK_EQUAL(14.0, val.y1); + CHECK_EQUAL(14.0, val.cx); + CHECK_EQUAL(14.0, val.cy); CHECK_EQUAL(100.0,val.width); - CHECK_EQUAL(100.0, val.height); + CHECK_EQUAL(100.0,val.height); val = kfb.GetValue(15); - CHECK_EQUAL(24.0, val.x1); - CHECK_EQUAL(24.0, val.y1); + CHECK_EQUAL(24.0, val.cx); + CHECK_EQUAL(24.0, val.cy); CHECK_EQUAL(100.0,val.width); CHECK_EQUAL(100.0, val.height); val = kfb.GetValue(25); - CHECK_EQUAL(34.0, val.x1); - CHECK_EQUAL(34.0, val.y1); + CHECK_EQUAL(34.0, val.cx); + CHECK_EQUAL(34.0, val.cy); CHECK_EQUAL(100.0,val.width); CHECK_EQUAL(100.0, val.height); @@ -566,10 +567,10 @@ TEST(KeyFrameBBox_GetVal_Interpolation) { TEST(KeyFrameBBox_Json_set) { KeyFrameBBox kfb; - kfb.AddBox(1, 10.0, 10.0, 100.0, 100.0); - kfb.AddBox(10, 20.0, 20.0, 100.0, 100.0); - kfb.AddBox(20, 30.0, 30.0, 100.0, 100.0); - kfb.AddBox(30, 40.0, 40.0, 100.0, 100.0); + kfb.AddBox(1, 10.0, 10.0, 100.0, 100.0, 0.0); + kfb.AddBox(10, 20.0, 20.0, 100.0, 100.0, 0.0); + kfb.AddBox(20, 30.0, 30.0, 100.0, 100.0, 0.0); + kfb.AddBox(30, 40.0, 40.0, 100.0, 100.0, 0.0); kfb.scale_x.AddPoint(1, 2.0); kfb.scale_x.AddPoint(10, 3.0); @@ -591,16 +592,17 @@ TEST(KeyFrameBBox_Json_set) { BBox kfb_bbox = kfb.BoxVec[time_kfb]; BBox fromJSON_bbox = fromJSON_kfb.BoxVec[time_fromJSON_kfb]; - CHECK_EQUAL(kfb_bbox.x1, fromJSON_bbox.x1); - CHECK_EQUAL(kfb_bbox.y1, fromJSON_bbox.y1); + CHECK_EQUAL(kfb_bbox.cx, fromJSON_bbox.cx); + CHECK_EQUAL(kfb_bbox.cy, fromJSON_bbox.cy); CHECK_EQUAL(kfb_bbox.width, fromJSON_bbox.width); CHECK_EQUAL(kfb_bbox.height, fromJSON_bbox.height); + CHECK_EQUAL(kfb_bbox.angle, fromJSON_bbox.angle); } TEST(KeyFrameBBox_Scale_test){ KeyFrameBBox kfb; - kfb.AddBox(1, 10.0, 10.0, 10.0, 10.0); + kfb.AddBox(1, 10.0, 10.0, 10.0, 10.0, 0.0); kfb.scale_x.AddPoint(1.0, 2.0); kfb.scale_y.AddPoint(1.0, 3.0); From 5b7458ac20d8ab2f02bef810eb60412072cf8dab Mon Sep 17 00:00:00 2001 From: Brenno Date: Thu, 17 Dec 2020 22:08:47 -0300 Subject: [PATCH 12/84] Fixed protobuf message compiling on Mac --- src/protobuf_messages/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/protobuf_messages/CMakeLists.txt b/src/protobuf_messages/CMakeLists.txt index 5752a2160..af8239d88 100644 --- a/src/protobuf_messages/CMakeLists.txt +++ b/src/protobuf_messages/CMakeLists.txt @@ -27,6 +27,7 @@ # Dependencies find_package(Protobuf 3) +include_directories(${PROTOBUF_INCLUDE_DIRS}) file(GLOB ProtoFiles "${CMAKE_CURRENT_SOURCE_DIR}/*.proto") PROTOBUF_GENERATE_CPP(ProtoSources ProtoHeaders ${ProtoFiles}) From b579ea649950293b9259f04919422594451ac886 Mon Sep 17 00:00:00 2001 From: Brenno Date: Tue, 22 Dec 2020 21:32:36 -0300 Subject: [PATCH 13/84] Added functionality to link a clip to a tracked object (Animations) - Added KeyframeBase class - Adjusted the inheritance of KeyframeBase to KeyframeBBox and Keyframe - Added feature to attach clip to bounding box - Added support to select tracked object with a dropdown list and removed keyframebbox downcasting --- src/CMakeLists.txt | 1 + src/Clip.cpp | 91 ++++++++++++-- src/Clip.h | 18 ++- src/KeyFrame.cpp | 63 +--------- src/KeyFrame.h | 9 +- src/KeyFrameBBox.cpp | 249 ++++++++++++++++++--------------------- src/KeyFrameBBox.h | 38 ++++-- src/KeyFrameBase.cpp | 107 +++++++++++++++++ src/KeyFrameBase.h | 98 +++++++++++++++ src/Timeline.cpp | 51 +++++++- src/Timeline.h | 12 +- src/TimelineBase.cpp | 9 ++ src/TimelineBase.h | 7 +- src/effects/Tracker.cpp | 114 ++++++------------ src/effects/Tracker.h | 5 +- tests/KeyFrame_Tests.cpp | 82 +++++++++++-- 16 files changed, 644 insertions(+), 310 deletions(-) create mode 100644 src/KeyFrameBase.cpp create mode 100644 src/KeyFrameBase.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index faa23d251..1d2a59067 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -86,6 +86,7 @@ set(OPENSHOT_SOURCES FrameMapper.cpp Json.cpp KeyFrame.cpp + KeyFrameBase.cpp KeyFrameBBox.cpp OpenShotVersion.cpp ZmqLogger.cpp diff --git a/src/Clip.cpp b/src/Clip.cpp index 79c9b75ec..de7a8c6f5 100644 --- a/src/Clip.cpp +++ b/src/Clip.cpp @@ -39,6 +39,7 @@ #include "ChunkReader.h" #include "DummyReader.h" #include "Timeline.h" +#include "effects/Tracker.h" using namespace openshot; @@ -57,6 +58,7 @@ void Clip::init_settings() mixing = VOLUME_MIX_NONE; waveform = false; previous_properties = ""; + attached_id = ""; // Init scale curves scale_x = Keyframe(1.0); @@ -242,6 +244,31 @@ Clip::~Clip() } } +// Attach clip to bounding box +void Clip::AttachToTracker(std::string tracked_id) +{ + // Search for the tracked object on the timeline + Timeline *parentTimeline = (Timeline *) ParentTimeline(); + + // Create a smart pointer to the tracked object from the timeline + std::shared_ptr trackedObject = parentTimeline->GetTrackedObject(tracked_id); + + // Check for valid tracked object + if (trackedObject){ + SetAttachedObject(trackedObject); + return; + } + else{ + return; + } +} + +// Set the pointer to the trackedObject this clip is attached to +void Clip::SetAttachedObject(std::shared_ptr trackedObject){ + attachedObject = trackedObject; + return; +} + /// Set the current reader void Clip::Reader(ReaderBase* new_reader) { @@ -762,7 +789,24 @@ std::string Clip::PropertiesJSON(int64_t requested_frame) const { root["display"] = add_property_json("Frame Number", display, "int", "", NULL, 0, 3, false, requested_frame); root["mixing"] = add_property_json("Volume Mixing", mixing, "int", "", NULL, 0, 2, false, requested_frame); root["waveform"] = add_property_json("Waveform", waveform, "int", "", NULL, 0, 1, false, requested_frame); - + root["attached_id"] = add_property_json("Attached ID", 0.0, "string", GetAttachedId(), NULL, -1, -1, false, requested_frame); + + // Add attached id choices (dropdown style) + if (timeline){ + Timeline* parentTimeline = (Timeline *) timeline; + std::vector tracked_ids = parentTimeline->GetTrackedObjectsIds(); + Json::Value temp; + temp["name"] = ""; + temp["value"] = ""; + temp["selected"] = true; + root["attached_id"]["choices"].append(temp); + for (auto it = tracked_ids.begin(); it != tracked_ids.end(); ++it){ + temp["name"] = *it; + temp["value"] = *it; + temp["selected"] = true; + root["attached_id"]["choices"].append(temp); + } + } // Add gravity choices (dropdown style) root["gravity"]["choices"].append(add_property_choice_json("Top Left", GRAVITY_TOP_LEFT, gravity)); root["gravity"]["choices"].append(add_property_choice_json("Top Center", GRAVITY_TOP, gravity)); @@ -836,6 +880,7 @@ Json::Value Clip::JsonValue() const { // Create root json object Json::Value root = ClipBase::JsonValue(); // get parent properties + root["attached_id"] = attached_id; root["gravity"] = gravity; root["scale"] = scale; root["anchor"] = anchor; @@ -913,6 +958,11 @@ void Clip::SetJsonValue(const Json::Value root) { cache.Clear(); // Set data from Json (if key is found) + if (!root["attached_id"].isNull()) + attached_id = root["attached_id"].asString(); + if (attached_id.size() > 0){ + AttachToTracker(attached_id); + } if (!root["gravity"].isNull()) gravity = (GravityType) root["gravity"].asInt(); if (!root["scale"].isNull()) @@ -1096,6 +1146,21 @@ void Clip::AddEffect(EffectBase* effect) // Sort effects sort_effects(); + // Add Tracker to Timeline + if (effect->info.class_name == "Tracker"){ + + Timeline* parentTimeline = (Timeline *) ParentTimeline(); + + // Downcast effect as Tracker + Tracker* tracker = (Tracker *) effect; + + // Get tracked data from the Tracker effect + std::shared_ptr trackedData = tracker->trackedData; + + // Add tracked data to the timeline + parentTimeline->AddTrackedObject(trackedData); + } + // Clear cache cache.Clear(); } @@ -1213,6 +1278,21 @@ void Clip::apply_keyframes(std::shared_ptr frame, int width, int height) } } + /* TRANSFORM CLIP TO ATTACHED OBJECT'S POSITION AND DIMENSION */ + if (attachedObject){ + + // Access the KeyframeBBox properties + std::map boxValues = attachedObject->GetBoxValues(frame->number); + + // Set the bounding box keyframes to this clip keyframes + location_x.AddPoint(frame->number, (boxValues["cx"]-0.5)); + location_y.AddPoint(frame->number, (boxValues["cy"]-0.5)); + scale_x.AddPoint(frame->number, boxValues["w"]*boxValues["sx"]*2.0); + scale_y.AddPoint(frame->number, boxValues["h"]*boxValues["sy"]); + rotation.AddPoint(frame->number, boxValues["r"]); + + } + /* GRAVITY LOCATION - Initialize X & Y to the correct values (before applying location curves) */ float x = 0.0; // left float y = 0.0; // top @@ -1261,6 +1341,8 @@ void Clip::apply_keyframes(std::shared_ptr frame, int width, int height) // Debug output ZmqLogger::Instance()->AppendDebugMethod("Clip::apply_keyframes (Gravity)", "frame->number", frame->number, "source_clip->gravity", gravity, "scaled_source_width", scaled_source_width, "scaled_source_height", scaled_source_height); + QTransform transform; + /* LOCATION, ROTATION, AND SCALE */ float r = rotation.GetValue(frame->number); // rotate in degrees x += (width * location_x.GetValue(frame->number)); // move in percentage of final width @@ -1270,16 +1352,13 @@ void Clip::apply_keyframes(std::shared_ptr frame, int width, int height) float origin_x_value = origin_x.GetValue(frame->number); float origin_y_value = origin_y.GetValue(frame->number); - QTransform transform; - // Transform source image (if needed) ZmqLogger::Instance()->AppendDebugMethod("Clip::apply_keyframes (Build QTransform - if needed)", "frame->number", frame->number, "x", x, "y", y, "r", r, "sx", sx, "sy", sy); if (!isEqual(x, 0) || !isEqual(y, 0)) { // TRANSLATE/MOVE CLIP transform.translate(x, y); - } - + } if (!isEqual(r, 0) || !isEqual(shear_x_value, 0) || !isEqual(shear_y_value, 0)) { // ROTATE CLIP (around origin_x, origin_y) float origin_x_offset = (scaled_source_width * origin_x_value); @@ -1289,11 +1368,9 @@ void Clip::apply_keyframes(std::shared_ptr frame, int width, int height) transform.shear(shear_x_value, shear_y_value); transform.translate(-origin_x_offset,-origin_y_offset); } - // SCALE CLIP (if needed) float source_width_scale = (float(source_size.width()) / float(source_image->width())) * sx; float source_height_scale = (float(source_size.height()) / float(source_image->height())) * sy; - if (!isEqual(source_width_scale, 1.0) || !isEqual(source_height_scale, 1.0)) { transform.scale(source_width_scale, source_height_scale); } diff --git a/src/Clip.h b/src/Clip.h index e2521532a..0886f7894 100644 --- a/src/Clip.h +++ b/src/Clip.h @@ -54,6 +54,7 @@ #include "Fraction.h" #include "Frame.h" #include "KeyFrame.h" +#include "KeyFrameBase.h" #include "ReaderBase.h" #include "JuceHeader.h" @@ -123,6 +124,8 @@ namespace openshot { bool waveform; ///< Should a waveform be used instead of the clip's image std::list effects; /// Is Reader opened + std::string attached_id; ///< Id of the bounding box that this clip is attached to + std::shared_ptr attachedObject; // Audio resampler (if time mapping) openshot::AudioResampler *resampler; @@ -161,8 +164,6 @@ namespace openshot { /// Reverse an audio buffer void reverse_buffer(juce::AudioSampleBuffer* buffer); - - public: openshot::GravityType gravity; ///< The gravity of a clip determines where it snaps to its parent openshot::ScaleType scale; ///< The scale determines how a clip should be resized to fit its parent @@ -196,6 +197,19 @@ namespace openshot { /// Determine if reader is open or closed bool IsOpen() override { return is_open; }; + /// Get and set the bounding box that this clip is attached to + std::string GetAttachedId() const { return attached_id; }; + /// Set id of the bounding box that this clip is attached to + void SetAttachedId(std::string value) { attached_id = value; }; + + /// Attach clip to bounding box + void AttachToTracker(std::string tracked_id); + + /// Set the pointer to the trackedObject this clip is attached to + void SetAttachedObject(std::shared_ptr trackedObject); + /// Return a pointer to the trackedObject this clip is attached to + std::shared_ptr GetAttachedObject() const { return attachedObject; }; + /// Return the type name of the class std::string Name() override { return "Clip"; }; diff --git a/src/KeyFrame.cpp b/src/KeyFrame.cpp index b113e6325..4441f6a9d 100644 --- a/src/KeyFrame.cpp +++ b/src/KeyFrame.cpp @@ -36,66 +36,7 @@ using namespace std; using namespace openshot; -namespace { - bool IsPointBeforeX(Point const & p, double const x) { - return p.co.X < x; - } - - double InterpolateLinearCurve(Point const & left, Point const & right, double const target) { - double const diff_Y = right.co.Y - left.co.Y; - double const diff_X = right.co.X - left.co.X; - double const slope = diff_Y / diff_X; - return left.co.Y + slope * (target - left.co.X); - } - - double InterpolateBezierCurve(Point const & left, Point const & right, double const target, double const allowed_error) { - double const X_diff = right.co.X - left.co.X; - double const Y_diff = right.co.Y - left.co.Y; - Coordinate const p0 = left.co; - Coordinate const p1 = Coordinate(p0.X + left.handle_right.X * X_diff, p0.Y + left.handle_right.Y * Y_diff); - Coordinate const p2 = Coordinate(p0.X + right.handle_left.X * X_diff, p0.Y + right.handle_left.Y * Y_diff); - Coordinate const p3 = right.co; - - double t = 0.5; - double t_step = 0.25; - do { - // Bernstein polynoms - double B[4] = {1, 3, 3, 1}; - double oneMinTExp = 1; - double tExp = 1; - for (int i = 0; i < 4; ++i, tExp *= t) { - B[i] *= tExp; - } - for (int i = 0; i < 4; ++i, oneMinTExp *= 1 - t) { - B[4 - i - 1] *= oneMinTExp; - } - double const x = p0.X * B[0] + p1.X * B[1] + p2.X * B[2] + p3.X * B[3]; - double const y = p0.Y * B[0] + p1.Y * B[1] + p2.Y * B[2] + p3.Y * B[3]; - if (fabs(target - x) < allowed_error) { - return y; - } - if (x > target) { - t -= t_step; - } - else { - t += t_step; - } - t_step /= 2; - } while (true); - } - - - double InterpolateBetween(Point const & left, Point const & right, double target, double allowed_error) { - assert(left.co.X < target); - assert(target <= right.co.X); - switch (right.interpolation) { - case CONSTANT: return left.co.Y; - case LINEAR: return InterpolateLinearCurve(left, right, target); - case BEZIER: return InterpolateBezierCurve(left, right, target, allowed_error); - } - } - - +namespace{ template int64_t SearchBetweenPoints(Point const & left, Point const & right, int64_t const current, Check check) { int64_t start = left.co.X; @@ -114,6 +55,7 @@ namespace { } + // Constructor which sets the default point & coordinate at X=1 Keyframe::Keyframe(double value) { // Add initial point @@ -544,6 +486,7 @@ void Keyframe::RemovePoint(int64_t index) { throw OutOfBoundsPoint("Invalid point requested", index, Points.size()); } +// Replace an existing point with a new point void Keyframe::UpdatePoint(int64_t index, Point p) { // Remove matching point RemovePoint(index); diff --git a/src/KeyFrame.h b/src/KeyFrame.h index 6424473a9..5ff191e4f 100644 --- a/src/KeyFrame.h +++ b/src/KeyFrame.h @@ -41,6 +41,7 @@ #include "Coordinate.h" #include "Point.h" #include "Json.h" +#include "KeyFrameBase.h" namespace openshot { @@ -61,9 +62,11 @@ namespace openshot { * kf.PrintValues(); * \endcode */ - class Keyframe { + class Keyframe : public KeyframeBase { + + private: - std::vector Points; ///< Vector of all Points + std::vector Points; ///< Vector of all Points public: @@ -145,7 +148,7 @@ namespace openshot { /// Scale all points by a percentage (good for evenly lengthening or shortening an openshot::Keyframe) /// 1.0 = same size, 1.05 = 5% increase, etc... - void ScalePoints(double scale); + void ScalePoints(double scale) override; /// Replace an existing point with a new point void UpdatePoint(int64_t index, Point p); diff --git a/src/KeyFrameBBox.cpp b/src/KeyFrameBBox.cpp index 7109101df..def7c186b 100644 --- a/src/KeyFrameBBox.cpp +++ b/src/KeyFrameBBox.cpp @@ -34,105 +34,9 @@ #include #include -//#define PI 3.14159265 - using namespace std; using namespace openshot; -namespace openshot -{ - bool IsPointBeforeX(Point const &p, double const x) - { - return p.co.X < x; - } - - double InterpolateLinearCurve(Point const &left, Point const &right, double const target) - { - double const diff_Y = right.co.Y - left.co.Y; - double const diff_X = right.co.X - left.co.X; - double const slope = diff_Y / diff_X; - return left.co.Y + slope * (target - left.co.X); - } - - double InterpolateBezierCurve(Point const &left, Point const &right, double const target, double const allowed_error) - { - double const X_diff = right.co.X - left.co.X; - double const Y_diff = right.co.Y - left.co.Y; - Coordinate const p0 = left.co; - Coordinate const p1 = Coordinate(p0.X + left.handle_right.X * X_diff, p0.Y + left.handle_right.Y * Y_diff); - Coordinate const p2 = Coordinate(p0.X + right.handle_left.X * X_diff, p0.Y + right.handle_left.Y * Y_diff); - Coordinate const p3 = right.co; - - double t = 0.5; - double t_step = 0.25; - do - { - // Bernstein polynoms - double B[4] = {1, 3, 3, 1}; - double oneMinTExp = 1; - double tExp = 1; - for (int i = 0; i < 4; ++i, tExp *= t) - { - B[i] *= tExp; - } - for (int i = 0; i < 4; ++i, oneMinTExp *= 1 - t) - { - B[4 - i - 1] *= oneMinTExp; - } - double const x = p0.X * B[0] + p1.X * B[1] + p2.X * B[2] + p3.X * B[3]; - double const y = p0.Y * B[0] + p1.Y * B[1] + p2.Y * B[2] + p3.Y * B[3]; - if (fabs(target - x) < allowed_error) - { - return y; - } - if (x > target) - { - t -= t_step; - } - else - { - t += t_step; - } - t_step /= 2; - } while (true); - } - - double InterpolateBetween(Point const &left, Point const &right, double target, double allowed_error) - { - assert(left.co.X < target); - assert(target <= right.co.X); - switch (right.interpolation) - { - case CONSTANT: - return left.co.Y; - case LINEAR: - return InterpolateLinearCurve(left, right, target); - case BEZIER: - return InterpolateBezierCurve(left, right, target, allowed_error); - } - } - - template - int64_t SearchBetweenPoints(Point const &left, Point const &right, int64_t const current, Check check) - { - int64_t start = left.co.X; - int64_t stop = right.co.X; - while (start < stop) - { - int64_t const mid = (start + stop + 1) / 2; - double const value = InterpolateBetween(left, right, mid, 0.01); - if (check(round(value), current)) - { - start = mid; - } - else - { - stop = mid - 1; - } - } - return start; - } -} // namespace openshot // Default Constructor that sets the bounding-box displacement as 0 and the scales as 1 for the first frame KeyFrameBBox::KeyFrameBBox() : delta_x(0.0), delta_y(0.0), scale_x(1.0), scale_y(1.0), rotation(0.0) @@ -207,7 +111,7 @@ void KeyFrameBBox::RemoveBox(int64_t frame_number) } // Return a bounding-box from BoxVec with it's properties adjusted by the Keyframes -BBox KeyFrameBBox::GetValue(int64_t frame_number) +BBox KeyFrameBBox::GetBox(int64_t frame_number) { // Get the time position of the given frame. double time = this->FrameNToTime(frame_number, this->TimeScale); @@ -372,33 +276,32 @@ bool KeyFrameBBox::LoadBoxData(std::string inputFilePath) return true; } +// Clear the BoxVec map +void KeyFrameBBox::clear() +{ + BoxVec.clear(); +} + // Generate JSON string of this object -std::string KeyFrameBBox::Json() +std::string KeyFrameBBox::Json() const { // Return formatted string return JsonValue().toStyledString(); } // Generate Json::Value for this object -Json::Value KeyFrameBBox::JsonValue() +Json::Value KeyFrameBBox::JsonValue() const { // Create root json object Json::Value root; + // Object's properties + root["box_id"] = Id(); root["BaseFPS"]["num"] = BaseFps.num; root["BaseFPS"]["den"] = BaseFps.den; - root["TimeScale"] = this->TimeScale; - root["Boxes"] = Json::Value(Json::arrayValue); + root["TimeScale"] = TimeScale; - // Loop through the BoxVec map and save the BBox data - for (auto const &x : BoxVec) - { - Json::Value box; - box["time"] = x.first; - box["data"] = x.second.JsonValue(); - root["Boxes"].append(box); - } - // Get the Keyframe's Json strings + // Keyframe's properties root["delta_x"] = delta_x.JsonValue(); root["delta_y"] = delta_y.JsonValue(); root["scale_x"] = scale_x.JsonValue(); @@ -427,45 +330,32 @@ void KeyFrameBBox::SetJson(const std::string value) return; } -// Clear the BoxVec map -void KeyFrameBBox::clear() -{ - BoxVec.clear(); -} - // Load Json::Value into this object void KeyFrameBBox::SetJsonValue(const Json::Value root) -{ - // Clear BoxVec - this->clear(); +{ + // Set the Id + if (!root["box_id"].isNull()) + SetId(root["box_id"].asString()); + + // Set the BaseFps by the given JSON object if (!root["BaseFPS"].isNull() && root["BaseFPS"].isObject()) - { - // Set the BaseFps by the given JSON object + { if (!root["BaseFPS"]["num"].isNull()) BaseFps.num = (int)root["BaseFPS"]["num"].asInt(); if (!root["BaseFPS"]["den"].isNull()) BaseFps.den = (int)root["BaseFPS"]["den"].asInt(); } + // Set the TimeScale by the given JSON object if (!root["TimeScale"].isNull()) { - // Set the TimeScale by the given JSON object double scale = (double)root["TimeScale"].asDouble(); this->ScalePoints(scale); } - if (!root["Boxes"].isNull()) - { - // Loop through the BBoxes data - for (const auto existing_point : root["Boxes"]) - { - // Insert BBox into the BoxVec map - BBox box; - box.SetJsonValue(existing_point["data"]); - BoxVec[existing_point["time"].asDouble()] = box; - } - } + if (!root["protobuf_data_path"].isNull()) + protobufDataPath = root["protobuf_data_path"].asString(); // Set the Keyframes by the given JSON object if (!root["delta_x"].isNull()) @@ -481,3 +371,96 @@ void KeyFrameBBox::SetJsonValue(const Json::Value root) return; } + +// Get all properties for a specific frame (perfect for a UI to display the current state +// of all properties at any time) +Json::Value KeyFrameBBox::PropertiesJSON(int64_t requested_frame) const +{ + Json::Value root; + + BBox box = GetBox(requested_frame); + + // Id + root["box_id"] = add_property_json("Box ID", 0.0, "string", Id(), 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); + root["x2"] = add_property_json("X2", box.cx+(box.width/2), "float", "", NULL, 0.0, 1.0, false, requested_frame); + root["y2"] = add_property_json("Y2", box.cy+(box.height/2), "float", "", NULL, 0.0, 1.0, false, requested_frame); + + // 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["rotation"] = add_property_json("Rotation", rotation.GetValue(requested_frame), "float", "", &rotation, 0, 360, false, requested_frame); + + // Return formatted string + return root; +} + + +// Generate JSON for a property +Json::Value KeyFrameBBox::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 { + + // Requested Point + const Point requested_point(requested_frame, requested_frame); + + // Create JSON Object + Json::Value prop = Json::Value(Json::objectValue); + prop["name"] = name; + prop["value"] = value; + prop["memo"] = memo; + prop["type"] = type; + prop["min"] = min_value; + prop["max"] = max_value; + if (keyframe) { + prop["keyframe"] = keyframe->Contains(requested_point); + prop["points"] = int(keyframe->GetCount()); + Point closest_point = keyframe->GetClosestPoint(requested_point); + prop["interpolation"] = closest_point.interpolation; + prop["closest_point_x"] = closest_point.co.X; + prop["previous_point_x"] = keyframe->GetPreviousPoint(closest_point).co.X; + } + else { + prop["keyframe"] = false; + prop["points"] = 0; + prop["interpolation"] = CONSTANT; + prop["closest_point_x"] = -1; + prop["previous_point_x"] = -1; + } + + prop["readonly"] = readonly; + prop["choices"] = Json::Value(Json::arrayValue); + + // return JsonValue + return prop; +} + +// Return the bounding box properties and it's keyframes indexed by their names +std::map KeyFrameBBox::GetBoxValues(int64_t frame_number){ + + // Create the map + std::map boxValues; + + // Get bounding box of the current frame + BBox box = GetBox(frame_number); + + // Save the bounding box properties + boxValues["cx"] = box.cx; + boxValues["cy"] = box.cy; + boxValues["w"] = box.width; + boxValues["h"] = box.height; + boxValues["ang"] = box.angle; + + // Save the keyframes values + boxValues["sx"] = this->scale_x.GetValue(frame_number); + boxValues["sy"] = this->scale_y.GetValue(frame_number); + boxValues["dx"] = this->delta_x.GetValue(frame_number); + boxValues["dy"] = this->delta_y.GetValue(frame_number); + boxValues["r"] = this->rotation.GetValue(frame_number); + + + return boxValues; +} \ No newline at end of file diff --git a/src/KeyFrameBBox.h b/src/KeyFrameBBox.h index 4480bddbf..16b0323d3 100644 --- a/src/KeyFrameBBox.h +++ b/src/KeyFrameBBox.h @@ -1,6 +1,6 @@ /** * @file - * @brief Header file for the IKeyframe class + * @brief Header file for the KeyFrameBBox class * @author Jonathan Thomas * * @ref License @@ -43,9 +43,11 @@ #include "Json.h" #include "IKeyFrame.h" #include "KeyFrame.h" +#include "KeyFrameBase.h" #include "trackerdata.pb.h" #include + using google::protobuf::util::TimeUtil; namespace openshot @@ -153,12 +155,12 @@ namespace openshot * object of this class. */ - class KeyFrameBBox + class KeyFrameBBox : public KeyframeBase { private: bool visible; Fraction BaseFps; - double TimeScale; + double TimeScale; public: std::map BoxVec; ///< Index the bounding-box by time of each frame @@ -182,7 +184,7 @@ namespace openshot Fraction GetBaseFPS(); /// Update the TimeScale member variable - void ScalePoints(double scale); + void ScalePoints(double scale) override; /// Check if there is a bounding-box in the given frame bool Contains(int64_t frame_number); @@ -194,11 +196,11 @@ namespace openshot void RemoveBox(int64_t frame_number); /// Return a bounding-box from BoxVec with it's properties adjusted by the Keyframes - BBox GetValue(int64_t frame_number) const + BBox GetBox(int64_t frame_number) const { - return const_cast(this)->GetValue(frame_number); + return const_cast(this)->GetBox(frame_number); } - BBox GetValue(int64_t frame_number); + BBox GetBox(int64_t frame_number); /// Load the bounding-boxes information from the protobuf file bool LoadBoxData(std::string inputFilePath); @@ -209,16 +211,26 @@ namespace openshot /// Interpolate the bouding-boxes properties BBox InterpolateBoxes(double t1, double t2, BBox left, BBox right, double target); + /// Clear the BoxVec map + void clear(); + /// Get and Set JSON methods - std::string Json(); ///< Generate JSON string of this object - Json::Value JsonValue(); ///< Generate Json::Value for this object + std::string Json() const; ///< Generate JSON string of this object + Json::Value JsonValue() const; ///< Generate Json::Value for this object void SetJson(const std::string value); ///< Load JSON string into this object void SetJsonValue(const Json::Value root); ///< Load Json::Value into this object - /// Clear the BoxVec map - void clear(); - }; + /// Get all properties for a specific frame (perfect for a UI to display the current state + /// of all properties at any time) + Json::Value PropertiesJSON(int64_t requested_frame) const; + // Generate JSON for a property + 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; + + /// Return the bounding box properties and it's keyframes indexed by their names + std::map GetBoxValues(int64_t frame_number) override; + + }; } // namespace openshot -#endif +#endif \ No newline at end of file diff --git a/src/KeyFrameBase.cpp b/src/KeyFrameBase.cpp new file mode 100644 index 000000000..acdf389fc --- /dev/null +++ b/src/KeyFrameBase.cpp @@ -0,0 +1,107 @@ +/** + * @file + * @brief Source file for the KeyframeBase class + * @author Jonathan Thomas + * + * @ref License + */ + +/* LICENSE + * + * Copyright (c) 2008-2019 OpenShot Studios, LLC + * . This file is part of + * OpenShot Library (libopenshot), an open-source project dedicated to + * delivering high quality video editing and animation solutions to the + * world. For more information visit . + * + * OpenShot Library (libopenshot) is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * OpenShot Library (libopenshot) is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OpenShot Library. If not, see . + */ + +#include "KeyFrameBase.h" +#include +#include +#include + + +namespace openshot{ + + // Check if the X coordinate of a given Point is lower than a given value + bool IsPointBeforeX(Point const & p, double const x) { + return p.co.X < x; + } + + // Linear interpolation between two points + double InterpolateLinearCurve(Point const & left, Point const & right, double const target) { + double const diff_Y = right.co.Y - left.co.Y; + double const diff_X = right.co.X - left.co.X; + double const slope = diff_Y / diff_X; + return left.co.Y + slope * (target - left.co.X); + } + + // Bezier interpolation between two points + double InterpolateBezierCurve(Point const & left, Point const & right, double const target, double const allowed_error) { + double const X_diff = right.co.X - left.co.X; + double const Y_diff = right.co.Y - left.co.Y; + Coordinate const p0 = left.co; + Coordinate const p1 = Coordinate(p0.X + left.handle_right.X * X_diff, p0.Y + left.handle_right.Y * Y_diff); + Coordinate const p2 = Coordinate(p0.X + right.handle_left.X * X_diff, p0.Y + right.handle_left.Y * Y_diff); + Coordinate const p3 = right.co; + + double t = 0.5; + double t_step = 0.25; + do { + // Bernstein polynoms + double B[4] = {1, 3, 3, 1}; + double oneMinTExp = 1; + double tExp = 1; + for (int i = 0; i < 4; ++i, tExp *= t) { + B[i] *= tExp; + } + for (int i = 0; i < 4; ++i, oneMinTExp *= 1 - t) { + B[4 - i - 1] *= oneMinTExp; + } + double const x = p0.X * B[0] + p1.X * B[1] + p2.X * B[2] + p3.X * B[3]; + double const y = p0.Y * B[0] + p1.Y * B[1] + p2.Y * B[2] + p3.Y * B[3]; + if (fabs(target - x) < allowed_error) { + return y; + } + if (x > target) { + t -= t_step; + } + else { + t += t_step; + } + t_step /= 2; + } while (true); + } + + // Interpolate two points using the right Point's interpolation method + double InterpolateBetween(Point const & left, Point const & right, double target, double allowed_error) { + assert(left.co.X < target); + assert(target <= right.co.X); + switch (right.interpolation) { + case CONSTANT: return left.co.Y; + case LINEAR: return InterpolateLinearCurve(left, right, target); + case BEZIER: return InterpolateBezierCurve(left, right, target, allowed_error); + } + } + + KeyframeBase::KeyframeBase(){ + id = "TESTBASEID"; + } + + KeyframeBase::KeyframeBase(std::string _id){ + SetId(_id); + } +} \ No newline at end of file diff --git a/src/KeyFrameBase.h b/src/KeyFrameBase.h new file mode 100644 index 000000000..316ed83a4 --- /dev/null +++ b/src/KeyFrameBase.h @@ -0,0 +1,98 @@ +/** + * @file + * @brief Header file for the KeyframeBase class + * @author Jonathan Thomas + * + * @ref License + */ + +/* LICENSE + * + * Copyright (c) 2008-2019 OpenShot Studios, LLC + * . This file is part of + * OpenShot Library (libopenshot), an open-source project dedicated to + * delivering high quality video editing and animation solutions to the + * world. For more information visit . + * + * OpenShot Library (libopenshot) is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * OpenShot Library (libopenshot) is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OpenShot Library. If not, see . + */ + +#ifndef OPENSHOT_KEYFRAMEBASE_H +#define OPENSHOT_KEYFRAMEBASE_H + +#include +#include +#include +#include +#include +#include +#include "Exceptions.h" +#include "Fraction.h" +#include "Coordinate.h" +#include "Point.h" +#include "Json.h" + +namespace openshot { + /** + * @brief This abstract class is the base class of all Keyframes. + * + * A Keyframe is a collection of Point instances, which is used to vary a number or property over time. + * + * Keyframes are used to animate and interpolate values of properties over time. For example, a single property + * can use a Keyframe instead of a constant value. Assume you want to slide an image (from left to right) over + * a video. You can create a Keyframe which will adjust the X value of the image over 100 frames (or however many + * frames the animation needs to last) from the value of 0 to 640. + */ + + /// Check if the X coordinate of a given Point is lower than a given value + bool IsPointBeforeX(Point const & p, double const x); + + /// Linear interpolation between two points + double InterpolateLinearCurve(Point const & left, Point const & right, double const target); + + /// Bezier interpolation between two points + double InterpolateBezierCurve(Point const & left, Point const & right, double const target, double const allowed_error); + + /// Interpolate two points using the right Point's interpolation method + double InterpolateBetween(Point const & left, Point const & right, double target, double allowed_error); + + // template + // int64_t SearchBetweenPoints(Point const & left, Point const & right, int64_t const current, Check check); + + class KeyframeBase{ + private: + std::string id; + + public: + + /// Blank constructor + KeyframeBase(); + + /// Default constructor + KeyframeBase(std::string _id); + + std::string Id() const { return id; } + void SetId(std::string _id) { id = _id; } + + /// Scale all points by a percentage (good for evenly lengthening or shortening an openshot::Keyframe) + /// 1.0 = same size, 1.05 = 5% increase, etc... + virtual void ScalePoints(double scale) { return; }; + + /// Return the main properties of a KeyframeBBox instance using a pointer to this base class + virtual std::map GetBoxValues(int64_t frame_number) { std::map ret; return ret; }; + + }; +} // Namespace openshot + +#endif diff --git a/src/Timeline.cpp b/src/Timeline.cpp index d7377a280..80a2170ab 100644 --- a/src/Timeline.cpp +++ b/src/Timeline.cpp @@ -240,6 +240,55 @@ Timeline::~Timeline() { } } +// Add to the tracked_objects map a pointer to a tracked object (KeyframeBBox) +void Timeline::AddTrackedObject(std::shared_ptr trackedObject){ + + // Search for the tracked object on the map + auto iterator = tracked_objects.find(trackedObject->Id()); + + if (iterator != tracked_objects.end()){ + // Tracked object's id already present on the map, overwrite it + iterator->second = trackedObject; + } + else{ + // Tracked object's id not present -> insert it on the map + tracked_objects[trackedObject->Id()] = trackedObject; + } + return; +} + +// Return tracked object pointer by it's id +std::shared_ptr Timeline::GetTrackedObject(std::string id) const{ + + // Search for the tracked object on the map + auto iterator = tracked_objects.find(id); + + if (iterator != tracked_objects.end()){ + // Id found, return the pointer to the tracked object + std::shared_ptr trackedObject = iterator->second; + return trackedObject; + } + else { + // Id not found, return a null pointer + return nullptr; + } +} + +// Return the ID's of the tracked objects as a vector of strings +std::vector Timeline::GetTrackedObjectsIds() const{ + + // Create a vector of strings + std::vector trackedObjects_ids; + + // Iterate through the tracked_objects map + for (auto const& it: tracked_objects){ + // Add the IDs to the vector + trackedObjects_ids.push_back(it.first); + } + + return trackedObjects_ids; +} + // Add an openshot::Clip to the timeline void Timeline::AddClip(Clip* clip) { @@ -1505,4 +1554,4 @@ void Timeline::SetMaxSize(int width, int height) { // Update preview settings preview_width = display_ratio_size.width(); preview_height = display_ratio_size.height(); -} +} \ No newline at end of file diff --git a/src/Timeline.h b/src/Timeline.h index e12cf3ee5..d5d1bda9b 100644 --- a/src/Timeline.h +++ b/src/Timeline.h @@ -52,6 +52,8 @@ #include "Frame.h" #include "FrameMapper.h" #include "KeyFrame.h" +#include "KeyFrameBBox.h" +#include "KeyFrameBase.h" #include "OpenMPUtilities.h" #include "ReaderBase.h" #include "Settings.h" @@ -177,7 +179,8 @@ namespace openshot { bool managed_cache; ///< Does this timeline instance manage the cache object std::string path; ///< Optional path of loaded UTF-8 OpenShot JSON project file std::mutex get_frame_mutex; ///< Mutex to protect GetFrame method from different threads calling it - + std::map> tracked_objects; ///< map of KeyframeBBoxes and their IDs + /// Process a new layer of video or audio void add_layer(std::shared_ptr new_frame, openshot::Clip* source_clip, int64_t clip_frame_number, int64_t timeline_frame_number, bool is_top_clip, float max_volume); @@ -241,6 +244,13 @@ namespace openshot { virtual ~Timeline(); + /// Add to the tracked_objects map a pointer to a tracked object (KeyframeBBox) + void AddTrackedObject(std::shared_ptr trackedObject); + /// Return tracked object pointer by it's id + std::shared_ptr GetTrackedObject(std::string id) const; + /// Return the ID's of the tracked objects as a vector of strings + std::vector GetTrackedObjectsIds() const; + /// @brief Add an openshot::Clip to the timeline /// @param clip Add an openshot::Clip to the timeline. A clip can contain any type of Reader. void AddClip(openshot::Clip* clip); diff --git a/src/TimelineBase.cpp b/src/TimelineBase.cpp index 4356167f5..6170bff2b 100644 --- a/src/TimelineBase.cpp +++ b/src/TimelineBase.cpp @@ -39,3 +39,12 @@ TimelineBase::TimelineBase() preview_width = 1920; preview_height = 1080; } + +/* This function will be overloaded in the Timeline class passing no arguments +* so we'll be able to access the Timeline::Clips() function from a pointer object of +* the TimelineBase class +*/ +void TimelineBase::Clips(int test){ + std::cout << test << std::endl; + return; +} \ No newline at end of file diff --git a/src/TimelineBase.h b/src/TimelineBase.h index af6a65a20..7bcd8f9a9 100644 --- a/src/TimelineBase.h +++ b/src/TimelineBase.h @@ -30,7 +30,7 @@ #ifndef OPENSHOT_TIMELINE_BASE_H #define OPENSHOT_TIMELINE_BASE_H - +#include namespace openshot { /** @@ -44,6 +44,11 @@ namespace openshot { /// Constructor for the base timeline TimelineBase(); + + /// This function will be overloaded in the Timeline class passing no arguments + /// so we'll be able to access the Timeline::Clips() function from a pointer object of + /// the TimelineBase class + virtual void Clips(int test); }; } diff --git a/src/effects/Tracker.cpp b/src/effects/Tracker.cpp index 6833b7f0e..b5ac70a84 100644 --- a/src/effects/Tracker.cpp +++ b/src/effects/Tracker.cpp @@ -29,6 +29,7 @@ */ #include "effects/Tracker.h" +#include "Timeline.h" using namespace openshot; @@ -37,8 +38,11 @@ Tracker::Tracker(std::string clipTrackerDataPath) { // Init effect properties init_effect_details(); - // Tries to load the tracked object's data from protobuf file - trackedData.LoadBoxData(clipTrackerDataPath); + // Instantiate a keyframebbox object and point to it + KeyFrameBBox trackedDataObject; + trackedData = std::make_shared(trackedDataObject); + // Tries to load the tracked object's data from protobuf file + trackedData->LoadBoxData(clipTrackerDataPath); } // Default constructor @@ -46,6 +50,9 @@ Tracker::Tracker() { // Init effect properties init_effect_details(); + // Instantiate a keyframebbox object and point to it + KeyFrameBBox trackedDataObject; + trackedData = std::make_shared(trackedDataObject); } @@ -76,14 +83,14 @@ std::shared_ptr Tracker::GetFrame(std::shared_ptr frame, int64_t f if(!frame_image.empty()) { // Check if track data exists for the requested frame - if (trackedData.Contains(frame_number)) + if (trackedData->Contains(frame_number)) { // Get the width and height of the image float fw = frame_image.size().width; float fh = frame_image.size().height; // Get the bounding-box of given frame - BBox fd = this->trackedData.GetValue(frame_number); + BBox fd = trackedData->GetBox(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) ), @@ -119,11 +126,23 @@ Json::Value Tracker::JsonValue() const { // Create root json object Json::Value root = EffectBase::JsonValue(); // get parent properties + + // Save the effect's properties on root root["type"] = info.class_name; root["protobuf_data_path"] = protobuf_data_path; root["BaseFPS"]["num"] = BaseFPS.num; root["BaseFPS"]["den"] = BaseFPS.den; root["TimeScale"] = this->TimeScale; + + // Get trackedData JSON + Json::Value trackedDataJSON; + trackedDataJSON = trackedData->JsonValue(); + + // Save the trackedData properties on root + for (const auto& key : trackedDataJSON.getMemberNames()){ + root[key] = trackedDataJSON[key]; + } + // return JsonValue return root; } @@ -143,6 +162,7 @@ void Tracker::SetJson(const std::string value) { // Error parsing JSON (or missing keys) throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); } + return; } // Load Json::Value into this object @@ -150,7 +170,10 @@ void Tracker::SetJsonValue(const Json::Value root) { // Set parent data EffectBase::SetJsonValue(root); - + + if(!root["type"].isNull()) + info.class_name = root["type"].asString(); + if (!root["BaseFPS"].isNull() && root["BaseFPS"].isObject()) { if (!root["BaseFPS"]["num"].isNull()) @@ -166,19 +189,20 @@ void Tracker::SetJsonValue(const Json::Value root) { if (!root["TimeScale"].isNull()) TimeScale = (double) root["TimeScale"].asDouble(); - trackedData.SetBaseFPS(this->BaseFPS); - trackedData.ScalePoints(TimeScale); - // Set data from Json (if key is found) if (!root["protobuf_data_path"].isNull()) { protobuf_data_path = (root["protobuf_data_path"].asString()); - if(!trackedData.LoadBoxData(protobuf_data_path)) + if(!trackedData->LoadBoxData(protobuf_data_path)) { std::cout<<"Invalid protobuf data path"; protobuf_data_path = ""; } } + + trackedData->SetJsonValue(root); + + return; } @@ -186,9 +210,10 @@ void Tracker::SetJsonValue(const Json::Value root) { std::string Tracker::PropertiesJSON(int64_t requested_frame) const { // Generate JSON properties list - Json::Value root; + Json::Value root; + root = trackedData->PropertiesJSON(requested_frame); - // Effect's properties + // Append effect's properties root["name"] = add_property_json("Tracker", 0.0, "string", "", NULL, -1, -1, true, requested_frame); root["id"] = add_property_json("ID", 0.0, "string", Id(), NULL, -1, -1, true, requested_frame); root["position"] = add_property_json("Position", Position(), "float", "", NULL, 0, 1000 * 60 * 30, false, requested_frame); @@ -197,73 +222,6 @@ std::string Tracker::PropertiesJSON(int64_t requested_frame) const { root["end"] = add_property_json("End", End(), "float", "", NULL, 0, 1000 * 60 * 30, false, requested_frame); root["duration"] = add_property_json("Duration", Duration(), "float", "", NULL, 0, 1000 * 60 * 30, true, requested_frame); - // Get the bounding-box for the given-frame - BBox fd = trackedData.GetValue(requested_frame); - // Add the data of given frame bounding-box to the JSON object - root["x1"] = add_property_json("X1", fd.cx-(fd.width/2), "float", "", NULL, 0.0, 1.0, false, requested_frame); - root["y1"] = add_property_json("Y1", fd.cy-(fd.height/2), "float", "", NULL, 0.0, 1.0, false, requested_frame); - root["x2"] = add_property_json("X2", fd.cx+(fd.width/2), "float", "", NULL, 0.0, 1.0, false, requested_frame); - root["y2"] = add_property_json("Y2", fd.cy+(fd.height/2), "float", "", NULL, 0.0, 1.0, false, requested_frame); - - // Add the bounding-box Keyframes to the JSON object - root["delta_x"] = add_property_json("Displacement X-axis", trackedData.delta_x.GetValue(requested_frame), "float", "", &trackedData.delta_x, -1.0, 1.0, false, requested_frame); - root["delta_y"] = add_property_json("Displacement Y-axis", trackedData.delta_y.GetValue(requested_frame), "float", "", &trackedData.delta_y, -1.0, 1.0, false, requested_frame); - root["scale_x"] = add_property_json("Scale (Width)", trackedData.scale_x.GetValue(requested_frame), "float", "", &trackedData.scale_x, -1.0, 1.0, false, requested_frame); - root["scale_y"] = add_property_json("Scale (Height)", trackedData.scale_y.GetValue(requested_frame), "float", "", &trackedData.scale_y, -1.0, 1.0, false, requested_frame); - root["rotation"] = add_property_json("Rotation", trackedData.rotation.GetValue(requested_frame), "float", "", &trackedData.rotation, 0, 360, false, requested_frame); - // Return formatted string return root.toStyledString(); } - -// Generate JSON string of the trackedData object passing the frame number -std::string Tracker::Json(int64_t requested_frame) const { - - // Generate JSON properties list - Json::Value root; - - // Add the KeyframeBBox class properties to the JSON object - root["type"] = info.class_name; - root["protobuf_data_path"] = protobuf_data_path; - root["BaseFPS"]["num"] = BaseFPS.num; - root["BaseFPS"]["den"] = BaseFPS.den; - root["TimeScale"] = this->TimeScale; - - // Add the bounding-box Keyframes to the JSON object - root["delta_x"] = trackedData.delta_x.JsonValue(); - root["delta_y"] = trackedData.delta_y.JsonValue(); - root["scale_x"] = trackedData.scale_x.JsonValue(); - root["scale_y"] = trackedData.scale_y.JsonValue(); - root["rotation"] = trackedData.rotation.JsonValue(); - - return root.toStyledString(); -} - -// Set the tracketData object properties by a JSON string -void Tracker::SetJson(int64_t requested_frame, const std::string value) -{ - // Parse JSON string into JSON objects - try - { - const Json::Value root = openshot::stringToJson(value); - - // Set all values that match - if (!root["delta_x"].isNull()) - trackedData.delta_x.SetJsonValue(root["delta_x"]); - if (!root["delta_y"].isNull()) - trackedData.delta_y.SetJsonValue(root["delta_y"]); - if (!root["scale_x"].isNull()) - trackedData.scale_x.SetJsonValue(root["scale_x"]); - if (!root["scale_y"].isNull()) - trackedData.scale_y.SetJsonValue(root["scale_y"]); - if (!root["rotation"].isNull()) - trackedData.rotation.SetJsonValue(root["rotation"]); - } - - catch (const std::exception& e) - { - // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); - } - return; -} diff --git a/src/effects/Tracker.h b/src/effects/Tracker.h index 57a8b8b10..0f3cb018d 100644 --- a/src/effects/Tracker.h +++ b/src/effects/Tracker.h @@ -67,7 +67,7 @@ namespace openshot public: std::string protobuf_data_path; ///< Path to the protobuf file that holds the bounding-box data - KeyFrameBBox trackedData; ///< Object that holds the bounding-box data and it's Keyframes + std::shared_ptr trackedData; ///< Pointer to an object that holds the bounding-box data and it's Keyframes /// Blank constructor, useful when using Json to load the effect properties Tracker(std::string clipTrackerDataPath); @@ -96,9 +96,6 @@ namespace openshot /// Get all properties for a specific frame (perfect for a UI to display the current state /// of all properties at any time) std::string PropertiesJSON(int64_t requested_frame) const override; - - std::string Json(int64_t requested_frame) const override; ///< Generate JSON string of the trackedData object passing the frame number - void SetJson(int64_t requested_frame, const std::string value) override; ///< Set the tracketData object properties by a JSON string }; } diff --git a/tests/KeyFrame_Tests.cpp b/tests/KeyFrame_Tests.cpp index 05cd5109f..6ca98e920 100644 --- a/tests/KeyFrame_Tests.cpp +++ b/tests/KeyFrame_Tests.cpp @@ -522,7 +522,7 @@ TEST(KeyFrameBBox_GetVal_test) { kfb.AddBox(1, 10.0, 10.0, 100.0, 100.0, 0.0); - BBox val = kfb.GetValue(1); + BBox val = kfb.GetBox(1); CHECK_EQUAL(10.0, val.cx); CHECK_EQUAL(10.0, val.cy); @@ -540,21 +540,21 @@ TEST(KeyFrameBBox_GetVal_Interpolation) { kfb.AddBox(21, 30.0, 30.0, 100.0, 100.0, 0.0); kfb.AddBox(31, 40.0, 40.0, 100.0, 100.0, 0.0); - BBox val = kfb.GetValue(5); + BBox val = kfb.GetBox(5); CHECK_EQUAL(14.0, val.cx); CHECK_EQUAL(14.0, val.cy); CHECK_EQUAL(100.0,val.width); CHECK_EQUAL(100.0,val.height); - val = kfb.GetValue(15); + val = kfb.GetBox(15); CHECK_EQUAL(24.0, val.cx); CHECK_EQUAL(24.0, val.cy); CHECK_EQUAL(100.0,val.width); CHECK_EQUAL(100.0, val.height); - val = kfb.GetValue(25); + val = kfb.GetBox(25); CHECK_EQUAL(34.0, val.cx); CHECK_EQUAL(34.0, val.cy); @@ -581,8 +581,6 @@ TEST(KeyFrameBBox_Json_set) { KeyFrameBBox fromJSON_kfb; fromJSON_kfb.SetJson(dataJSON); - std::cout << fromJSON_kfb.Json() << std::endl; - CHECK_EQUAL(kfb.GetBaseFPS().num, fromJSON_kfb.GetBaseFPS().num); double time_kfb = kfb.FrameNToTime(1, 1.0); @@ -606,8 +604,78 @@ TEST(KeyFrameBBox_Scale_test){ kfb.scale_x.AddPoint(1.0, 2.0); kfb.scale_y.AddPoint(1.0, 3.0); - BBox bbox = kfb.GetValue(1); + BBox bbox = kfb.GetBox(1); CHECK_EQUAL(20.0, bbox.width); CHECK_EQUAL(30.0, bbox.height); +} + + + +TEST(Attach_test){ + + // Create Timelime + Timeline t(1280, 720, Fraction(25,1), 44100, 2, ChannelLayout::LAYOUT_STEREO); + + // Create Clip and add it to the Timeline + Clip clip(new ImageReader("../../examples/front.png")); + clip.Id("AAAA1234"); + + // Create a child clip and add it to the Timeline + Clip childClip(new ImageReader("../../examples/mask2.png")); + childClip.Id("CHILD123"); + + // Add clips to timeline + t.AddClip(&childClip); + t.AddClip(&clip); + + // Create tracker and add it to clip + Tracker tracker; + clip.AddEffect(&tracker); + + // Save a pointer to trackedData + std::shared_ptr trackedData = tracker.trackedData; + + // Change trackedData scale + trackedData->scale_x.AddPoint(1, 2.0); + CHECK_EQUAL(2.0, trackedData->scale_x.GetValue(1)); + + // Tracked Data JSON + auto trackedDataJson = trackedData->JsonValue(); + + // Get and cast the trakcedObject + auto trackedObject_base = t.GetTrackedObject("TESTBASEID"); + std::shared_ptr trackedObject = std::static_pointer_cast(trackedObject_base); + CHECK_EQUAL(trackedData, trackedObject); + + // Set trackedObject Json Value + trackedObject->SetJsonValue(trackedDataJson); + + // Attach childClip to tracked object + std::string tracked_id = trackedData->Id(); + childClip.Open(); + childClip.AttachToTracker(tracked_id); + + std::shared_ptr trackedTest = std::static_pointer_cast(childClip.GetAttachedObject()); + + CHECK_EQUAL(trackedData->scale_x.GetValue(1), trackedTest->scale_x.GetValue(1)); + + auto frameTest = childClip.GetFrame(1); + childClip.Close(); +} + +TEST(GetBoxValues_test){ + + KeyFrameBBox trackedDataObject; + trackedDataObject.AddBox(1, 10.0, 10.0, 20.0, 20.0, 30.0); + + std::shared_ptr trackedData = std::make_shared(trackedDataObject); + + auto boxValues = trackedData->GetBoxValues(1); + + CHECK_EQUAL(10.0, boxValues["cx"]); + CHECK_EQUAL(10.0, boxValues["cy"]); + CHECK_EQUAL(20.0, boxValues["w"]); + CHECK_EQUAL(20.0, boxValues["h"]); + CHECK_EQUAL(30.0, boxValues["ang"]); } \ No newline at end of file From 3d5d907c5ddf70d539a011d06859731978b77c0b Mon Sep 17 00:00:00 2001 From: Brenno Date: Thu, 14 Jan 2021 15:45:28 -0300 Subject: [PATCH 14/84] Updated Clip.cpp to support GUI to select attached object Modified Clip.cpp PropertiesJSON function and applied minor fixes to Keyframe_Tests --- src/Clip.cpp | 21 ++++----------------- tests/KeyFrame_Tests.cpp | 4 +--- 2 files changed, 5 insertions(+), 20 deletions(-) diff --git a/src/Clip.cpp b/src/Clip.cpp index 501184295..e86e120d6 100644 --- a/src/Clip.cpp +++ b/src/Clip.cpp @@ -787,23 +787,10 @@ std::string Clip::PropertiesJSON(int64_t requested_frame) const { root["display"] = add_property_json("Frame Number", display, "int", "", NULL, 0, 3, false, requested_frame); root["mixing"] = add_property_json("Volume Mixing", mixing, "int", "", NULL, 0, 2, false, requested_frame); root["waveform"] = add_property_json("Waveform", waveform, "int", "", NULL, 0, 1, false, requested_frame); - root["attached_id"] = add_property_json("Attached ID", 0.0, "string", GetAttachedId(), NULL, -1, -1, false, requested_frame); - - // Add attached id choices (dropdown style) - if (timeline){ - Timeline* parentTimeline = (Timeline *) timeline; - std::vector tracked_ids = parentTimeline->GetTrackedObjectsIds(); - Json::Value temp; - temp["name"] = ""; - temp["value"] = ""; - temp["selected"] = true; - root["attached_id"]["choices"].append(temp); - for (auto it = tracked_ids.begin(); it != tracked_ids.end(); ++it){ - temp["name"] = *it; - temp["value"] = *it; - temp["selected"] = true; - root["attached_id"]["choices"].append(temp); - } + if (!attached_id.empty()) { + root["attached_id"] = add_property_json("Attached ID", 0.0, "string", attached_id, NULL, -1, -1, false, requested_frame); + } else { + root["attached_id"] = add_property_json("Attached ID", 0.0, "string", "None", NULL, -1, -1, false, requested_frame); } // Add gravity choices (dropdown style) root["gravity"]["choices"].append(add_property_choice_json("Top Left", GRAVITY_TOP_LEFT, gravity)); diff --git a/tests/KeyFrame_Tests.cpp b/tests/KeyFrame_Tests.cpp index 3a331baf4..9e67f9eec 100644 --- a/tests/KeyFrame_Tests.cpp +++ b/tests/KeyFrame_Tests.cpp @@ -620,8 +620,6 @@ TEST(KeyFrameBBox_Scale_test){ CHECK_EQUAL(30.0, bbox.height); } - - TEST(Attach_test){ std::stringstream path1, path2; @@ -648,7 +646,7 @@ TEST(Attach_test){ clip.AddEffect(&tracker); // Save a pointer to trackedData - std::shared_ptr trackedData = tracker.trackedData; + std::shared_ptr trackedData = tracker.trackedData; // Change trackedData scale trackedData->scale_x.AddPoint(1, 2.0); From 7cce93eb55862add1b297469d568fdcd1ce136c1 Mon Sep 17 00:00:00 2001 From: Brenno Date: Thu, 14 Jan 2021 15:52:49 -0300 Subject: [PATCH 15/84] Removed IKeyFrame.h and applied minor fixes to Clip.cpp --- src/Clip.cpp | 6 ++-- src/IKeyFrame.h | 90 ---------------------------------------------- src/KeyFrameBBox.h | 1 - 3 files changed, 3 insertions(+), 94 deletions(-) delete mode 100644 src/IKeyFrame.h diff --git a/src/Clip.cpp b/src/Clip.cpp index e86e120d6..c260bb8f9 100644 --- a/src/Clip.cpp +++ b/src/Clip.cpp @@ -945,8 +945,10 @@ void Clip::SetJsonValue(const Json::Value root) { // Set data from Json (if key is found) if (!root["attached_id"].isNull()) attached_id = root["attached_id"].asString(); - if (attached_id.size() > 0){ + if (attached_id.size() > 0 && attached_id != "None"){ AttachToTracker(attached_id); + } else{ + attachedObject = nullptr; } if (!root["gravity"].isNull()) gravity = (GravityType) root["gravity"].asInt(); @@ -1265,7 +1267,6 @@ void Clip::apply_keyframes(std::shared_ptr frame, int width, int height) /* TRANSFORM CLIP TO ATTACHED OBJECT'S POSITION AND DIMENSION */ if (attachedObject){ - // Access the KeyframeBBox properties std::map boxValues = attachedObject->GetBoxValues(frame->number); @@ -1275,7 +1276,6 @@ void Clip::apply_keyframes(std::shared_ptr frame, int width, int height) scale_x.AddPoint(frame->number, boxValues["w"]*boxValues["sx"]*2.0); scale_y.AddPoint(frame->number, boxValues["h"]*boxValues["sy"]); rotation.AddPoint(frame->number, boxValues["r"]); - } /* GRAVITY LOCATION - Initialize X & Y to the correct values (before applying location curves) */ diff --git a/src/IKeyFrame.h b/src/IKeyFrame.h deleted file mode 100644 index 3aef26cd1..000000000 --- a/src/IKeyFrame.h +++ /dev/null @@ -1,90 +0,0 @@ -/** - * @file - * @brief Header file for the IKeyframe class - * @author Jonathan Thomas - * - * @ref License - */ - -/* LICENSE - * - * Copyright (c) 2008-2019 OpenShot Studios, LLC - * . This file is part of - * OpenShot Library (libopenshot), an open-source project dedicated to - * delivering high quality video editing and animation solutions to the - * world. For more information visit . - * - * OpenShot Library (libopenshot) is free software: you can redistribute it - * and/or modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * OpenShot Library (libopenshot) is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with OpenShot Library. If not, see . - */ - -#ifndef OPENSHOT_IKEYFRAME_H -#define OPENSHOT_IKEYFRAME_H - -#include -#include -#include -#include -#include -#include "Exceptions.h" -#include "Fraction.h" -#include "Coordinate.h" -#include "Point.h" -#include "Json.h" - - -namespace openshot { - /** - * @brief A Keyframe is a collection of Point instances, which is used to vary a number or property over time. - * - * Keyframes are used to animate and interpolate values of properties over time. For example, a single property - * can use a Keyframe instead of a constant value. Assume you want to slide an image (from left to right) over - * a video. You can create a Keyframe which will adjust the X value of the image over 100 frames (or however many - * frames the animation needs to last) from the value of 0 to 640. - * - * \endcode - */ - - class IKeyFrame { - public: - virtual void AddPoint(Point p) = 0; - virtual void AddPoint(double x, double y) = 0; - virtual bool Contains(Point p) const = 0; - virtual std::vector GetValue(int64_t frame_number) = 0; - virtual double GetDelta(int64_t index) const = 0; - virtual int64_t GetLength() const = 0; - virtual int64_t GetCount() const = 0; - - /// Get and Set JSON methods - virtual std::string Json() const = 0; ///< Generate JSON string of this object - virtual Json::Value JsonValue() const = 0; ///< Generate Json::Value for this object - virtual void SetJson(const std::string value) = 0; ///< Load JSON string into this object - virtual void SetJsonValue(const Json::Value root) = 0; ///< Load Json::Value into this object - - /// Remove a single point by matching a value - virtual void RemovePoint(Point p) = 0; - - /// Remove a points by frame_number - virtual void RemovePoint(int64_t frame_number) = 0; - - /// Replace an existing point with a new point - virtual void UpdatePoint(int64_t index, Point p) = 0; - - /// Print collection of points - virtual void PrintPoints() const = 0; - - }; - -} - -#endif \ No newline at end of file diff --git a/src/KeyFrameBBox.h b/src/KeyFrameBBox.h index 5eff5cec9..b3f446060 100644 --- a/src/KeyFrameBBox.h +++ b/src/KeyFrameBBox.h @@ -41,7 +41,6 @@ #include "Coordinate.h" #include "Point.h" #include "Json.h" -#include "IKeyFrame.h" #include "KeyFrame.h" #include "KeyFrameBase.h" #include "protobuf_messages/trackerdata.pb.h" From b2cd0a500aace5e89d7cc653eec4c5a9f7d50ca8 Mon Sep 17 00:00:00 2001 From: Brenno Date: Thu, 14 Jan 2021 16:03:22 -0300 Subject: [PATCH 16/84] Update Clip.cpp apply_keyframes funcion The Clip's Keyframes are no longer modified when it's attached to an object, and the bounding-box properties are requested by the Timeline's frame, not the Clip's frame. --- src/Clip.cpp | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/src/Clip.cpp b/src/Clip.cpp index c260bb8f9..a5e3702d0 100644 --- a/src/Clip.cpp +++ b/src/Clip.cpp @@ -1264,18 +1264,30 @@ void Clip::apply_keyframes(std::shared_ptr frame, int width, int height) break; } } + + // Initialize bounding-box values + float box_cx = 0.0; + float box_cy = 0.0; + float box_sx = 0.0; + float box_sy = 0.0; + float box_r = 0.0; /* TRANSFORM CLIP TO ATTACHED OBJECT'S POSITION AND DIMENSION */ if (attachedObject){ + // Convert Clip's frame position to Timeline's frame position + long clip_start_position = round(Position() * info.fps.ToDouble()) + 1; + long clip_start_frame = (Start() * info.fps.ToDouble()) + 1; + double timeline_frame_number = frame->number + clip_start_position - clip_start_frame; + // Access the KeyframeBBox properties - std::map boxValues = attachedObject->GetBoxValues(frame->number); - - // Set the bounding box keyframes to this clip keyframes - location_x.AddPoint(frame->number, (boxValues["cx"]-0.5)); - location_y.AddPoint(frame->number, (boxValues["cy"]-0.5)); - scale_x.AddPoint(frame->number, boxValues["w"]*boxValues["sx"]*2.0); - scale_y.AddPoint(frame->number, boxValues["h"]*boxValues["sy"]); - rotation.AddPoint(frame->number, boxValues["r"]); + std::map boxValues = attachedObject->GetBoxValues(timeline_frame_number); + + // Get the bounding-box values and correct them by the clip's reference system + box_cx = boxValues["cx"] - 0.5; + box_cy = boxValues["cy"] - 0.5; + box_sx = boxValues["w"]*boxValues["sx"]*2.0; + box_sy = boxValues["h"]*boxValues["sy"]; + box_r = boxValues["r"]; } /* GRAVITY LOCATION - Initialize X & Y to the correct values (before applying location curves) */ @@ -1285,9 +1297,14 @@ void Clip::apply_keyframes(std::shared_ptr frame, int width, int height) // Adjust size for scale x and scale y float sx = scale_x.GetValue(frame->number); // percentage X scale float sy = scale_y.GetValue(frame->number); // percentage Y scale + // Change clip's scale to bounding-box scale + if(box_sx > 0.0 && box_sy > 0.0){ + sx = box_sx; + sy = box_sy; + } float scaled_source_width = source_size.width() * sx; float scaled_source_height = source_size.height() * sy; - + switch (gravity) { case (GRAVITY_TOP_LEFT): @@ -1329,9 +1346,9 @@ void Clip::apply_keyframes(std::shared_ptr frame, int width, int height) QTransform transform; /* LOCATION, ROTATION, AND SCALE */ - float r = rotation.GetValue(frame->number); // rotate in degrees - x += (width * location_x.GetValue(frame->number)); // move in percentage of final width - y += (height * location_y.GetValue(frame->number)); // move in percentage of final height + float r = rotation.GetValue(frame->number) + box_r; // rotate in degrees + x += (width * (location_x.GetValue(frame->number) + box_cx)); // move in percentage of final width + y += (height * (location_y.GetValue(frame->number) + box_cy)); // move in percentage of final height float shear_x_value = shear_x.GetValue(frame->number); float shear_y_value = shear_y.GetValue(frame->number); float origin_x_value = origin_x.GetValue(frame->number); From a5feadce1e13eddfe23aa1238bdbb1ab4eb2f081 Mon Sep 17 00:00:00 2001 From: Brenno Date: Mon, 18 Jan 2021 14:52:01 -0300 Subject: [PATCH 17/84] Changed KeyframeBBox to TrackedObjectBBox and added TrackedObjectBase Added new base class TrackedObjectBase, changed class KeyframeBBox to TrackedObjectBBox and changes it's inheritance from KeyframeBase to TrackedObjectBase. --- src/CMakeLists.txt | 3 +- src/Clip.cpp | 17 ++-- src/Clip.h | 8 +- src/KeyFrameBase.cpp | 6 +- src/KeyFrameBase.h | 14 +-- src/OpenShot.h | 2 +- src/Timeline.cpp | 19 ++-- src/Timeline.h | 16 +-- src/TimelineBase.cpp | 1 - ...KeyFrameBBox.cpp => TrackedObjectBBox.cpp} | 76 ++++++++++----- src/{KeyFrameBBox.h => TrackedObjectBBox.h} | 18 ++-- src/TrackedObjectBase.cpp | 46 +++++++++ src/TrackedObjectBase.h | 97 +++++++++++++++++++ src/effects/Tracker.cpp | 16 +-- src/effects/Tracker.h | 4 +- tests/KeyFrame_Tests.cpp | 40 ++++---- 16 files changed, 278 insertions(+), 105 deletions(-) rename src/{KeyFrameBBox.cpp => TrackedObjectBBox.cpp} (82%) rename src/{KeyFrameBBox.h => TrackedObjectBBox.h} (94%) create mode 100644 src/TrackedObjectBase.cpp create mode 100644 src/TrackedObjectBase.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0fc367520..adb7351a5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -87,7 +87,8 @@ set(OPENSHOT_SOURCES Json.cpp KeyFrame.cpp KeyFrameBase.cpp - KeyFrameBBox.cpp + TrackedObjectBase.cpp + TrackedObjectBBox.cpp OpenShotVersion.cpp ZmqLogger.cpp PlayerBase.cpp diff --git a/src/Clip.cpp b/src/Clip.cpp index a5e3702d0..341e111c8 100644 --- a/src/Clip.cpp +++ b/src/Clip.cpp @@ -251,7 +251,7 @@ void Clip::AttachToTracker(std::string tracked_id) Timeline *parentTimeline = (Timeline *) ParentTimeline(); // Create a smart pointer to the tracked object from the timeline - std::shared_ptr trackedObject = parentTimeline->GetTrackedObject(tracked_id); + std::shared_ptr trackedObject = parentTimeline->GetTrackedObject(tracked_id); // Check for valid tracked object if (trackedObject){ @@ -264,7 +264,7 @@ void Clip::AttachToTracker(std::string tracked_id) } // Set the pointer to the trackedObject this clip is attached to -void Clip::SetAttachedObject(std::shared_ptr trackedObject){ +void Clip::SetAttachedObject(std::shared_ptr trackedObject){ attachedObject = trackedObject; return; } @@ -1142,7 +1142,7 @@ void Clip::AddEffect(EffectBase* effect) Tracker* tracker = (Tracker *) effect; // Get tracked data from the Tracker effect - std::shared_ptr trackedData = tracker->trackedData; + std::shared_ptr trackedData = tracker->trackedData; // Add tracked data to the timeline parentTimeline->AddTrackedObject(trackedData); @@ -1279,13 +1279,18 @@ void Clip::apply_keyframes(std::shared_ptr frame, int width, int height) long clip_start_frame = (Start() * info.fps.ToDouble()) + 1; double timeline_frame_number = frame->number + clip_start_position - clip_start_frame; - // Access the KeyframeBBox properties - std::map boxValues = attachedObject->GetBoxValues(timeline_frame_number); + // Get attachedObject's parent clip frame number + Timeline* parentTimeline = (Timeline *) ParentTimeline(); + double attachedObjectParentClip_frame_number = timeline_frame_number - clip_start_position + clip_start_frame; + + // Access the TrackedObjectBBox properties + std::map boxValues = attachedObject->GetBoxValues(attachedObjectParentClip_frame_number); // Get the bounding-box values and correct them by the clip's reference system box_cx = boxValues["cx"] - 0.5; box_cy = boxValues["cy"] - 0.5; - box_sx = boxValues["w"]*boxValues["sx"]*2.0; + // box_sx = boxValues["w"]*boxValues["sx"]*2.0; + box_sx = boxValues["w"]*boxValues["sx"]; box_sy = boxValues["h"]*boxValues["sy"]; box_r = boxValues["r"]; } diff --git a/src/Clip.h b/src/Clip.h index 0886f7894..8b31405af 100644 --- a/src/Clip.h +++ b/src/Clip.h @@ -54,7 +54,7 @@ #include "Fraction.h" #include "Frame.h" #include "KeyFrame.h" -#include "KeyFrameBase.h" +#include "TrackedObjectBase.h" #include "ReaderBase.h" #include "JuceHeader.h" @@ -125,7 +125,7 @@ namespace openshot { std::list effects; /// Is Reader opened std::string attached_id; ///< Id of the bounding box that this clip is attached to - std::shared_ptr attachedObject; + std::shared_ptr attachedObject; // Audio resampler (if time mapping) openshot::AudioResampler *resampler; @@ -206,9 +206,9 @@ namespace openshot { void AttachToTracker(std::string tracked_id); /// Set the pointer to the trackedObject this clip is attached to - void SetAttachedObject(std::shared_ptr trackedObject); + void SetAttachedObject(std::shared_ptr trackedObject); /// Return a pointer to the trackedObject this clip is attached to - std::shared_ptr GetAttachedObject() const { return attachedObject; }; + std::shared_ptr GetAttachedObject() const { return attachedObject; }; /// Return the type name of the class std::string Name() override { return "Clip"; }; diff --git a/src/KeyFrameBase.cpp b/src/KeyFrameBase.cpp index acdf389fc..79f4f5281 100644 --- a/src/KeyFrameBase.cpp +++ b/src/KeyFrameBase.cpp @@ -98,10 +98,6 @@ namespace openshot{ } KeyframeBase::KeyframeBase(){ - id = "TESTBASEID"; + } - - KeyframeBase::KeyframeBase(std::string _id){ - SetId(_id); - } } \ No newline at end of file diff --git a/src/KeyFrameBase.h b/src/KeyFrameBase.h index 316ed83a4..6a55ea5ef 100644 --- a/src/KeyFrameBase.h +++ b/src/KeyFrameBase.h @@ -43,6 +43,7 @@ #include "Point.h" #include "Json.h" + namespace openshot { /** * @brief This abstract class is the base class of all Keyframes. @@ -71,27 +72,16 @@ namespace openshot { // int64_t SearchBetweenPoints(Point const & left, Point const & right, int64_t const current, Check check); class KeyframeBase{ - private: - std::string id; public: - + /// Blank constructor KeyframeBase(); - /// Default constructor - KeyframeBase(std::string _id); - - std::string Id() const { return id; } - void SetId(std::string _id) { id = _id; } - /// Scale all points by a percentage (good for evenly lengthening or shortening an openshot::Keyframe) /// 1.0 = same size, 1.05 = 5% increase, etc... virtual void ScalePoints(double scale) { return; }; - /// Return the main properties of a KeyframeBBox instance using a pointer to this base class - virtual std::map GetBoxValues(int64_t frame_number) { std::map ret; return ret; }; - }; } // Namespace openshot diff --git a/src/OpenShot.h b/src/OpenShot.h index 1cb8700a9..561c1bed9 100644 --- a/src/OpenShot.h +++ b/src/OpenShot.h @@ -132,7 +132,7 @@ #include "TextReader.h" #endif #include "KeyFrame.h" -#include "KeyFrameBBox.h" +#include "TrackedObjectBBox.h" #include "PlayerBase.h" #include "Point.h" #include "Profiles.h" diff --git a/src/Timeline.cpp b/src/Timeline.cpp index 3956dab2d..4c4be0c06 100644 --- a/src/Timeline.cpp +++ b/src/Timeline.cpp @@ -240,8 +240,8 @@ Timeline::~Timeline() { } } -// Add to the tracked_objects map a pointer to a tracked object (KeyframeBBox) -void Timeline::AddTrackedObject(std::shared_ptr trackedObject){ +// Add to the tracked_objects map a pointer to a tracked object (TrackedObjectBBox) +void Timeline::AddTrackedObject(std::shared_ptr trackedObject){ // Search for the tracked object on the map auto iterator = tracked_objects.find(trackedObject->Id()); @@ -254,18 +254,19 @@ void Timeline::AddTrackedObject(std::shared_ptr trackedO // Tracked object's id not present -> insert it on the map tracked_objects[trackedObject->Id()] = trackedObject; } + return; } // Return tracked object pointer by it's id -std::shared_ptr Timeline::GetTrackedObject(std::string id) const{ +std::shared_ptr Timeline::GetTrackedObject(std::string id) const{ // Search for the tracked object on the map auto iterator = tracked_objects.find(id); if (iterator != tracked_objects.end()){ // Id found, return the pointer to the tracked object - std::shared_ptr trackedObject = iterator->second; + std::shared_ptr trackedObject = iterator->second; return trackedObject; } else { @@ -274,15 +275,15 @@ std::shared_ptr Timeline::GetTrackedObject(std::string i } } -// Return the ID's of the tracked objects as a vector of strings -std::vector Timeline::GetTrackedObjectsIds() const{ +// Return the ID's of the tracked objects as a list of strings +std::list Timeline::GetTrackedObjectsIds() const{ - // Create a vector of strings - std::vector trackedObjects_ids; + // Create a list of strings + std::list trackedObjects_ids; // Iterate through the tracked_objects map for (auto const& it: tracked_objects){ - // Add the IDs to the vector + // Add the IDs to the list trackedObjects_ids.push_back(it.first); } diff --git a/src/Timeline.h b/src/Timeline.h index d5d1bda9b..69cebc8ab 100644 --- a/src/Timeline.h +++ b/src/Timeline.h @@ -52,8 +52,8 @@ #include "Frame.h" #include "FrameMapper.h" #include "KeyFrame.h" -#include "KeyFrameBBox.h" -#include "KeyFrameBase.h" +#include "TrackedObjectBBox.h" +#include "TrackedObjectBase.h" #include "OpenMPUtilities.h" #include "ReaderBase.h" #include "Settings.h" @@ -179,7 +179,7 @@ namespace openshot { bool managed_cache; ///< Does this timeline instance manage the cache object std::string path; ///< Optional path of loaded UTF-8 OpenShot JSON project file std::mutex get_frame_mutex; ///< Mutex to protect GetFrame method from different threads calling it - std::map> tracked_objects; ///< map of KeyframeBBoxes and their IDs + std::map> tracked_objects; ///< map of TrackedObjectBBoxes and their IDs /// Process a new layer of video or audio void add_layer(std::shared_ptr new_frame, openshot::Clip* source_clip, int64_t clip_frame_number, int64_t timeline_frame_number, bool is_top_clip, float max_volume); @@ -244,12 +244,12 @@ namespace openshot { virtual ~Timeline(); - /// Add to the tracked_objects map a pointer to a tracked object (KeyframeBBox) - void AddTrackedObject(std::shared_ptr trackedObject); + /// Add to the tracked_objects map a pointer to a tracked object (TrackedObjectBBox) + void AddTrackedObject(std::shared_ptr trackedObject); /// Return tracked object pointer by it's id - std::shared_ptr GetTrackedObject(std::string id) const; - /// Return the ID's of the tracked objects as a vector of strings - std::vector GetTrackedObjectsIds() const; + std::shared_ptr GetTrackedObject(std::string id) const; + /// Return the ID's of the tracked objects as a list of strings + std::list GetTrackedObjectsIds() const; /// @brief Add an openshot::Clip to the timeline /// @param clip Add an openshot::Clip to the timeline. A clip can contain any type of Reader. diff --git a/src/TimelineBase.cpp b/src/TimelineBase.cpp index 6170bff2b..120de01b1 100644 --- a/src/TimelineBase.cpp +++ b/src/TimelineBase.cpp @@ -45,6 +45,5 @@ TimelineBase::TimelineBase() * the TimelineBase class */ void TimelineBase::Clips(int test){ - std::cout << test << std::endl; return; } \ No newline at end of file diff --git a/src/KeyFrameBBox.cpp b/src/TrackedObjectBBox.cpp similarity index 82% rename from src/KeyFrameBBox.cpp rename to src/TrackedObjectBBox.cpp index 2a1155a85..119ec0839 100644 --- a/src/KeyFrameBBox.cpp +++ b/src/TrackedObjectBBox.cpp @@ -28,7 +28,8 @@ * along with OpenShot Library. If not, see . */ -#include "KeyFrameBBox.h" +#include "TrackedObjectBBox.h" +#include "Clip.h" #include #include #include @@ -39,14 +40,14 @@ using namespace openshot; // Default Constructor that sets the bounding-box displacement as 0 and the scales as 1 for the first frame -KeyFrameBBox::KeyFrameBBox() : 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) { this->TimeScale = 1.0; return; } // Add a BBox to the BoxVec map -void KeyFrameBBox::AddBox(int64_t _frame_num, float _cx, float _cy, float _width, float _height, float _angle) +void TrackedObjectBBox::AddBox(int64_t _frame_num, float _cx, float _cy, float _width, float _height, float _angle) { // Check if the given frame number is valid if (_frame_num < 0) @@ -73,7 +74,7 @@ void KeyFrameBBox::AddBox(int64_t _frame_num, float _cx, float _cy, float _width } // Get the size of BoxVec map -int64_t KeyFrameBBox::GetLength() const +int64_t TrackedObjectBBox::GetLength() const { if (BoxVec.empty()) return 0; @@ -83,7 +84,7 @@ int64_t KeyFrameBBox::GetLength() const } // Check if there is a bounding-box in the given frame -bool KeyFrameBBox::Contains(int64_t frame_num) +bool TrackedObjectBBox::Contains(int64_t frame_num) { // Get the time of given frame double time = this->FrameNToTime(frame_num, 1.0); @@ -96,7 +97,7 @@ bool KeyFrameBBox::Contains(int64_t frame_num) } // Remove a bounding-box from the BoxVec map -void KeyFrameBBox::RemoveBox(int64_t frame_number) +void TrackedObjectBBox::RemoveBox(int64_t frame_number) { // Get the time of given frame double time = this->FrameNToTime(frame_number, 1.0); @@ -111,7 +112,7 @@ void KeyFrameBBox::RemoveBox(int64_t frame_number) } // Return a bounding-box from BoxVec with it's properties adjusted by the Keyframes -BBox KeyFrameBBox::GetBox(int64_t frame_number) +BBox TrackedObjectBBox::GetBox(int64_t frame_number) { // Get the time position of the given frame. double time = this->FrameNToTime(frame_number, this->TimeScale); @@ -164,7 +165,7 @@ BBox KeyFrameBBox::GetBox(int64_t frame_number) } // Interpolate the bouding-boxes properties -BBox KeyFrameBBox::InterpolateBoxes(double t1, double t2, BBox left, BBox right, double target) +BBox TrackedObjectBBox::InterpolateBoxes(double t1, double t2, BBox left, BBox right, double target) { // Interpolate the x-coordinate of the center point Point cx_left(t1, left.cx, openshot::InterpolationType::LINEAR); @@ -198,30 +199,30 @@ BBox KeyFrameBBox::InterpolateBoxes(double t1, double t2, BBox left, BBox right, } // Update object's BaseFps -void KeyFrameBBox::SetBaseFPS(Fraction fps){ +void TrackedObjectBBox::SetBaseFPS(Fraction fps){ this->BaseFps = fps; return; } // Return the object's BaseFps -Fraction KeyFrameBBox::GetBaseFPS(){ +Fraction TrackedObjectBBox::GetBaseFPS(){ return BaseFps; } // Get the time of the given frame -double KeyFrameBBox::FrameNToTime(int64_t frame_number, double time_scale){ +double TrackedObjectBBox::FrameNToTime(int64_t frame_number, double time_scale){ double time = ((double)frame_number) * this->BaseFps.Reciprocal().ToDouble() * (1.0 / time_scale); return time; } // Update the TimeScale member variable -void KeyFrameBBox::ScalePoints(double time_scale){ +void TrackedObjectBBox::ScalePoints(double time_scale){ this->TimeScale = time_scale; } // Load the bounding-boxes information from the protobuf file -bool KeyFrameBBox::LoadBoxData(std::string inputFilePath) +bool TrackedObjectBBox::LoadBoxData(std::string inputFilePath) { // Variable to hold the loaded data pb_tracker::Tracker bboxMessage; @@ -277,20 +278,20 @@ bool KeyFrameBBox::LoadBoxData(std::string inputFilePath) } // Clear the BoxVec map -void KeyFrameBBox::clear() +void TrackedObjectBBox::clear() { BoxVec.clear(); } // Generate JSON string of this object -std::string KeyFrameBBox::Json() const +std::string TrackedObjectBBox::Json() const { // Return formatted string return JsonValue().toStyledString(); } // Generate Json::Value for this object -Json::Value KeyFrameBBox::JsonValue() const +Json::Value TrackedObjectBBox::JsonValue() const { // Create root json object Json::Value root; @@ -313,7 +314,7 @@ Json::Value KeyFrameBBox::JsonValue() const } // Load JSON string into this object -void KeyFrameBBox::SetJson(const std::string value) +void TrackedObjectBBox::SetJson(const std::string value) { // Parse JSON string into JSON objects try @@ -331,12 +332,12 @@ void KeyFrameBBox::SetJson(const std::string value) } // Load Json::Value into this object -void KeyFrameBBox::SetJsonValue(const Json::Value root) +void TrackedObjectBBox::SetJsonValue(const Json::Value root) { // Set the Id if (!root["box_id"].isNull()) - SetId(root["box_id"].asString()); + Id(root["box_id"].asString()); // Set the BaseFps by the given JSON object if (!root["BaseFPS"].isNull() && root["BaseFPS"].isObject()) @@ -374,7 +375,7 @@ void KeyFrameBBox::SetJsonValue(const Json::Value root) // Get all properties for a specific frame (perfect for a UI to display the current state // of all properties at any time) -Json::Value KeyFrameBBox::PropertiesJSON(int64_t requested_frame) const +Json::Value TrackedObjectBBox::PropertiesJSON(int64_t requested_frame) const { Json::Value root; @@ -402,7 +403,7 @@ Json::Value KeyFrameBBox::PropertiesJSON(int64_t requested_frame) const // Generate JSON for a property -Json::Value KeyFrameBBox::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 { +Json::Value TrackedObjectBBox::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 { // Requested Point const Point requested_point(requested_frame, requested_frame); @@ -439,7 +440,7 @@ Json::Value KeyFrameBBox::add_property_json(std::string name, float value, std:: } // Return the bounding box properties and it's keyframes indexed by their names -std::map KeyFrameBBox::GetBoxValues(int64_t frame_number){ +std::map TrackedObjectBBox::GetBoxValues(int64_t frame_number){ // Create the map std::map boxValues; @@ -463,4 +464,35 @@ std::map KeyFrameBBox::GetBoxValues(int64_t frame_number){ return boxValues; +} + +// Return properties of this object's parent clip +std::map TrackedObjectBBox::GetParentClipProperties(int64_t frame_number){ + + // Get the parent clip of this object as a Clip pointer + Clip* parentClip = (Clip *) ParentClip(); + + // Calculate parentClip's frame number + long parentClip_start_position = round( parentClip->Position() * parentClip->info.fps.ToDouble() ) + 1; + long parentClip_start_frame = ( parentClip->Start() * parentClip->info.fps.ToDouble() ) + 1; + float parentClip_frame_number = frame_number - parentClip_start_position + parentClip_start_frame; + + // Get parentClip's Keyframes + float parentClip_location_x = parentClip->location_x.GetValue(parentClip_frame_number); + float parentClip_location_y = parentClip->location_y.GetValue(parentClip_frame_number); + float parentClip_scale_x = parentClip->scale_x.GetValue(parentClip_frame_number); + float parentClip_scale_y = parentClip->scale_y.GetValue(parentClip_frame_number); + float parentClip_rotation = parentClip->rotation.GetValue(parentClip_frame_number); + + std::map parentClipProperties; + + parentClipProperties["frame_number"] = parentClip_frame_number; + parentClipProperties["timeline_frame_number"] = frame_number; + parentClipProperties["location_x"] = parentClip_location_x; + parentClipProperties["location_y"] = parentClip_location_y; + parentClipProperties["scale_x"] = parentClip_scale_x; + parentClipProperties["scale_y"] = parentClip_scale_y; + parentClipProperties["rotation"] = parentClip_rotation; + + return parentClipProperties; } \ No newline at end of file diff --git a/src/KeyFrameBBox.h b/src/TrackedObjectBBox.h similarity index 94% rename from src/KeyFrameBBox.h rename to src/TrackedObjectBBox.h index b3f446060..3e05529de 100644 --- a/src/KeyFrameBBox.h +++ b/src/TrackedObjectBBox.h @@ -1,6 +1,6 @@ /** * @file - * @brief Header file for the KeyFrameBBox class + * @brief Header file for the TrackedObjectBBox class * @author Jonathan Thomas * * @ref License @@ -28,8 +28,8 @@ * along with OpenShot Library. If not, see . */ -#ifndef OPENSHOT_BBOXKEYFRAME_H -#define OPENSHOT_BBOXKEYFRAME_H +#ifndef OPENSHOT_TRACKEDOBJECTBBOX_H +#define OPENSHOT_TRACKEDOBJECTBBOX_H #include #include @@ -42,7 +42,7 @@ #include "Point.h" #include "Json.h" #include "KeyFrame.h" -#include "KeyFrameBase.h" +#include "TrackedObjectBase.h" #include "protobuf_messages/trackerdata.pb.h" #include @@ -154,7 +154,7 @@ namespace openshot * object of this class. */ - class KeyFrameBBox : public KeyframeBase + class TrackedObjectBBox : public TrackedObjectBase { private: bool visible; @@ -171,7 +171,7 @@ namespace openshot std::string protobufDataPath; ///< Path to the protobuf file that holds the bbox points across the frames /// Default Constructor - KeyFrameBBox(); + TrackedObjectBBox(); /// Add a BBox to the BoxVec map void AddBox(int64_t _frame_num, float _cx, float _cy, float _width, float _height, float _angle); @@ -197,7 +197,7 @@ namespace openshot /// Return a bounding-box from BoxVec with it's properties adjusted by the Keyframes BBox GetBox(int64_t frame_number) const { - return const_cast(this)->GetBox(frame_number); + return const_cast(this)->GetBox(frame_number); } BBox GetBox(int64_t frame_number); @@ -227,7 +227,9 @@ namespace openshot 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; /// Return the bounding box properties and it's keyframes indexed by their names - std::map GetBoxValues(int64_t frame_number) override; + std::map GetBoxValues(int64_t frame_number) override; + /// Return properties of this object's parent clip + std::map GetParentClipProperties(int64_t frame_number); }; } // namespace openshot diff --git a/src/TrackedObjectBase.cpp b/src/TrackedObjectBase.cpp new file mode 100644 index 000000000..5d43d7fa5 --- /dev/null +++ b/src/TrackedObjectBase.cpp @@ -0,0 +1,46 @@ +/** + * @file + * @brief Source file for the TrackedObjectBase class + * @author Jonathan Thomas + * + * @ref License + */ + +/* LICENSE + * + * Copyright (c) 2008-2019 OpenShot Studios, LLC + * . This file is part of + * OpenShot Library (libopenshot), an open-source project dedicated to + * delivering high quality video editing and animation solutions to the + * world. For more information visit . + * + * OpenShot Library (libopenshot) is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * OpenShot Library (libopenshot) is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OpenShot Library. If not, see . + */ + +#include "TrackedObjectBase.h" +#include +#include +#include + + +namespace openshot{ + + TrackedObjectBase::TrackedObjectBase(){ + id = "None"; + } + + TrackedObjectBase::TrackedObjectBase(std::string _id){ + Id(_id); + } +} \ No newline at end of file diff --git a/src/TrackedObjectBase.h b/src/TrackedObjectBase.h new file mode 100644 index 000000000..acfd3ce82 --- /dev/null +++ b/src/TrackedObjectBase.h @@ -0,0 +1,97 @@ +/** + * @file + * @brief Header file for the TrackedObjectBase class + * @author Jonathan Thomas + * + * @ref License + */ + +/* LICENSE + * + * Copyright (c) 2008-2019 OpenShot Studios, LLC + * . This file is part of + * OpenShot Library (libopenshot), an open-source project dedicated to + * delivering high quality video editing and animation solutions to the + * world. For more information visit . + * + * OpenShot Library (libopenshot) is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * OpenShot Library (libopenshot) is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OpenShot Library. If not, see . + */ + +#ifndef OPENSHOT_TRACKEDOBJECTBASE_H +#define OPENSHOT_TRACKEDOBJECTBASE_H + +#include +#include +#include +#include +#include +#include +#include "Exceptions.h" +#include "Fraction.h" +#include "Coordinate.h" +#include "Point.h" +#include "Json.h" +#include "ClipBase.h" + + +namespace openshot { + /** + * @brief This abstract class is the base class of all Keyframes. + * + * A Keyframe is a collection of Point instances, which is used to vary a number or property over time. + * + * Keyframes are used to animate and interpolate values of properties over time. For example, a single property + * can use a Keyframe instead of a constant value. Assume you want to slide an image (from left to right) over + * a video. You can create a Keyframe which will adjust the X value of the image over 100 frames (or however many + * frames the animation needs to last) from the value of 0 to 640. + */ + + class TrackedObjectBase { + private: + std::string id; + ClipBase* parentClip; + + public: + + /// Blank constructor + TrackedObjectBase(); + + /// Default constructor + TrackedObjectBase(std::string _id); + + /// Get and set the id of this object + std::string Id() const { return id; } + void Id(std::string _id) { id = _id; } + /// Get and set the parentClip of this object + ClipBase* ParentClip() { return parentClip; } + void ParentClip(ClipBase* clip) { parentClip = clip; } + + /// Scale a property + virtual void ScalePoints(double scale) { return; }; + /// Return the main properties of a TrackedObjectBBox instance using a pointer to this base class + virtual std::map GetBoxValues(int64_t frame_number) { std::map ret; return ret; }; + /// Return the main properties of the tracked object's parent clip + virtual std::map GetParentClipProperties(int64_t frame_number) { std::map ret; return ret; } + + /// Get and Set JSON methods + virtual std::string Json() const = 0; ///< Generate JSON string of this object + virtual Json::Value JsonValue() const = 0; ///< Generate Json::Value for this object + virtual void SetJson(const std::string value) = 0; ///< Load JSON string into this object + virtual void SetJsonValue(const Json::Value root) = 0; ///< Load Json::Value into this object + + + }; +} // Namespace openshot + +#endif diff --git a/src/effects/Tracker.cpp b/src/effects/Tracker.cpp index 4c0df453e..651d9fca7 100644 --- a/src/effects/Tracker.cpp +++ b/src/effects/Tracker.cpp @@ -41,11 +41,13 @@ Tracker::Tracker(std::string clipTrackerDataPath) { // Init effect properties init_effect_details(); - // Instantiate a keyframebbox object and point to it - KeyFrameBBox trackedDataObject; - trackedData = std::make_shared(trackedDataObject); + // Instantiate a TrackedObjectBBox object and point to it + TrackedObjectBBox trackedDataObject; + trackedData = std::make_shared(trackedDataObject); // Tries to load the tracked object's data from protobuf file trackedData->LoadBoxData(clipTrackerDataPath); + ClipBase* parentClip = this->ParentClip(); + trackedData->ParentClip(parentClip); } // Default constructor @@ -53,9 +55,11 @@ Tracker::Tracker() { // Init effect properties init_effect_details(); - // Instantiate a keyframebbox object and point to it - KeyFrameBBox trackedDataObject; - trackedData = std::make_shared(trackedDataObject); + // Instantiate a TrackedObjectBBox object and point to it + TrackedObjectBBox trackedDataObject; + trackedData = std::make_shared(trackedDataObject); + ClipBase* parentClip = this->ParentClip(); + trackedData->ParentClip(parentClip); } diff --git a/src/effects/Tracker.h b/src/effects/Tracker.h index 41d0baed3..2cb1faf5a 100644 --- a/src/effects/Tracker.h +++ b/src/effects/Tracker.h @@ -41,7 +41,7 @@ #include "../Json.h" #include "../KeyFrame.h" #include "protobuf_messages/trackerdata.pb.h" -#include "../KeyFrameBBox.h" +#include "../TrackedObjectBBox.h" #include "../Clip.h" using namespace std; @@ -63,7 +63,7 @@ namespace openshot public: std::string protobuf_data_path; ///< Path to the protobuf file that holds the bounding-box data - std::shared_ptr trackedData; ///< Pointer to an object that holds the bounding-box data and it's Keyframes + std::shared_ptr trackedData; ///< Pointer to an object that holds the bounding-box data and it's Keyframes /// Blank constructor, useful when using Json to load the effect properties Tracker(std::string clipTrackerDataPath); diff --git a/tests/KeyFrame_Tests.cpp b/tests/KeyFrame_Tests.cpp index 9e67f9eec..31d93c3fb 100644 --- a/tests/KeyFrame_Tests.cpp +++ b/tests/KeyFrame_Tests.cpp @@ -35,7 +35,7 @@ // Prevent name clashes with juce::UnitTest #define DONT_SET_USING_JUCE_NAMESPACE 1 #include "KeyFrame.h" -#include "KeyFrameBBox.h" +#include "TrackedObjectBBox.h" #include "Coordinate.h" #include "Fraction.h" #include "Clip.h" @@ -506,14 +506,14 @@ TEST(Keyframe_Handle_Large_Segment) } -TEST(KeyFrameBBox_init_test) { +TEST(TrackedObjectBBox_init_test) { - KeyFrameBBox kfb; + TrackedObjectBBox kfb; } -TEST(KeyFrameBBox_addBox_test) { - KeyFrameBBox kfb; +TEST(TrackedObjectBBox_addBox_test) { + TrackedObjectBBox kfb; kfb.AddBox(1, 10.0, 10.0, 100.0, 100.0, 0.0); @@ -527,8 +527,8 @@ TEST(KeyFrameBBox_addBox_test) { } -TEST(KeyFrameBBox_GetVal_test) { - KeyFrameBBox kfb; +TEST(TrackedObjectBBox_GetVal_test) { + TrackedObjectBBox kfb; kfb.AddBox(1, 10.0, 10.0, 100.0, 100.0, 0.0); @@ -542,8 +542,8 @@ TEST(KeyFrameBBox_GetVal_test) { } -TEST(KeyFrameBBox_GetVal_Interpolation) { - KeyFrameBBox kfb; +TEST(TrackedObjectBBox_GetVal_Interpolation) { + TrackedObjectBBox kfb; kfb.AddBox(1, 10.0, 10.0, 100.0, 100.0, 0.0); kfb.AddBox(11, 20.0, 20.0, 100.0, 100.0, 0.0); @@ -574,8 +574,8 @@ TEST(KeyFrameBBox_GetVal_Interpolation) { } -TEST(KeyFrameBBox_Json_set) { - KeyFrameBBox kfb; +TEST(TrackedObjectBBox_Json_set) { + TrackedObjectBBox kfb; kfb.AddBox(1, 10.0, 10.0, 100.0, 100.0, 0.0); kfb.AddBox(10, 20.0, 20.0, 100.0, 100.0, 0.0); @@ -588,7 +588,7 @@ TEST(KeyFrameBBox_Json_set) { kfb.SetBaseFPS(Fraction(24.0, 1.0)); auto dataJSON = kfb.Json(); - KeyFrameBBox fromJSON_kfb; + TrackedObjectBBox fromJSON_kfb; fromJSON_kfb.SetJson(dataJSON); CHECK_EQUAL(kfb.GetBaseFPS().num, fromJSON_kfb.GetBaseFPS().num); @@ -607,8 +607,8 @@ TEST(KeyFrameBBox_Json_set) { CHECK_EQUAL(kfb_bbox.angle, fromJSON_bbox.angle); } -TEST(KeyFrameBBox_Scale_test){ - KeyFrameBBox kfb; +TEST(TrackedObjectBBox_Scale_test){ + TrackedObjectBBox kfb; kfb.AddBox(1, 10.0, 10.0, 10.0, 10.0, 0.0); kfb.scale_x.AddPoint(1.0, 2.0); @@ -646,7 +646,7 @@ TEST(Attach_test){ clip.AddEffect(&tracker); // Save a pointer to trackedData - std::shared_ptr trackedData = tracker.trackedData; + std::shared_ptr trackedData = tracker.trackedData; // Change trackedData scale trackedData->scale_x.AddPoint(1, 2.0); @@ -656,8 +656,8 @@ TEST(Attach_test){ auto trackedDataJson = trackedData->JsonValue(); // Get and cast the trakcedObject - auto trackedObject_base = t.GetTrackedObject("TESTBASEID"); - std::shared_ptr trackedObject = std::static_pointer_cast(trackedObject_base); + auto trackedObject_base = t.GetTrackedObject("None"); + std::shared_ptr trackedObject = std::static_pointer_cast(trackedObject_base); CHECK_EQUAL(trackedData, trackedObject); // Set trackedObject Json Value @@ -668,7 +668,7 @@ TEST(Attach_test){ childClip.Open(); childClip.AttachToTracker(tracked_id); - std::shared_ptr trackedTest = std::static_pointer_cast(childClip.GetAttachedObject()); + std::shared_ptr trackedTest = std::static_pointer_cast(childClip.GetAttachedObject()); CHECK_EQUAL(trackedData->scale_x.GetValue(1), trackedTest->scale_x.GetValue(1)); @@ -678,10 +678,10 @@ TEST(Attach_test){ TEST(GetBoxValues_test){ - KeyFrameBBox trackedDataObject; + TrackedObjectBBox trackedDataObject; trackedDataObject.AddBox(1, 10.0, 10.0, 20.0, 20.0, 30.0); - std::shared_ptr trackedData = std::make_shared(trackedDataObject); + std::shared_ptr trackedData = std::make_shared(trackedDataObject); auto boxValues = trackedData->GetBoxValues(1); From f05ded9a2f3587e4edeb371ca0fdf9633eb07a1f Mon Sep 17 00:00:00 2001 From: Brenno Date: Mon, 18 Jan 2021 15:12:45 -0300 Subject: [PATCH 18/84] Attaching clip to tracked object fixes Fixed bug that caused the clip to not attach correctly if the tracked object's parent clip wasn't in the position 0 of the timeline. Fixed bug that caused the wrong scale adjustment when an emoji or picture was attached to a tracked object. --- src/Clip.cpp | 49 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/src/Clip.cpp b/src/Clip.cpp index 341e111c8..b6c968a27 100644 --- a/src/Clip.cpp +++ b/src/Clip.cpp @@ -1144,6 +1144,9 @@ void Clip::AddEffect(EffectBase* effect) // Get tracked data from the Tracker effect std::shared_ptr trackedData = tracker->trackedData; + // Set tracked data parent clip to this + trackedData->ParentClip(this); + // Add tracked data to the timeline parentTimeline->AddTrackedObject(trackedData); } @@ -1228,6 +1231,12 @@ void Clip::apply_keyframes(std::shared_ptr frame, int width, int height) /* RESIZE SOURCE IMAGE - based on scale type */ QSize source_size = source_image->size(); + + // Apply stretch scale to correctly fit the bounding-box + if (attachedObject){ + scale = SCALE_STRETCH; + } + switch (scale) { case (SCALE_FIT): { @@ -1272,6 +1281,13 @@ void Clip::apply_keyframes(std::shared_ptr frame, int width, int height) float box_sy = 0.0; float box_r = 0.0; + // Initialize attached object's parent clip's properties + float attachedObjectParentClip_lx = 0.0; + float attachedObjectParentClip_ly = 0.0; + float attachedObjectParentClip_sx = 0.0; + float attachedObjectParentClip_sy = 0.0; + float attachedObjectParentClip_r = 0.0; + /* TRANSFORM CLIP TO ATTACHED OBJECT'S POSITION AND DIMENSION */ if (attachedObject){ // Convert Clip's frame position to Timeline's frame position @@ -1279,17 +1295,28 @@ void Clip::apply_keyframes(std::shared_ptr frame, int width, int height) long clip_start_frame = (Start() * info.fps.ToDouble()) + 1; double timeline_frame_number = frame->number + clip_start_position - clip_start_frame; - // Get attachedObject's parent clip frame number - Timeline* parentTimeline = (Timeline *) ParentTimeline(); - double attachedObjectParentClip_frame_number = timeline_frame_number - clip_start_position + clip_start_frame; - - // Access the TrackedObjectBBox properties - std::map boxValues = attachedObject->GetBoxValues(attachedObjectParentClip_frame_number); - + // Initialize attachedObject's properties + std::map boxValues; + + // Get attachedObject's properties and attachedObject's parent clip's properties + std::map attachedObject_ClipProperties = attachedObject->GetParentClipProperties(timeline_frame_number); + if (!attachedObject_ClipProperties.empty()){ + float attachedObjectParentClip_frame_number = attachedObject_ClipProperties["frame_number"]; + attachedObjectParentClip_lx = attachedObject_ClipProperties["location_x"]; + attachedObjectParentClip_ly = attachedObject_ClipProperties["location_y"]; + attachedObjectParentClip_sx = attachedObject_ClipProperties["scale_x"]; + attachedObjectParentClip_sy = attachedObject_ClipProperties["scale_y"]; + attachedObjectParentClip_r = attachedObject_ClipProperties["rotation"]; + // Access the attachedObject's properties + boxValues = attachedObject->GetBoxValues(attachedObjectParentClip_frame_number); + } else { + // Access the attachedObject's properties + boxValues = attachedObject->GetBoxValues(timeline_frame_number); + } + // Get the bounding-box values and correct them by the clip's reference system box_cx = boxValues["cx"] - 0.5; box_cy = boxValues["cy"] - 0.5; - // box_sx = boxValues["w"]*boxValues["sx"]*2.0; box_sx = boxValues["w"]*boxValues["sx"]; box_sy = boxValues["h"]*boxValues["sy"]; box_r = boxValues["r"]; @@ -1351,9 +1378,9 @@ void Clip::apply_keyframes(std::shared_ptr frame, int width, int height) QTransform transform; /* LOCATION, ROTATION, AND SCALE */ - float r = rotation.GetValue(frame->number) + box_r; // rotate in degrees - x += (width * (location_x.GetValue(frame->number) + box_cx)); // move in percentage of final width - y += (height * (location_y.GetValue(frame->number) + box_cy)); // move in percentage of final height + float r = rotation.GetValue(frame->number) + box_r + attachedObjectParentClip_r; // rotate in degrees + x += (width * (location_x.GetValue(frame->number) + box_cx + attachedObjectParentClip_lx )); // move in percentage of final width + y += (height * (location_y.GetValue(frame->number) + box_cy + attachedObjectParentClip_ly )); // move in percentage of final height float shear_x_value = shear_x.GetValue(frame->number); float shear_y_value = shear_y.GetValue(frame->number); float origin_x_value = origin_x.GetValue(frame->number); From b08e65f24fece388869ca61be44d0c04782642cd Mon Sep 17 00:00:00 2001 From: Brenno Date: Mon, 18 Jan 2021 15:17:10 -0300 Subject: [PATCH 19/84] Tracked object bounding box transform handler fix Fixed bug that caused the tracked object bounding box to be incorrectly updated when the user interacted with it's transform handler. --- src/Timeline.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Timeline.cpp b/src/Timeline.cpp index 4c4be0c06..8cbfeb843 100644 --- a/src/Timeline.cpp +++ b/src/Timeline.cpp @@ -773,6 +773,15 @@ std::shared_ptr Timeline::GetFrame(int64_t requested_frame) return frame; } + // Check if previous frame was cached? (if not, assume we are seeking somewhere else on the Timeline, and need + // to clear all cache (for continuity sake). For example, jumping back to a previous spot can cause issues with audio + // data where the new jump location doesn't match up with the previously cached audio data. + std::shared_ptr previous_frame = final_cache->GetFrame(requested_frame - 1); + if (!previous_frame) { + // Seeking to new place on timeline (destroy cache) + ClearAllCache(); + } + // Minimum number of frames to process (for performance reasons) int minimum_frames = OPEN_MP_NUM_PROCESSORS; From cb61f914f70a287e26a58fcea00a6d052102c7b6 Mon Sep 17 00:00:00 2001 From: Brenno Date: Mon, 18 Jan 2021 15:30:11 -0300 Subject: [PATCH 20/84] Tracker effect and export video fixes Fixed bug that made Openshot crash if two or more Tracker effects were added to the same video. Fixed bug that made the clips to be incorrectly attached to tracked objects in the exported video. --- src/Clip.cpp | 45 ++++++++++++++++++++++----------------- src/Timeline.cpp | 7 ++++++ src/TrackedObjectBBox.cpp | 2 +- src/TrackedObjectBBox.h | 8 +++---- 4 files changed, 38 insertions(+), 24 deletions(-) diff --git a/src/Clip.cpp b/src/Clip.cpp index b6c968a27..1f52fd9ba 100644 --- a/src/Clip.cpp +++ b/src/Clip.cpp @@ -248,19 +248,21 @@ Clip::~Clip() void Clip::AttachToTracker(std::string tracked_id) { // Search for the tracked object on the timeline - Timeline *parentTimeline = (Timeline *) ParentTimeline(); + Timeline* parentTimeline = (Timeline *) ParentTimeline(); - // Create a smart pointer to the tracked object from the timeline - std::shared_ptr trackedObject = parentTimeline->GetTrackedObject(tracked_id); - - // Check for valid tracked object - if (trackedObject){ - SetAttachedObject(trackedObject); - return; - } - else{ - return; + // Check if the clip has a parent timeline + if (parentTimeline){ + + // Create a smart pointer to the tracked object from the timeline + std::shared_ptr trackedObject = parentTimeline->GetTrackedObject(tracked_id); + + // Check for valid tracked object + if (trackedObject){ + SetAttachedObject(trackedObject); + } + } + return; } // Set the pointer to the trackedObject this clip is attached to @@ -1138,17 +1140,22 @@ void Clip::AddEffect(EffectBase* effect) Timeline* parentTimeline = (Timeline *) ParentTimeline(); - // Downcast effect as Tracker - Tracker* tracker = (Tracker *) effect; + // Check if this clip has a parent timeline + if (parentTimeline){ - // Get tracked data from the Tracker effect - std::shared_ptr trackedData = tracker->trackedData; + // Downcast effect as Tracker + Tracker* tracker = (Tracker *) effect; - // Set tracked data parent clip to this - trackedData->ParentClip(this); + // Get tracked data from the Tracker effect + std::shared_ptr trackedData = tracker->trackedData; - // Add tracked data to the timeline - parentTimeline->AddTrackedObject(trackedData); + // Set tracked data parent clip to this + trackedData->ParentClip(this); + + // Add tracked data to the timeline + parentTimeline->AddTrackedObject(trackedData); + + } } // Clear cache diff --git a/src/Timeline.cpp b/src/Timeline.cpp index 8cbfeb843..de69bcce8 100644 --- a/src/Timeline.cpp +++ b/src/Timeline.cpp @@ -1071,6 +1071,13 @@ void Timeline::SetJsonValue(const Json::Value root) { // Create Clip Clip *c = new Clip(); + // When a clip is attached to an object, it searches for the object + // on it's parent timeline. Setting the parent timeline of the clip here + // allows attaching it to an object when exporting the project (because) + // the exporter script initializes the clip and it's effects + // before setting it's parent timeline. + c->ParentTimeline(this); + // Load Json into Clip c->SetJsonValue(existing_clip); diff --git a/src/TrackedObjectBBox.cpp b/src/TrackedObjectBBox.cpp index 119ec0839..b926d4487 100644 --- a/src/TrackedObjectBBox.cpp +++ b/src/TrackedObjectBBox.cpp @@ -475,7 +475,7 @@ std::map TrackedObjectBBox::GetParentClipProperties(int64_t // Calculate parentClip's frame number long parentClip_start_position = round( parentClip->Position() * parentClip->info.fps.ToDouble() ) + 1; long parentClip_start_frame = ( parentClip->Start() * parentClip->info.fps.ToDouble() ) + 1; - float parentClip_frame_number = frame_number - parentClip_start_position + parentClip_start_frame; + float parentClip_frame_number = round(frame_number - parentClip_start_position) + parentClip_start_frame; // Get parentClip's Keyframes float parentClip_location_x = parentClip->location_x.GetValue(parentClip_frame_number); diff --git a/src/TrackedObjectBBox.h b/src/TrackedObjectBBox.h index 3e05529de..d7903b734 100644 --- a/src/TrackedObjectBBox.h +++ b/src/TrackedObjectBBox.h @@ -214,10 +214,10 @@ namespace openshot void clear(); /// Get and Set JSON methods - std::string Json() const; ///< Generate JSON string of this object - Json::Value JsonValue() const; ///< Generate Json::Value for this object - void SetJson(const std::string value); ///< Load JSON string into this object - void SetJsonValue(const Json::Value root); ///< Load Json::Value into this object + std::string Json() const override; ///< Generate JSON string of this object + Json::Value JsonValue() const override; ///< Generate Json::Value for this object + void SetJson(const std::string value) override; ///< Load JSON string into this object + void SetJsonValue(const Json::Value root) override; ///< Load Json::Value into this object /// Get all properties for a specific frame (perfect for a UI to display the current state /// of all properties at any time) From f8198d668f00b17f777a4bc73c129c2bf438f3ad Mon Sep 17 00:00:00 2001 From: Brenno Date: Tue, 19 Jan 2021 15:28:33 -0300 Subject: [PATCH 21/84] Fixed codacy review warnings --- src/CVObjectDetection.cpp | 7 +++---- src/CVStabilization.cpp | 6 ++++-- src/CVTracker.cpp | 2 ++ src/sort_filter/Hungarian.cpp | 5 ++--- src/sort_filter/sort.cpp | 6 +++--- src/sort_filter/sort.hpp | 2 ++ 6 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/CVObjectDetection.cpp b/src/CVObjectDetection.cpp index ca0e92aef..c391197a2 100644 --- a/src/CVObjectDetection.cpp +++ b/src/CVObjectDetection.cpp @@ -38,6 +38,8 @@ using google::protobuf::util::TimeUtil; CVObjectDetection::CVObjectDetection(std::string processInfoJson, ProcessingController &processingController) : processingController(&processingController), processingDevice("CPU"){ SetJson(processInfoJson); + confThreshold = 0.5; + nmsThreshold = 0.1; } void CVObjectDetection::setProcessingDevice(){ @@ -69,9 +71,6 @@ void CVObjectDetection::detectObjectsClip(openshot::Clip &video, size_t _start, std::string line; while (std::getline(ifs, line)) classNames.push_back(line); - confThreshold = 0.5; - nmsThreshold = 0.1; - // Load the network if(classesFile == "" || modelConfiguration == "" || modelWeights == "") return; @@ -79,7 +78,7 @@ void CVObjectDetection::detectObjectsClip(openshot::Clip &video, size_t _start, setProcessingDevice(); size_t frame_number; - if(!process_interval || end == 0 || end-start <= 0){ + if(!process_interval || end == 0 || end-start == 0){ // Get total number of frames in video start = video.Start() * video.Reader()->info.fps.ToInt(); end = video.End() * video.Reader()->info.fps.ToInt(); diff --git a/src/CVStabilization.cpp b/src/CVStabilization.cpp index b2f944b92..864f9b583 100644 --- a/src/CVStabilization.cpp +++ b/src/CVStabilization.cpp @@ -39,6 +39,8 @@ using google::protobuf::util::TimeUtil; CVStabilization::CVStabilization(std::string processInfoJson, ProcessingController &processingController) : processingController(&processingController){ SetJson(processInfoJson); + start = 0; + end = 0; } // Process clip and store necessary stabilization data @@ -58,7 +60,7 @@ void CVStabilization::stabilizeClip(openshot::Clip& video, size_t _start, size_t cv::Size readerDims(video.Reader()->info.width, video.Reader()->info.height); size_t frame_number; - if(!process_interval || end == 0 || end-start <= 0){ + if(!process_interval || end == 0 || end-start == 0){ // Get total number of frames in video start = video.Start() * video.Reader()->info.fps.ToInt(); end = video.End() * video.Reader()->info.fps.ToInt(); @@ -230,7 +232,7 @@ std::map CVStabilization::SmoothTrajectory(std::vector = 0 && i+j < trajectory.size()) { + if(i+j < trajectory.size()) { sum_x += trajectory[i+j].x; sum_y += trajectory[i+j].y; sum_a += trajectory[i+j].a; diff --git a/src/CVTracker.cpp b/src/CVTracker.cpp index 757420252..fda0fbf14 100644 --- a/src/CVTracker.cpp +++ b/src/CVTracker.cpp @@ -40,6 +40,8 @@ using google::protobuf::util::TimeUtil; CVTracker::CVTracker(std::string processInfoJson, ProcessingController &processingController) : processingController(&processingController), json_interval(false){ SetJson(processInfoJson); + start = 0; + end = 0; } // Set desirable tracker method diff --git a/src/sort_filter/Hungarian.cpp b/src/sort_filter/Hungarian.cpp index 61b9c36b1..eac72263d 100644 --- a/src/sort_filter/Hungarian.cpp +++ b/src/sort_filter/Hungarian.cpp @@ -192,10 +192,9 @@ void HungarianAlgorithm::buildassignmentvector( int nOfRows, int nOfColumns) { - int row, col; - for (row = 0; row < nOfRows; row++) - for (col = 0; col < nOfColumns; col++) + for (int row = 0; row < nOfRows; row++) + for (int col = 0; col < nOfColumns; col++) if (starMatrix[row + nOfRows * col]) { #ifdef ONE_INDEXING diff --git a/src/sort_filter/sort.cpp b/src/sort_filter/sort.cpp index 299bfb1a0..03225e179 100644 --- a/src/sort_filter/sort.cpp +++ b/src/sort_filter/sort.cpp @@ -7,6 +7,7 @@ SortTracker::SortTracker(int max_age, int min_hits) { _min_hits = min_hits; _max_age = max_age; + alive_tracker = true; } // Computes IOU between two bounding boxes @@ -154,11 +155,10 @@ void SortTracker::update(vector detections_cv, int frame_count, double matchedPairs.push_back(cv::Point(i, assignment[i])); } - int detIdx, trkIdx; for (unsigned int i = 0; i < matchedPairs.size(); i++) { - trkIdx = matchedPairs[i].x; - detIdx = matchedPairs[i].y; + int trkIdx = matchedPairs[i].x; + int detIdx = matchedPairs[i].y; trackers[trkIdx].update(detections[detIdx].box); trackers[trkIdx].classId = detections[detIdx].classId; trackers[trkIdx].confidence = detections[detIdx].confidence; diff --git a/src/sort_filter/sort.hpp b/src/sort_filter/sort.hpp index 4eab6dcda..295b9d567 100644 --- a/src/sort_filter/sort.hpp +++ b/src/sort_filter/sort.hpp @@ -22,6 +22,8 @@ typedef struct TrackingBox int classId = 0; int id = 0; cv::Rect_ box = cv::Rect_(0.0, 0.0, 0.0, 0.0); + TrackingBox() {} + TrackingBox(int _frame, float _confidence, int _classId, int _id) : frame(_frame), confidence(_confidence), classId(_classId), id(_id) {} } TrackingBox; class SortTracker From a7d2b6adab328f6f873c92aa46d266d89a4e14fa Mon Sep 17 00:00:00 2001 From: Brenno Date: Tue, 19 Jan 2021 16:03:51 -0300 Subject: [PATCH 22/84] Fixed clip transform handler when attached to object --- src/Clip.cpp | 130 ++++++++++++++++++++++++-------------- src/Fraction.cpp | 2 +- src/Fraction.h | 2 +- src/TrackedObjectBBox.cpp | 4 +- src/TrackedObjectBBox.h | 4 +- src/TrackedObjectBase.h | 6 +- 6 files changed, 91 insertions(+), 57 deletions(-) diff --git a/src/Clip.cpp b/src/Clip.cpp index 1f52fd9ba..3288929ef 100644 --- a/src/Clip.cpp +++ b/src/Clip.cpp @@ -825,16 +825,50 @@ std::string Clip::PropertiesJSON(int64_t requested_frame) const { // Add waveform choices (dropdown style) root["waveform"]["choices"].append(add_property_choice_json("Yes", true, waveform)); root["waveform"]["choices"].append(add_property_choice_json("No", false, waveform)); + + if (attachedObject){ + + // Convert Clip's frame position to Timeline's frame position + long clip_start_position = round(Position() * info.fps.ToDouble()) + 1; + long clip_start_frame = (Start() * info.fps.ToDouble()) + 1; + double timeline_frame_number = requested_frame + clip_start_position - clip_start_frame; + + // Get attached object's parent clip properties + std::map< std::string, float > attached_clip_properties = attachedObject->GetParentClipProperties(timeline_frame_number); + double attached_frame_number = attached_clip_properties["frame_number"]; + + // Get attached object properties + std::map< std::string, float > attached_properties = attachedObject->GetBoxValues(attached_frame_number); + + // Compose attachedObject's properties with it's parent clip's properties + float attached_location_x = attached_properties["cx"] - 0.5 + attached_clip_properties["cx"]; + float attached_location_y = attached_properties["cy"] - 0.5 + attached_clip_properties["cy"]; + float attached_scale_x = attached_properties["w"]*attached_properties["sx"]; + float attached_scale_y = attached_properties["h"]*attached_properties["sy"]; + float attached_rotation = attached_properties["r"] + attached_clip_properties["r"]; + + // Set JSON properties with composed attached object's properties + root["location_x"] = add_property_json("Location X", attached_location_x, "float", "", &location_x, -1.0, 1.0, false, requested_frame); + root["location_y"] = add_property_json("Location Y", attached_location_y, "float", "", &location_y, -1.0, 1.0, false, requested_frame); + root["scale_x"] = add_property_json("Scale X", attached_scale_x, "float", "", &scale_x, 0.0, 1.0, false, requested_frame); + root["scale_y"] = add_property_json("Scale Y", attached_scale_y, "float", "", &scale_y, 0.0, 1.0, false, requested_frame); + root["rotation"] = add_property_json("Rotation", attached_rotation, "float", "", &rotation, -360, 360, false, requested_frame); + + } else { + + // Set JSON properties with clip's properties + root["location_x"] = add_property_json("Location X", location_x.GetValue(requested_frame), "float", "", &location_x, -1.0, 1.0, false, requested_frame); + root["location_y"] = add_property_json("Location Y", location_y.GetValue(requested_frame), "float", "", &location_y, -1.0, 1.0, false, requested_frame); + root["scale_x"] = add_property_json("Scale X", scale_x.GetValue(requested_frame), "float", "", &scale_x, 0.0, 1.0, false, requested_frame); + root["scale_y"] = add_property_json("Scale Y", 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, -360, 360, false, requested_frame); + + } // Keyframes - root["location_x"] = add_property_json("Location X", location_x.GetValue(requested_frame), "float", "", &location_x, -1.0, 1.0, false, requested_frame); - root["location_y"] = add_property_json("Location Y", location_y.GetValue(requested_frame), "float", "", &location_y, -1.0, 1.0, false, requested_frame); - root["scale_x"] = add_property_json("Scale X", scale_x.GetValue(requested_frame), "float", "", &scale_x, 0.0, 1.0, false, requested_frame); - root["scale_y"] = add_property_json("Scale Y", scale_y.GetValue(requested_frame), "float", "", &scale_y, 0.0, 1.0, false, requested_frame); root["alpha"] = add_property_json("Alpha", alpha.GetValue(requested_frame), "float", "", &alpha, 0.0, 1.0, false, requested_frame); root["shear_x"] = add_property_json("Shear X", shear_x.GetValue(requested_frame), "float", "", &shear_x, -1.0, 1.0, false, requested_frame); root["shear_y"] = add_property_json("Shear Y", shear_y.GetValue(requested_frame), "float", "", &shear_y, -1.0, 1.0, false, requested_frame); - root["rotation"] = add_property_json("Rotation", rotation.GetValue(requested_frame), "float", "", &rotation, -360, 360, false, requested_frame); root["origin_x"] = add_property_json("Origin X", origin_x.GetValue(requested_frame), "float", "", &origin_x, 0.0, 1.0, false, requested_frame); root["origin_y"] = add_property_json("Origin Y", origin_y.GetValue(requested_frame), "float", "", &origin_y, 0.0, 1.0, false, requested_frame); root["volume"] = add_property_json("Volume", volume.GetValue(requested_frame), "float", "", &volume, 0.0, 1.0, false, requested_frame); @@ -1281,52 +1315,50 @@ void Clip::apply_keyframes(std::shared_ptr frame, int width, int height) } } - // Initialize bounding-box values - float box_cx = 0.0; - float box_cy = 0.0; - float box_sx = 0.0; - float box_sy = 0.0; - float box_r = 0.0; - - // Initialize attached object's parent clip's properties - float attachedObjectParentClip_lx = 0.0; - float attachedObjectParentClip_ly = 0.0; - float attachedObjectParentClip_sx = 0.0; - float attachedObjectParentClip_sy = 0.0; - float attachedObjectParentClip_r = 0.0; + // Initialize attached object's properties values + float attached_location_x = 0.0; + float attached_location_y = 0.0; + float attached_scale_x = 1.0; + float attached_scale_y = 1.0; + float attached_rotation = 0.0; /* TRANSFORM CLIP TO ATTACHED OBJECT'S POSITION AND DIMENSION */ if (attachedObject){ + // Convert Clip's frame position to Timeline's frame position long clip_start_position = round(Position() * info.fps.ToDouble()) + 1; long clip_start_frame = (Start() * info.fps.ToDouble()) + 1; double timeline_frame_number = frame->number + clip_start_position - clip_start_frame; - // Initialize attachedObject's properties - std::map boxValues; - - // Get attachedObject's properties and attachedObject's parent clip's properties - std::map attachedObject_ClipProperties = attachedObject->GetParentClipProperties(timeline_frame_number); - if (!attachedObject_ClipProperties.empty()){ - float attachedObjectParentClip_frame_number = attachedObject_ClipProperties["frame_number"]; - attachedObjectParentClip_lx = attachedObject_ClipProperties["location_x"]; - attachedObjectParentClip_ly = attachedObject_ClipProperties["location_y"]; - attachedObjectParentClip_sx = attachedObject_ClipProperties["scale_x"]; - attachedObjectParentClip_sy = attachedObject_ClipProperties["scale_y"]; - attachedObjectParentClip_r = attachedObject_ClipProperties["rotation"]; - // Access the attachedObject's properties - boxValues = attachedObject->GetBoxValues(attachedObjectParentClip_frame_number); + // Get attached object's parent clip properties + std::map< std::string, float > attached_clip_properties = attachedObject->GetParentClipProperties(timeline_frame_number); + + // Get attachedObject's properties and compose with attachedObject's parent clip properties + if (!attached_clip_properties.empty()){ + + // Get attachedObject's parent clip frame number + double attached_frame_number = attached_clip_properties["frame_number"]; + + // Get attachedObject's properties values + std::map< std::string, float > attached_properties = attachedObject->GetBoxValues(attached_frame_number); + + attached_location_x = attached_properties["cx"] - 0.5 + attached_clip_properties["cx"]; + attached_location_y = attached_properties["cy"] - 0.5 + attached_clip_properties["cy"]; + attached_scale_x = attached_properties["w"]*attached_properties["sx"]; + attached_scale_y = attached_properties["h"]*attached_properties["sy"]; + attached_rotation = attached_properties["r"] + attached_clip_properties["r"]; + } else { - // Access the attachedObject's properties - boxValues = attachedObject->GetBoxValues(timeline_frame_number); + // Get attachedObject's properties values + std::map< std::string, float > attached_properties = attachedObject->GetBoxValues(timeline_frame_number); + + attached_location_x = attached_properties["cx"] - 0.5; + attached_location_y = attached_properties["cy"] - 0.5; + attached_scale_x = attached_properties["w"]*attached_properties["sx"]; + attached_scale_y = attached_properties["h"]*attached_properties["sy"]; + attached_rotation = attached_properties["r"]; + } - - // Get the bounding-box values and correct them by the clip's reference system - box_cx = boxValues["cx"] - 0.5; - box_cy = boxValues["cy"] - 0.5; - box_sx = boxValues["w"]*boxValues["sx"]; - box_sy = boxValues["h"]*boxValues["sy"]; - box_r = boxValues["r"]; } /* GRAVITY LOCATION - Initialize X & Y to the correct values (before applying location curves) */ @@ -1336,11 +1368,13 @@ void Clip::apply_keyframes(std::shared_ptr frame, int width, int height) // Adjust size for scale x and scale y float sx = scale_x.GetValue(frame->number); // percentage X scale float sy = scale_y.GetValue(frame->number); // percentage Y scale - // Change clip's scale to bounding-box scale - if(box_sx > 0.0 && box_sy > 0.0){ - sx = box_sx; - sy = box_sy; + + // Compose clip's scale to attachedObject's scale + if(attached_scale_x > 0.0 && attached_scale_y > 0.0){ + sx*= attached_scale_x; + sy*= attached_scale_y; } + float scaled_source_width = source_size.width() * sx; float scaled_source_height = source_size.height() * sy; @@ -1385,9 +1419,9 @@ void Clip::apply_keyframes(std::shared_ptr frame, int width, int height) QTransform transform; /* LOCATION, ROTATION, AND SCALE */ - float r = rotation.GetValue(frame->number) + box_r + attachedObjectParentClip_r; // rotate in degrees - x += (width * (location_x.GetValue(frame->number) + box_cx + attachedObjectParentClip_lx )); // move in percentage of final width - y += (height * (location_y.GetValue(frame->number) + box_cy + attachedObjectParentClip_ly )); // move in percentage of final height + float r = rotation.GetValue(frame->number) + attached_rotation; // rotate in degrees + x += ( width * (location_x.GetValue(frame->number) + attached_location_x) ); // move in percentage of final width + y += ( height * (location_y.GetValue(frame->number) + attached_location_y) ); // move in percentage of final height float shear_x_value = shear_x.GetValue(frame->number); float shear_y_value = shear_y.GetValue(frame->number); float origin_x_value = origin_x.GetValue(frame->number); diff --git a/src/Fraction.cpp b/src/Fraction.cpp index 869ef35ff..b0d5464d3 100644 --- a/src/Fraction.cpp +++ b/src/Fraction.cpp @@ -46,7 +46,7 @@ float Fraction::ToFloat() { } // Return this fraction as a double (i.e. 1/2 = 0.5) -double Fraction::ToDouble() { +double Fraction::ToDouble() const { return double(num) / double(den); } diff --git a/src/Fraction.h b/src/Fraction.h index 88c16fbc0..0c46643e5 100644 --- a/src/Fraction.h +++ b/src/Fraction.h @@ -62,7 +62,7 @@ namespace openshot { float ToFloat(); /// Return this fraction as a double (i.e. 1/2 = 0.5) - double ToDouble(); + double ToDouble() const; /// Return a rounded integer of the fraction (for example 30000/1001 returns 30) int ToInt(); diff --git a/src/TrackedObjectBBox.cpp b/src/TrackedObjectBBox.cpp index b926d4487..40ba5e21c 100644 --- a/src/TrackedObjectBBox.cpp +++ b/src/TrackedObjectBBox.cpp @@ -440,7 +440,7 @@ Json::Value TrackedObjectBBox::add_property_json(std::string name, float value, } // Return the bounding box properties and it's keyframes indexed by their names -std::map TrackedObjectBBox::GetBoxValues(int64_t frame_number){ +std::map TrackedObjectBBox::GetBoxValues(int64_t frame_number) const { // Create the map std::map boxValues; @@ -467,7 +467,7 @@ std::map TrackedObjectBBox::GetBoxValues(int64_t frame_numbe } // Return properties of this object's parent clip -std::map TrackedObjectBBox::GetParentClipProperties(int64_t frame_number){ +std::map TrackedObjectBBox::GetParentClipProperties(int64_t frame_number) const { // Get the parent clip of this object as a Clip pointer Clip* parentClip = (Clip *) ParentClip(); diff --git a/src/TrackedObjectBBox.h b/src/TrackedObjectBBox.h index d7903b734..a990b4fda 100644 --- a/src/TrackedObjectBBox.h +++ b/src/TrackedObjectBBox.h @@ -227,9 +227,9 @@ namespace openshot 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; /// Return the bounding box properties and it's keyframes indexed by their names - std::map GetBoxValues(int64_t frame_number) override; + std::map GetBoxValues(int64_t frame_number) const override; /// Return properties of this object's parent clip - std::map GetParentClipProperties(int64_t frame_number); + std::map GetParentClipProperties(int64_t frame_number) const override; }; } // namespace openshot diff --git a/src/TrackedObjectBase.h b/src/TrackedObjectBase.h index acfd3ce82..5278f4c0c 100644 --- a/src/TrackedObjectBase.h +++ b/src/TrackedObjectBase.h @@ -74,15 +74,15 @@ namespace openshot { std::string Id() const { return id; } void Id(std::string _id) { id = _id; } /// Get and set the parentClip of this object - ClipBase* ParentClip() { return parentClip; } + ClipBase* ParentClip() const { return parentClip; } void ParentClip(ClipBase* clip) { parentClip = clip; } /// Scale a property virtual void ScalePoints(double scale) { return; }; /// Return the main properties of a TrackedObjectBBox instance using a pointer to this base class - virtual std::map GetBoxValues(int64_t frame_number) { std::map ret; return ret; }; + virtual std::map GetBoxValues(int64_t frame_number) const { std::map ret; return ret; }; /// Return the main properties of the tracked object's parent clip - virtual std::map GetParentClipProperties(int64_t frame_number) { std::map ret; return ret; } + virtual std::map GetParentClipProperties(int64_t frame_number) const { std::map ret; return ret; } /// Get and Set JSON methods virtual std::string Json() const = 0; ///< Generate JSON string of this object From 17463313fc4cca0210422feae49dc0b2ad9f6f00 Mon Sep 17 00:00:00 2001 From: Brenno Date: Fri, 22 Jan 2021 19:00:44 -0300 Subject: [PATCH 23/84] Clip.cpp: Removed hard-coded Tracker effect check in AddEffect function Added "has_tracked_object" property on EffectBase so that the AddEffect function checks for this property instead of the Tracker effect name - this way it's possible to support other effects that have tracked objects but different names. --- src/Clip.cpp | 21 +++++++++++---------- src/EffectBase.cpp | 1 + src/EffectBase.h | 5 +++++ src/TrackedObjectBBox.h | 2 +- src/TrackedObjectBase.h | 3 +++ src/effects/ObjectDetection.cpp | 1 + src/effects/Tracker.cpp | 19 +++++++++++++++++-- 7 files changed, 39 insertions(+), 13 deletions(-) diff --git a/src/Clip.cpp b/src/Clip.cpp index 3288929ef..b1ea5c315 100644 --- a/src/Clip.cpp +++ b/src/Clip.cpp @@ -1170,24 +1170,25 @@ void Clip::AddEffect(EffectBase* effect) sort_effects(); // Add Tracker to Timeline - if (effect->info.class_name == "Tracker"){ + if (effect->info.has_tracked_object){ Timeline* parentTimeline = (Timeline *) ParentTimeline(); // Check if this clip has a parent timeline if (parentTimeline){ - // Downcast effect as Tracker - Tracker* tracker = (Tracker *) effect; - - // Get tracked data from the Tracker effect - std::shared_ptr trackedData = tracker->trackedData; + // Iterate through effect's vector of Tracked Objects + for (auto const& trackedObject : effect->trackedObjects){ + + // Cast the Tracked Object as TrackedObjectBBox + std::shared_ptr trackedObjectBBox = std::static_pointer_cast(trackedObject.second); - // Set tracked data parent clip to this - trackedData->ParentClip(this); + // Set the Tracked Object's parent clip to this + trackedObjectBBox->ParentClip(this); - // Add tracked data to the timeline - parentTimeline->AddTrackedObject(trackedData); + // Add the Tracked Object to the timeline + parentTimeline->AddTrackedObject(trackedObjectBBox); + } } } diff --git a/src/EffectBase.cpp b/src/EffectBase.cpp index 458381ced..aa2bc4e42 100644 --- a/src/EffectBase.cpp +++ b/src/EffectBase.cpp @@ -47,6 +47,7 @@ void EffectBase::InitEffectInfo() info.has_audio = false; info.name = ""; info.description = ""; + info.has_tracked_object = false; } // Display file information diff --git a/src/EffectBase.h b/src/EffectBase.h index 090637e7e..320e840cf 100644 --- a/src/EffectBase.h +++ b/src/EffectBase.h @@ -37,6 +37,7 @@ #include "ClipBase.h" #include "Json.h" #include "Frame.h" +#include "TrackedObjectBase.h" namespace openshot { @@ -54,6 +55,7 @@ namespace openshot std::string description; ///< The description of this effect and what it does 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 + bool has_tracked_object; ///< Determines if this effect track objects through the clip }; /** @@ -73,6 +75,9 @@ namespace openshot public: + /// Map of Tracked Object's by their indices (used by Effects that track objects on clips) + std::map > trackedObjects; + /// Information about the current effect EffectInfoStruct info; diff --git a/src/TrackedObjectBBox.h b/src/TrackedObjectBBox.h index a990b4fda..4a5a34ada 100644 --- a/src/TrackedObjectBBox.h +++ b/src/TrackedObjectBBox.h @@ -221,7 +221,7 @@ namespace openshot /// Get all properties for a specific frame (perfect for a UI to display the current state /// of all properties at any time) - Json::Value PropertiesJSON(int64_t requested_frame) const; + Json::Value PropertiesJSON(int64_t requested_frame) const override; // Generate JSON for a property 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; diff --git a/src/TrackedObjectBase.h b/src/TrackedObjectBase.h index 5278f4c0c..683b0b3f1 100644 --- a/src/TrackedObjectBase.h +++ b/src/TrackedObjectBase.h @@ -90,6 +90,9 @@ namespace openshot { virtual void SetJson(const std::string value) = 0; ///< Load JSON string into this object virtual void SetJsonValue(const Json::Value root) = 0; ///< Load Json::Value into this object + /// Get all properties for a specific frame (perfect for a UI to display the current state + /// of all properties at any time) + virtual Json::Value PropertiesJSON(int64_t requested_frame) const = 0; }; } // Namespace openshot diff --git a/src/effects/ObjectDetection.cpp b/src/effects/ObjectDetection.cpp index 7c84e7163..929c9039a 100644 --- a/src/effects/ObjectDetection.cpp +++ b/src/effects/ObjectDetection.cpp @@ -64,6 +64,7 @@ void ObjectDetection::init_effect_details() info.description = "Detect objects through the video."; info.has_audio = false; info.has_video = true; + info.has_tracked_object = false; } // This method is required for all derived classes of EffectBase, and returns a diff --git a/src/effects/Tracker.cpp b/src/effects/Tracker.cpp index 651d9fca7..260909bf9 100644 --- a/src/effects/Tracker.cpp +++ b/src/effects/Tracker.cpp @@ -48,6 +48,8 @@ Tracker::Tracker(std::string clipTrackerDataPath) trackedData->LoadBoxData(clipTrackerDataPath); ClipBase* parentClip = this->ParentClip(); trackedData->ParentClip(parentClip); + // Insert TrackedObject with index 0 to the trackedObjects map + trackedObjects.insert({0, trackedData}); } // Default constructor @@ -60,6 +62,8 @@ Tracker::Tracker() trackedData = std::make_shared(trackedDataObject); ClipBase* parentClip = this->ParentClip(); trackedData->ParentClip(parentClip); + // Insert TrackedObject with index 0 to the trackedObjects map + trackedObjects.insert({0, trackedData}); } @@ -75,6 +79,7 @@ void Tracker::init_effect_details() info.description = "Track the selected bounding box through the video."; info.has_audio = false; info.has_video = true; + info.has_tracked_object = true; this->TimeScale = 1.0; } @@ -207,7 +212,9 @@ void Tracker::SetJsonValue(const Json::Value root) { } } - trackedData->SetJsonValue(root); + for (auto const& trackedObject : trackedObjects){ + trackedObject.second->SetJsonValue(root); + } return; } @@ -218,7 +225,15 @@ std::string Tracker::PropertiesJSON(int64_t requested_frame) const { // Generate JSON properties list Json::Value root; - root = trackedData->PropertiesJSON(requested_frame); + + // Add trackedObjects properties to JSON + for (auto const& trackedObject : trackedObjects){ + Json::Value trackedObjectJSON = trackedObject.second->PropertiesJSON(requested_frame); + // Save the trackedData properties on root + for (const auto& key : trackedObjectJSON.getMemberNames()){ + root[key] = trackedObjectJSON[key]; + } + } // Append effect's properties root["name"] = add_property_json("Tracker", 0.0, "string", "", NULL, -1, -1, true, requested_frame); From 32a217eda7c1452e724cc23905eb5f2adc5850d6 Mon Sep 17 00:00:00 2001 From: Brenno Date: Fri, 22 Jan 2021 19:28:16 -0300 Subject: [PATCH 24/84] Added support to attach clip to detected object (ObjectDetection) effect This feature let's the user attach a clip to an object detected by the Object Detection effect, in the same way it is done with the Tracker Effect. --- src/CVObjectDetection.cpp | 21 ++++-- src/CVObjectDetection.h | 10 ++- src/Timeline.cpp | 38 +++++++++++ src/Timeline.h | 2 + src/TrackedObjectBBox.cpp | 2 +- src/TrackedObjectBBox.h | 2 +- src/TrackedObjectBase.h | 5 +- src/effects/ObjectDetection.cpp | 80 ++++++++++++++++++----- src/effects/ObjectDetection.h | 12 +++- src/protobuf_messages/objdetectdata.proto | 1 + src/sort_filter/sort.hpp | 2 +- 11 files changed, 148 insertions(+), 27 deletions(-) diff --git a/src/CVObjectDetection.cpp b/src/CVObjectDetection.cpp index c391197a2..b262f8c51 100644 --- a/src/CVObjectDetection.cpp +++ b/src/CVObjectDetection.cpp @@ -101,7 +101,6 @@ void CVObjectDetection::detectObjectsClip(openshot::Clip &video, size_t _start, // Update progress processingController->SetProgress(uint(100*(frame_number-start)/(end-start))); - // std::cout<<"Frame: "< classIds; std::vector confidences; std::vector boxes; + std::vector objectIds; for (size_t i = 0; i < outs.size(); ++i) { @@ -176,13 +176,14 @@ void CVObjectDetection::postprocess(const cv::Size &frameDims, const std::vector sort.update(sortBoxes, frameId, sqrt(pow(frameDims.width,2) + pow(frameDims.height, 2)), confidences, classIds); // Clear data vectors - boxes.clear(); confidences.clear(); classIds.clear(); + boxes.clear(); confidences.clear(); classIds.clear(); objectIds.clear(); // Get SORT predicted boxes for(auto TBox : sort.frameTrackingResult){ if(TBox.frame == frameId){ boxes.push_back(TBox.box); confidences.push_back(TBox.confidence); classIds.push_back(TBox.classId); + objectIds.push_back(TBox.id); } } @@ -198,12 +199,14 @@ void CVObjectDetection::postprocess(const cv::Size &frameDims, const std::vector boxes.erase(boxes.begin() + j); classIds.erase(classIds.begin() + j); confidences.erase(confidences.begin() + j); + objectIds.erase(objectIds.begin() + j); break; } else{ boxes.erase(boxes.begin() + i); classIds.erase(classIds.begin() + i); confidences.erase(confidences.begin() + i); + objectIds.erase(objectIds.begin() + i); i = 0; break; } @@ -222,12 +225,14 @@ void CVObjectDetection::postprocess(const cv::Size &frameDims, const std::vector boxes.erase(boxes.begin() + j); classIds.erase(classIds.begin() + j); confidences.erase(confidences.begin() + j); + objectIds.erase(objectIds.begin() + j); break; } else{ boxes.erase(boxes.begin() + i); classIds.erase(classIds.begin() + i); confidences.erase(confidences.begin() + i); + objectIds.erase(objectIds.begin() + i); i = 0; break; } @@ -247,7 +252,7 @@ void CVObjectDetection::postprocess(const cv::Size &frameDims, const std::vector normalized_boxes.push_back(normalized_box); } - detectionsData[frameId] = CVDetectionData(classIds, confidences, normalized_boxes, frameId); + detectionsData[frameId] = CVDetectionData(classIds, confidences, normalized_boxes, frameId, objectIds); } // Compute IOU between 2 boxes @@ -355,6 +360,7 @@ void CVObjectDetection::AddFrameDataToProto(pb_objdetect::Frame* pbFrameData, CV box->set_h(dData.boxes.at(i).height); box->set_classid(dData.classIds.at(i)); box->set_confidence(dData.confidences.at(i)); + box->set_objectid(dData.objectIds.at(i)); } } @@ -457,7 +463,10 @@ bool CVObjectDetection::_LoadObjDetectdData(){ const google::protobuf::RepeatedPtrField &pBox = pbFrameData.bounding_box(); // Construct data vectors related to detections in the current frame - std::vector classIds; std::vector confidences; std::vector> boxes; + std::vector classIds; + std::vector confidences; + std::vector> boxes; + std::vector objectIds; for(int i = 0; i < pbFrameData.bounding_box_size(); i++){ // Get bounding box coordinates @@ -468,13 +477,15 @@ bool CVObjectDetection::_LoadObjDetectdData(){ // Get class Id (which will be assign to a class name) and prediction confidence int classId = pBox.Get(i).classid(); float confidence = pBox.Get(i).confidence(); + // Get object Id + int objectId = pBox.Get(i).objectid(); // Push back data into vectors boxes.push_back(box); classIds.push_back(classId); confidences.push_back(confidence); } // Assign data to object detector map - detectionsData[id] = CVDetectionData(classIds, confidences, boxes, id); + detectionsData[id] = CVDetectionData(classIds, confidences, boxes, id, objectIds); } // Show the time stamp from the last update in object detector data file diff --git a/src/CVObjectDetection.h b/src/CVObjectDetection.h index ae3dbf7d4..3ec802172 100644 --- a/src/CVObjectDetection.h +++ b/src/CVObjectDetection.h @@ -49,16 +49,24 @@ namespace openshot // Stores the detected object bounding boxes and its properties. struct CVDetectionData{ CVDetectionData(){} - CVDetectionData(std::vector _classIds, std::vector _confidences, std::vector> _boxes, size_t _frameId){ + CVDetectionData( + std::vector _classIds, + std::vector _confidences, + std::vector> _boxes, + size_t _frameId, + std::vector _objectIds) + { classIds = _classIds; confidences = _confidences; boxes = _boxes; frameId = _frameId; + objectIds = _objectIds; } size_t frameId; std::vector classIds; std::vector confidences; std::vector> boxes; + std::vector objectIds; }; /** diff --git a/src/Timeline.cpp b/src/Timeline.cpp index de69bcce8..05b9bead4 100644 --- a/src/Timeline.cpp +++ b/src/Timeline.cpp @@ -290,6 +290,44 @@ std::list Timeline::GetTrackedObjectsIds() const{ return trackedObjects_ids; } +std::string Timeline::GetTrackedObjectValues(std::string id) const { + + // Initialize the JSON object + Json::Value trackedObjectJson; + + // Search for the tracked object on the map + auto iterator = tracked_objects.find(id); + + if (iterator != tracked_objects.end()) + { + // Id found, Get the object pointer and cast it as a TrackedObjectBBox + std::shared_ptr trackedObject = std::static_pointer_cast(iterator->second); + + // Get the trackedObject values for it's first frame + auto boxes = trackedObject->BoxVec; + auto firstBox = boxes.begin()->second; + float x1 = firstBox.cx - (firstBox.width/2); + float y1 = firstBox.cy - (firstBox.height/2); + float x2 = firstBox.cx + (firstBox.width/2); + float y2 = firstBox.cy + (firstBox.height/2); + + trackedObjectJson["x1"] = x1; + trackedObjectJson["y1"] = y1; + trackedObjectJson["x2"] = x2; + trackedObjectJson["y2"] = y2; + + } + else { + // Id not found, return all 0 values + trackedObjectJson["x1"] = 0; + trackedObjectJson["y1"] = 0; + trackedObjectJson["x2"] = 0; + trackedObjectJson["y2"] = 0; + } + + return trackedObjectJson.toStyledString(); +} + // Add an openshot::Clip to the timeline void Timeline::AddClip(Clip* clip) { diff --git a/src/Timeline.h b/src/Timeline.h index 69cebc8ab..e9b201b04 100644 --- a/src/Timeline.h +++ b/src/Timeline.h @@ -250,6 +250,8 @@ namespace openshot { std::shared_ptr GetTrackedObject(std::string id) const; /// Return the ID's of the tracked objects as a list of strings std::list GetTrackedObjectsIds() const; + /// Return the first trackedObject's properties as a JSON string + std::string GetTrackedObjectValues(std::string id) const; /// @brief Add an openshot::Clip to the timeline /// @param clip Add an openshot::Clip to the timeline. A clip can contain any type of Reader. diff --git a/src/TrackedObjectBBox.cpp b/src/TrackedObjectBBox.cpp index 40ba5e21c..75f960942 100644 --- a/src/TrackedObjectBBox.cpp +++ b/src/TrackedObjectBBox.cpp @@ -230,7 +230,7 @@ bool TrackedObjectBBox::LoadBoxData(std::string inputFilePath) // Read the existing tracker message. fstream input(inputFilePath, ios::in | ios::binary); - //Check if it was able to read the protobuf data + // Check if it was able to read the protobuf data if (!bboxMessage.ParseFromIstream(&input)) { cerr << "Failed to parse protobuf message." << endl; diff --git a/src/TrackedObjectBBox.h b/src/TrackedObjectBBox.h index 4a5a34ada..a8deadf6b 100644 --- a/src/TrackedObjectBBox.h +++ b/src/TrackedObjectBBox.h @@ -174,7 +174,7 @@ namespace openshot TrackedObjectBBox(); /// Add a BBox to the BoxVec map - void AddBox(int64_t _frame_num, float _cx, float _cy, float _width, float _height, float _angle); + void AddBox(int64_t _frame_num, float _cx, float _cy, float _width, float _height, float _angle) override; /// Update object's BaseFps void SetBaseFPS(Fraction fps); diff --git a/src/TrackedObjectBase.h b/src/TrackedObjectBase.h index 683b0b3f1..0a336cf2b 100644 --- a/src/TrackedObjectBase.h +++ b/src/TrackedObjectBase.h @@ -83,7 +83,10 @@ namespace openshot { virtual std::map GetBoxValues(int64_t frame_number) const { std::map ret; return ret; }; /// Return the main properties of the tracked object's parent clip virtual std::map GetParentClipProperties(int64_t frame_number) const { std::map ret; return ret; } - + /// Add a bounding box to the tracked object's BoxVec map + virtual void AddBox(int64_t _frame_num, float _cx, float _cy, float _width, float _height, float _angle) { return; }; + + /// Get and Set JSON methods virtual std::string Json() const = 0; ///< Generate JSON string of this object virtual Json::Value JsonValue() const = 0; ///< Generate Json::Value for this object diff --git a/src/effects/ObjectDetection.cpp b/src/effects/ObjectDetection.cpp index 929c9039a..8036e9fc5 100644 --- a/src/effects/ObjectDetection.cpp +++ b/src/effects/ObjectDetection.cpp @@ -28,12 +28,15 @@ * along with OpenShot Library. If not, see . */ +#include + #include "effects/ObjectDetection.h" #include "effects/Tracker.h" using namespace std; using namespace openshot; + /// Blank constructor, useful when using Json to load the effect properties ObjectDetection::ObjectDetection(std::string clipObDetectDataPath) { @@ -64,7 +67,7 @@ void ObjectDetection::init_effect_details() info.description = "Detect objects through the video."; info.has_audio = false; info.has_video = true; - info.has_tracked_object = false; + info.has_tracked_object = true; } // This method is required for all derived classes of EffectBase, and returns a @@ -92,7 +95,7 @@ std::shared_ptr ObjectDetection::GetFrame(std::shared_ptr frame, i (int)(bb_nrml.width*fw), (int)(bb_nrml.height*fh)); drawPred(detections.classIds.at(i), detections.confidences.at(i), - box, cv_image); + box, cv_image, detections.objectIds.at(i)); } } @@ -103,7 +106,7 @@ std::shared_ptr ObjectDetection::GetFrame(std::shared_ptr frame, i return frame; } -void ObjectDetection::drawPred(int classId, float conf, cv::Rect2d box, cv::Mat& frame) +void ObjectDetection::drawPred(int classId, float conf, cv::Rect2d box, cv::Mat& frame, int objectNumber) { //Draw a rectangle displaying the bounding box @@ -133,29 +136,32 @@ bool ObjectDetection::LoadObjDetectdData(std::string inputFilePath){ // Create tracker message pb_objdetect::ObjDetect objMessage; - { - // Read the existing tracker message. - fstream input(inputFilePath, ios::in | ios::binary); - if (!objMessage.ParseFromIstream(&input)) { - cerr << "Failed to parse protobuf message." << endl; - return false; - } + + // Read the existing tracker message. + fstream input(inputFilePath, ios::in | ios::binary); + if (!objMessage.ParseFromIstream(&input)) { + cerr << "Failed to parse protobuf message." << endl; + return false; } + - // Make sure classNames and detectionsData are empty + // Make sure classNames, detectionsData and trackedObjects are empty classNames.clear(); detectionsData.clear(); + trackedObjects.clear(); // Seed to generate same random numbers std::srand(1); // Get all classes names and assign a color to them - for(int i = 0; i < objMessage.classnames_size(); i++){ + for(int i = 0; i < objMessage.classnames_size(); i++) + { classNames.push_back(objMessage.classnames(i)); classesColor.push_back(cv::Scalar(std::rand()%205 + 50, std::rand()%205 + 50, std::rand()%205 + 50)); } // Iterate over all frames of the saved message - for (size_t i = 0; i < objMessage.frame_size(); i++) { + for (size_t i = 0; i < objMessage.frame_size(); i++) + { // Create protobuf message reader const pb_objdetect::Frame& pbFrameData = objMessage.frame(i); @@ -169,8 +175,11 @@ bool ObjectDetection::LoadObjDetectdData(std::string inputFilePath){ std::vector classIds; std::vector confidences; std::vector> boxes; + std::vector objectIds; - for(int i = 0; i < pbFrameData.bounding_box_size(); i++){ + // Iterate through the detected objects + for(int i = 0; i < pbFrameData.bounding_box_size(); i++) + { // Get bounding box coordinates float x = pBox.Get(i).x(); float y = pBox.Get(i).y(); @@ -180,6 +189,26 @@ bool ObjectDetection::LoadObjDetectdData(std::string inputFilePath){ int classId = pBox.Get(i).classid(); // Get prediction confidence float confidence = pBox.Get(i).confidence(); + + // Get the object Id + int objectId = pBox.Get(i).objectid(); + + // Search for the object id on trackedObjects map + auto trackedObject = trackedObjects.find(objectId); + // Check if object already exists on the map + if (trackedObject != trackedObjects.end()) + { + // Add a new BBox to it + trackedObject->second->AddBox(id, x+(w/2), y+(h/2), w, h, 0.0); + } + else + { + // There is no tracked object with that id, so insert a new one + TrackedObjectBBox trackedObj; + trackedObj.AddBox(id, x+(w/2), y+(h/2), w, h, 0.0); + std::shared_ptr trackedObjPtr = std::make_shared(trackedObj); + trackedObjects.insert({objectId, trackedObjPtr}); + } // Create OpenCV rectangle with the bouding box info cv::Rect_ box(x, y, w, h); @@ -188,10 +217,11 @@ bool ObjectDetection::LoadObjDetectdData(std::string inputFilePath){ boxes.push_back(box); classIds.push_back(classId); confidences.push_back(confidence); + objectIds.push_back(objectId); } // Assign data to object detector map - detectionsData[id] = DetectionData(classIds, confidences, boxes, id); + detectionsData[id] = DetectionData(classIds, confidences, boxes, id, objectIds); } // Delete all global objects allocated by libprotobuf. @@ -226,6 +256,12 @@ Json::Value ObjectDetection::JsonValue() const { Json::Value root = EffectBase::JsonValue(); // get parent properties root["type"] = info.class_name; root["protobuf_data_path"] = protobuf_data_path; + + // Add trackedObjects IDs to JSON + for (auto const& trackedObject : trackedObjects){ + // Save the trackedObject Id on root + root["box_id"+to_string(trackedObject.first)] = trackedObject.second->Id(); + } // return JsonValue return root; @@ -262,6 +298,12 @@ void ObjectDetection::SetJsonValue(const Json::Value root) { protobuf_data_path = ""; } } + + for (auto const& trackedObject : trackedObjects){ + Json::Value trackedObjectJSON; + trackedObjectJSON["box_id"] = root["box_id"+to_string(trackedObject.first)]; + trackedObject.second->SetJsonValue(trackedObjectJSON); + } } // Get all properties for a specific frame @@ -269,6 +311,14 @@ std::string ObjectDetection::PropertiesJSON(int64_t requested_frame) const { // Generate JSON properties list Json::Value root; + + // Add trackedObjects IDs to JSON + for (auto const& trackedObject : trackedObjects){ + // 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["id"] = add_property_json("ID", 0.0, "string", Id(), NULL, -1, -1, true, requested_frame); root["position"] = add_property_json("Position", Position(), "float", "", NULL, 0, 1000 * 60 * 30, false, requested_frame); root["layer"] = add_property_json("Track", Layer(), "int", "", NULL, 0, 20, false, requested_frame); diff --git a/src/effects/ObjectDetection.h b/src/effects/ObjectDetection.h index 31518c865..64df91c3b 100644 --- a/src/effects/ObjectDetection.h +++ b/src/effects/ObjectDetection.h @@ -45,16 +45,24 @@ // Struct that stores the detected bounding boxes for all the clip frames struct DetectionData{ DetectionData(){} - DetectionData(std::vector _classIds, std::vector _confidences, std::vector> _boxes, size_t _frameId){ + DetectionData( + std::vector _classIds, + std::vector _confidences, + std::vector> _boxes, + size_t _frameId, + std::vector _objectIds) + { classIds = _classIds; confidences = _confidences; boxes = _boxes; frameId = _frameId; + objectIds = _objectIds; } size_t frameId; std::vector classIds; std::vector confidences; std::vector> boxes; + std::vector objectIds; }; namespace openshot @@ -74,7 +82,7 @@ namespace openshot /// Init effect settings void init_effect_details(); - void drawPred(int classId, float conf, cv::Rect2d box, cv::Mat& frame); + void drawPred(int classId, float conf, cv::Rect2d box, cv::Mat& frame, int objectNumber); public: diff --git a/src/protobuf_messages/objdetectdata.proto b/src/protobuf_messages/objdetectdata.proto index 49ad94afa..272ffb4f6 100644 --- a/src/protobuf_messages/objdetectdata.proto +++ b/src/protobuf_messages/objdetectdata.proto @@ -17,6 +17,7 @@ message Frame { float h = 4; int32 classId = 5; float confidence = 6; + int32 objectId = 7; } repeated Box bounding_box = 2; diff --git a/src/sort_filter/sort.hpp b/src/sort_filter/sort.hpp index 295b9d567..086af1f10 100644 --- a/src/sort_filter/sort.hpp +++ b/src/sort_filter/sort.hpp @@ -39,7 +39,7 @@ class SortTracker double GetCentroidsDistance(cv::Rect_ bb_test, cv::Rect_ bb_gt); std::vector trackers; - double max_centroid_dist_norm = 0.15; + double max_centroid_dist_norm = 0.05; std::vector> predictedBoxes; std::vector> centroid_dist_matrix; From 5eb9f60eeabb74353739b08690d9db48708e6210 Mon Sep 17 00:00:00 2001 From: Brenno Date: Fri, 22 Jan 2021 19:47:36 -0300 Subject: [PATCH 25/84] Added support to update the detected bounding-boxes keyframes Added support to show transform handlers for the bounding-boxes (Tracked Objects) detected by the Object Detection effect and update their Keyframes. --- src/Timeline.cpp | 3 ++ src/effects/ObjectDetection.cpp | 62 ++++++++++++++++++++++++++------- src/effects/Tracker.cpp | 35 +++++++++++++++---- 3 files changed, 81 insertions(+), 19 deletions(-) diff --git a/src/Timeline.cpp b/src/Timeline.cpp index 05b9bead4..dd2c1702e 100644 --- a/src/Timeline.cpp +++ b/src/Timeline.cpp @@ -310,11 +310,13 @@ std::string Timeline::GetTrackedObjectValues(std::string id) const { float y1 = firstBox.cy - (firstBox.height/2); float x2 = firstBox.cx + (firstBox.width/2); float y2 = firstBox.cy + (firstBox.height/2); + float r = firstBox.angle; trackedObjectJson["x1"] = x1; trackedObjectJson["y1"] = y1; trackedObjectJson["x2"] = x2; trackedObjectJson["y2"] = y2; + trackedObjectJson["r"] = r; } else { @@ -323,6 +325,7 @@ std::string Timeline::GetTrackedObjectValues(std::string id) const { trackedObjectJson["y1"] = 0; trackedObjectJson["x2"] = 0; trackedObjectJson["y2"] = 0; + trackedObjectJson["r"] = 0; } return trackedObjectJson.toStyledString(); diff --git a/src/effects/ObjectDetection.cpp b/src/effects/ObjectDetection.cpp index 8036e9fc5..f95f559b2 100644 --- a/src/effects/ObjectDetection.cpp +++ b/src/effects/ObjectDetection.cpp @@ -89,13 +89,30 @@ std::shared_ptr ObjectDetection::GetFrame(std::shared_ptr frame, i DetectionData detections = detectionsData[frame_number]; for(int i = 0; i bb_nrml = detections.boxes.at(i); - cv::Rect2d box((int)(bb_nrml.x*fw), - (int)(bb_nrml.y*fh), - (int)(bb_nrml.width*fw), - (int)(bb_nrml.height*fh)); - drawPred(detections.classIds.at(i), detections.confidences.at(i), - box, cv_image, detections.objectIds.at(i)); + + // Get the object id + int objectId = detections.objectIds.at(i); + + // Search for the object in the trackedObjects map + auto trackedObject_it = trackedObjects.find(objectId); + + // Cast the object as TrackedObjectBBox + std::shared_ptr trackedObject = std::static_pointer_cast(trackedObject_it->second); + + // Check if the tracked object has data for this frame + if (trackedObject->Contains(frame_number)){ + + // Get the bounding-box of given frame + BBox trackedBox = trackedObject->GetBox(frame_number); + cv::Rect2d box( + (int)( (trackedBox.cx-trackedBox.width/2)*fw), + (int)( (trackedBox.cy-trackedBox.height/2)*fh), + (int)( trackedBox.width*fw), + (int)( trackedBox.height*fh) + ); + drawPred(detections.classIds.at(i), detections.confidences.at(i), + box, cv_image, detections.objectIds.at(i)); + } } } @@ -259,8 +276,14 @@ Json::Value ObjectDetection::JsonValue() const { // Add trackedObjects IDs to JSON for (auto const& trackedObject : trackedObjects){ - // Save the trackedObject Id on root - root["box_id"+to_string(trackedObject.first)] = trackedObject.second->Id(); + Json::Value trackedObjectJSON = trackedObject.second->JsonValue(); + // Save the trackedObject JSON on root + root["box_id-"+to_string(trackedObject.first)] = trackedObjectJSON["box_id"]; + 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"]; } // return JsonValue @@ -301,8 +324,14 @@ void ObjectDetection::SetJsonValue(const Json::Value root) { for (auto const& trackedObject : trackedObjects){ Json::Value trackedObjectJSON; - trackedObjectJSON["box_id"] = root["box_id"+to_string(trackedObject.first)]; - trackedObject.second->SetJsonValue(trackedObjectJSON); + trackedObjectJSON["box_id"] = root["box_id-"+to_string(trackedObject.first)]; + trackedObjectJSON["delta_x"] = root["delta_x-"+to_string(trackedObject.first)]; + trackedObjectJSON["delta_y"] = root["delta_y-"+to_string(trackedObject.first)]; + trackedObjectJSON["scale_x"] = root["scale_x-"+to_string(trackedObject.first)]; + trackedObjectJSON["scale_y"] = root["scale_y-"+to_string(trackedObject.first)]; + trackedObjectJSON["rotation"] = root["rotation-"+to_string(trackedObject.first)]; + if (!trackedObjectJSON.isNull()) + trackedObject.second->SetJsonValue(trackedObjectJSON); } } @@ -316,7 +345,16 @@ std::string ObjectDetection::PropertiesJSON(int64_t requested_frame) const { for (auto const& trackedObject : trackedObjects){ // 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["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["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 260909bf9..5f43cbeb5 100644 --- a/src/effects/Tracker.cpp +++ b/src/effects/Tracker.cpp @@ -151,8 +151,15 @@ Json::Value Tracker::JsonValue() const { trackedDataJSON = trackedData->JsonValue(); // Save the trackedData properties on root - for (const auto& key : trackedDataJSON.getMemberNames()){ - root[key] = trackedDataJSON[key]; + for (auto const& trackedObject : trackedObjects){ + Json::Value trackedObjectJSON = trackedObject.second->JsonValue(); + // Save the trackedObject JSON on root + root["box_id-"+to_string(trackedObject.first)] = trackedObjectJSON["box_id"]; + 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"]; } // return JsonValue @@ -213,7 +220,15 @@ void Tracker::SetJsonValue(const Json::Value root) { } for (auto const& trackedObject : trackedObjects){ - trackedObject.second->SetJsonValue(root); + Json::Value trackedObjectJSON; + trackedObjectJSON["box_id"] = root["box_id-"+to_string(trackedObject.first)]; + trackedObjectJSON["delta_x"] = root["delta_x-"+to_string(trackedObject.first)]; + trackedObjectJSON["delta_y"] = root["delta_y-"+to_string(trackedObject.first)]; + trackedObjectJSON["scale_x"] = root["scale_x-"+to_string(trackedObject.first)]; + trackedObjectJSON["scale_y"] = root["scale_y-"+to_string(trackedObject.first)]; + trackedObjectJSON["rotation"] = root["rotation-"+to_string(trackedObject.first)]; + if (!trackedObjectJSON.isNull()) + trackedObject.second->SetJsonValue(trackedObjectJSON); } return; @@ -229,10 +244,16 @@ std::string Tracker::PropertiesJSON(int64_t requested_frame) const { // Add trackedObjects properties to JSON for (auto const& trackedObject : trackedObjects){ Json::Value trackedObjectJSON = trackedObject.second->PropertiesJSON(requested_frame); - // Save the trackedData properties on root - for (const auto& key : trackedObjectJSON.getMemberNames()){ - root[key] = trackedObjectJSON[key]; - } + 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"]; } // Append effect's properties From d6e0acb0cbde41cfda53ba7e74a7aa1ed478d256 Mon Sep 17 00:00:00 2001 From: Brenno Date: Fri, 22 Jan 2021 20:03:05 -0300 Subject: [PATCH 26/84] 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 b0d5464d3..a5576aadf 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 0c46643e5..7d2ba0a3e 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 75f960942..5ce953971 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 a8deadf6b..b670b3a51 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 f95f559b2..621070132 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 5f43cbeb5..ec7553929 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 cab850620..3fdb220c4 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)); From ce2c4e01985ed2a5be9188ac40c931c22ba93651 Mon Sep 17 00:00:00 2001 From: Brenno Date: Fri, 22 Jan 2021 20:14:25 -0300 Subject: [PATCH 27/84] Updated documentation --- src/KeyFrameBase.h | 23 ++++++++---------- src/TrackedObjectBBox.cpp | 13 +++++++---- src/TrackedObjectBBox.h | 49 ++++++++++++++++++++------------------- src/TrackedObjectBase.cpp | 3 +++ src/TrackedObjectBase.h | 21 +++++++---------- src/effects/Stabilizer.h | 2 +- src/effects/Tracker.h | 6 +++-- 7 files changed, 60 insertions(+), 57 deletions(-) diff --git a/src/KeyFrameBase.h b/src/KeyFrameBase.h index 6a55ea5ef..14b94c198 100644 --- a/src/KeyFrameBase.h +++ b/src/KeyFrameBase.h @@ -45,16 +45,6 @@ namespace openshot { - /** - * @brief This abstract class is the base class of all Keyframes. - * - * A Keyframe is a collection of Point instances, which is used to vary a number or property over time. - * - * Keyframes are used to animate and interpolate values of properties over time. For example, a single property - * can use a Keyframe instead of a constant value. Assume you want to slide an image (from left to right) over - * a video. You can create a Keyframe which will adjust the X value of the image over 100 frames (or however many - * frames the animation needs to last) from the value of 0 to 640. - */ /// Check if the X coordinate of a given Point is lower than a given value bool IsPointBeforeX(Point const & p, double const x); @@ -68,9 +58,16 @@ namespace openshot { /// Interpolate two points using the right Point's interpolation method double InterpolateBetween(Point const & left, Point const & right, double target, double allowed_error); - // template - // int64_t SearchBetweenPoints(Point const & left, Point const & right, int64_t const current, Check check); - + /** + * @brief This abstract class is the base class of all Keyframes. + * + * A Keyframe is a collection of Point instances, which is used to vary a number or property over time. + * + * Keyframes are used to animate and interpolate values of properties over time. For example, a single property + * can use a Keyframe instead of a constant value. Assume you want to slide an image (from left to right) over + * a video. You can create a Keyframe which will adjust the X value of the image over 100 frames (or however many + * frames the animation needs to last) from the value of 0 to 640. + */ class KeyframeBase{ public: diff --git a/src/TrackedObjectBBox.cpp b/src/TrackedObjectBBox.cpp index 5ce953971..ed8e152a8 100644 --- a/src/TrackedObjectBBox.cpp +++ b/src/TrackedObjectBBox.cpp @@ -1,6 +1,6 @@ /** * @file - * @brief Source file for the Keyframe class + * @brief Source file for the TrackedObjectBBox class * @author Jonathan Thomas * * @ref License @@ -350,7 +350,7 @@ void TrackedObjectBBox::SetJson(const std::string value) void TrackedObjectBBox::SetJsonValue(const Json::Value root) { - // Set the Id + // Set the Id by the given JSON object if (!root["box_id"].isNull()) Id(root["box_id"].asString()); @@ -370,6 +370,7 @@ void TrackedObjectBBox::SetJsonValue(const Json::Value root) this->ScalePoints(scale); } + // Set the protobuf data path by the given JSON object if (!root["protobuf_data_path"].isNull()) protobufDataPath = root["protobuf_data_path"].asString(); @@ -396,7 +397,7 @@ Json::Value TrackedObjectBBox::PropertiesJSON(int64_t requested_frame) const BBox box = GetBox(requested_frame); - // Id + // 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 a boolean property to inform if the object has data for the requested frame @@ -457,7 +458,7 @@ Json::Value TrackedObjectBBox::add_property_json(std::string name, float value, return prop; } -// Return the bounding box properties and it's keyframes indexed by their names +// Return a map that contains the bounding box properties and it's keyframes indexed by their names std::map TrackedObjectBBox::GetBoxValues(int64_t frame_number) const { // Create the map @@ -484,7 +485,7 @@ std::map TrackedObjectBBox::GetBoxValues(int64_t frame_numbe return boxValues; } -// Return properties of this object's parent clip +// Return a map that contains the properties of this object's parent clip std::map TrackedObjectBBox::GetParentClipProperties(int64_t frame_number) const { // Get the parent clip of this object as a Clip pointer @@ -502,8 +503,10 @@ std::map TrackedObjectBBox::GetParentClipProperties(int64_t float parentClip_scale_y = parentClip->scale_y.GetValue(parentClip_frame_number); float parentClip_rotation = parentClip->rotation.GetValue(parentClip_frame_number); + // Initialize the parent clip properties map std::map parentClipProperties; + // Set the map properties parentClipProperties["frame_number"] = parentClip_frame_number; parentClipProperties["timeline_frame_number"] = frame_number; parentClipProperties["location_x"] = parentClip_location_x; diff --git a/src/TrackedObjectBBox.h b/src/TrackedObjectBBox.h index b670b3a51..182853a46 100644 --- a/src/TrackedObjectBBox.h +++ b/src/TrackedObjectBBox.h @@ -52,13 +52,15 @@ using google::protobuf::util::TimeUtil; namespace openshot { /** - * @brief This struct holds the information of a bounding-box: a rectangular shape that enclosures an object or a - * desired set of pixels in a digital image. - * - * The bounding-box structure holds four floating-point properties: the x and y coordinates of the rectangle's - * top left corner (x1, y1), the rectangle's width and the rectangle's height. - */ - + * @brief This struct holds the information of a bounding-box. + * + * A bounding-box is a rectangular shape that enclosures an + * object or a desired set of pixels in a digital image. + * + * The bounding-box structure holds five floating-point properties: + * the x and y coordinates of the rectangle's center point (cx, cy), + * the rectangle's width, height and rotation. + */ struct BBox { float cx = -1; ///< x-coordinate of the bounding box center @@ -68,10 +70,7 @@ namespace openshot float angle = -1; ///< bounding box rotation angle [degrees] /// Blank constructor - BBox() - { - return; - } + BBox() {} /// Default constructor, which takes the bounding box top-left corner coordinates, width and height. /// @param _cx X-coordinate of the bounding box center @@ -144,16 +143,17 @@ namespace openshot }; /** - * @brief This class holds the information of a bounding-box (mapped by time) over the frames that contain - * the object enclosured by it. - * - * The bounding-box displacement in X and Y directions and it's width and height variation over the frames - * are set as openshot::Keyframe objects + * @brief This class contains the properties of a tracked object + * and functions to manipulate it. * - * The bounding-box information over the clip's frames are saved into a protobuf file and loaded into an - * object of this class. - */ - + * The bounding-box displacement in X and Y directions, it's width, + * height and rotation variation over the frames are set as + * openshot::Keyframe objects. + * + * The bounding-box information over the clip's frames are + * saved into a protobuf file and loaded into an + * object of this class. + */ class TrackedObjectBBox : public TrackedObjectBase { private: @@ -168,7 +168,7 @@ namespace openshot Keyframe scale_x; ///< X-direction scale Keyframe Keyframe scale_y; ///< Y-direction scale Keyframe Keyframe rotation; ///< Rotation Keyframe - std::string protobufDataPath; ///< Path to the protobuf file that holds the bbox points across the frames + std::string protobufDataPath; ///< Path to the protobuf file that holds the bounding box points across the frames /// Default Constructor TrackedObjectBBox(); @@ -197,11 +197,12 @@ namespace openshot void RemoveBox(int64_t frame_number); /// Return a bounding-box from BoxVec with it's properties adjusted by the Keyframes + BBox GetBox(int64_t frame_number); + /// Const-cast of the GetBox function, so that it can be called inside other cont function BBox GetBox(int64_t frame_number) const { return const_cast(this)->GetBox(frame_number); } - BBox GetBox(int64_t frame_number); /// Load the bounding-boxes information from the protobuf file bool LoadBoxData(std::string inputFilePath); @@ -228,9 +229,9 @@ namespace openshot // Generate JSON for a property 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; - /// Return the bounding box properties and it's keyframes indexed by their names + /// Return a map that contains the bounding box properties and it's keyframes indexed by their names std::map GetBoxValues(int64_t frame_number) const override; - /// Return properties of this object's parent clip + /// Return a map that contains the properties of this object's parent clip std::map GetParentClipProperties(int64_t frame_number) const override; }; diff --git a/src/TrackedObjectBase.cpp b/src/TrackedObjectBase.cpp index 5d43d7fa5..157f55b39 100644 --- a/src/TrackedObjectBase.cpp +++ b/src/TrackedObjectBase.cpp @@ -36,10 +36,13 @@ namespace openshot{ + // Blank constructor TrackedObjectBase::TrackedObjectBase(){ + // Initializes the id as "None" id = "None"; } + // Default constructor TrackedObjectBase::TrackedObjectBase(std::string _id){ Id(_id); } diff --git a/src/TrackedObjectBase.h b/src/TrackedObjectBase.h index 0a336cf2b..52499ed04 100644 --- a/src/TrackedObjectBase.h +++ b/src/TrackedObjectBase.h @@ -47,16 +47,12 @@ namespace openshot { /** - * @brief This abstract class is the base class of all Keyframes. + * @brief This abstract class is the base class of all Tracked Objects. * - * A Keyframe is a collection of Point instances, which is used to vary a number or property over time. - * - * Keyframes are used to animate and interpolate values of properties over time. For example, a single property - * can use a Keyframe instead of a constant value. Assume you want to slide an image (from left to right) over - * a video. You can create a Keyframe which will adjust the X value of the image over 100 frames (or however many - * frames the animation needs to last) from the value of 0 to 640. + * A Tracked Object is an object or a desired set of pixels in a digital image + * which properties (such as position, width and height) can be detected and + * predicted along the frames of a clip. */ - class TrackedObjectBase { private: std::string id; @@ -70,18 +66,19 @@ namespace openshot { /// Default constructor TrackedObjectBase(std::string _id); - /// Get and set the id of this object + /// Get the id of this object std::string Id() const { return id; } + /// Set the id of this object void Id(std::string _id) { id = _id; } /// Get and set the parentClip of this object ClipBase* ParentClip() const { return parentClip; } void ParentClip(ClipBase* clip) { parentClip = clip; } - /// Scale a property + /// Scale an object's property virtual void ScalePoints(double scale) { return; }; - /// Return the main properties of a TrackedObjectBBox instance using a pointer to this base class + /// Return the main properties of a TrackedObjectBBox instance - such as position, size and rotation virtual std::map GetBoxValues(int64_t frame_number) const { std::map ret; return ret; }; - /// Return the main properties of the tracked object's parent clip + /// Return the main properties of the tracked object's parent clip - such as position, size and rotation virtual std::map GetParentClipProperties(int64_t frame_number) const { std::map ret; return ret; } /// Add a bounding box to the tracked object's BoxVec map virtual void AddBox(int64_t _frame_num, float _cx, float _cy, float _width, float _height, float _angle) { return; }; diff --git a/src/effects/Stabilizer.h b/src/effects/Stabilizer.h index 0d24b6c0c..4217958ec 100644 --- a/src/effects/Stabilizer.h +++ b/src/effects/Stabilizer.h @@ -76,7 +76,7 @@ namespace openshot { /** - * @brief This class stabilizes video clip to remove undesired shaking and jitter. + * @brief This class stabilizes a video clip to remove undesired shaking and jitter. * * Adding stabilization is useful to increase video quality overall, since it removes * from subtle to harsh unexpected camera movements. diff --git a/src/effects/Tracker.h b/src/effects/Tracker.h index 2cb1faf5a..e5cca0477 100644 --- a/src/effects/Tracker.h +++ b/src/effects/Tracker.h @@ -48,9 +48,11 @@ using namespace std; namespace openshot { /** - * @brief This class track a given object through the clip and, when called, draws a box surrounding it. + * @brief This class tracks a given object through the clip, draws a box around it and allow + * the user to attach another clip (image or video) to the tracked object. * - * Tracking is useful to better visualize and follow the movement of an object through video. + * Tracking is useful to better visualize, follow the movement of an object through video + * and attach an image or video to it. */ class Tracker : public EffectBase { From 4a28654bcce6e77c4bf0c65737d7a71a152d111b Mon Sep 17 00:00:00 2001 From: Brenno Date: Wed, 27 Jan 2021 16:52:15 -0300 Subject: [PATCH 28/84] Added support to show the transform handler for the selected object When using the ObjectDetection effect, it's now possible to select one detected object and update it's properties through it's transform handler. --- src/Timeline.cpp | 46 +++++++++----- src/Timeline.h | 4 +- src/effects/ObjectDetection.cpp | 102 +++++++++++++++++++++----------- src/effects/ObjectDetection.h | 3 + 4 files changed, 102 insertions(+), 53 deletions(-) diff --git a/src/Timeline.cpp b/src/Timeline.cpp index dd2c1702e..47b52bdf6 100644 --- a/src/Timeline.cpp +++ b/src/Timeline.cpp @@ -290,7 +290,8 @@ std::list Timeline::GetTrackedObjectsIds() const{ return trackedObjects_ids; } -std::string Timeline::GetTrackedObjectValues(std::string id) const { +// Return the trackedObject's properties as a JSON string +std::string Timeline::GetTrackedObjectValues(std::string id, int64_t frame_number) const { // Initialize the JSON object Json::Value trackedObjectJson; @@ -304,19 +305,34 @@ std::string Timeline::GetTrackedObjectValues(std::string id) const { std::shared_ptr trackedObject = std::static_pointer_cast(iterator->second); // Get the trackedObject values for it's first frame - auto boxes = trackedObject->BoxVec; - auto firstBox = boxes.begin()->second; - float x1 = firstBox.cx - (firstBox.width/2); - float y1 = firstBox.cy - (firstBox.height/2); - float x2 = firstBox.cx + (firstBox.width/2); - float y2 = firstBox.cy + (firstBox.height/2); - float r = firstBox.angle; - - trackedObjectJson["x1"] = x1; - trackedObjectJson["y1"] = y1; - trackedObjectJson["x2"] = x2; - trackedObjectJson["y2"] = y2; - trackedObjectJson["r"] = r; + if (trackedObject->ExactlyContains(frame_number)){ + BBox box = trackedObject->GetBox(frame_number); + float x1 = box.cx - (box.width/2); + float y1 = box.cy - (box.height/2); + float x2 = box.cx + (box.width/2); + float y2 = box.cy + (box.height/2); + float rotation = box.angle; + + trackedObjectJson["x1"] = x1; + trackedObjectJson["y1"] = y1; + trackedObjectJson["x2"] = x2; + trackedObjectJson["y2"] = y2; + trackedObjectJson["rotation"] = rotation; + + } else { + BBox box = trackedObject->BoxVec.begin()->second; + float x1 = box.cx - (box.width/2); + float y1 = box.cy - (box.height/2); + float x2 = box.cx + (box.width/2); + float y2 = box.cy + (box.height/2); + float rotation = box.angle; + + trackedObjectJson["x1"] = x1; + trackedObjectJson["y1"] = y1; + trackedObjectJson["x2"] = x2; + trackedObjectJson["y2"] = y2; + trackedObjectJson["rotation"] = rotation; + } } else { @@ -325,7 +341,7 @@ std::string Timeline::GetTrackedObjectValues(std::string id) const { trackedObjectJson["y1"] = 0; trackedObjectJson["x2"] = 0; trackedObjectJson["y2"] = 0; - trackedObjectJson["r"] = 0; + trackedObjectJson["rotation"] = 0; } return trackedObjectJson.toStyledString(); diff --git a/src/Timeline.h b/src/Timeline.h index e9b201b04..b17d164e1 100644 --- a/src/Timeline.h +++ b/src/Timeline.h @@ -250,8 +250,8 @@ namespace openshot { std::shared_ptr GetTrackedObject(std::string id) const; /// Return the ID's of the tracked objects as a list of strings std::list GetTrackedObjectsIds() const; - /// Return the first trackedObject's properties as a JSON string - std::string GetTrackedObjectValues(std::string id) const; + /// Return the trackedObject's properties as a JSON string + std::string GetTrackedObjectValues(std::string id, int64_t frame_number) const; /// @brief Add an openshot::Clip to the timeline /// @param clip Add an openshot::Clip to the timeline. A clip can contain any type of Reader. diff --git a/src/effects/ObjectDetection.cpp b/src/effects/ObjectDetection.cpp index 621070132..a9ee04114 100644 --- a/src/effects/ObjectDetection.cpp +++ b/src/effects/ObjectDetection.cpp @@ -45,6 +45,9 @@ ObjectDetection::ObjectDetection(std::string clipObDetectDataPath) // Tries to load the tracker data from protobuf LoadObjDetectdData(clipObDetectDataPath); + + // Initialize the selected object index as the first object index + selectedObjectIndex = trackedObjects.begin()->first; } // Default constructor @@ -53,6 +56,8 @@ ObjectDetection::ObjectDetection() // Init effect properties init_effect_details(); + // Initialize the selected object index as the first object index + selectedObjectIndex = trackedObjects.begin()->first; } // Init effect settings @@ -273,18 +278,23 @@ Json::Value ObjectDetection::JsonValue() const { Json::Value root = EffectBase::JsonValue(); // get parent properties root["type"] = info.class_name; root["protobuf_data_path"] = protobuf_data_path; + root["selected_object_index"] = selectedObjectIndex; - // Add trackedObjects IDs to JSON - for (auto const& trackedObject : trackedObjects){ - Json::Value trackedObjectJSON = trackedObject.second->JsonValue(); - // Save the trackedObject JSON on root + for (auto const& trackedObject : trackedObjects){ + Json::Value trackedObjectJSON = trackedObject.second->JsonValue(); root["box_id-"+to_string(trackedObject.first)] = trackedObjectJSON["box_id"]; - 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"]; - } + } + + // Add the selected object Json to root + auto selectedObject = trackedObjects.at(selectedObjectIndex); + if (selectedObject){ + Json::Value selectedObjectJSON = selectedObject->JsonValue(); + root["delta_x-"+to_string(selectedObjectIndex)] = selectedObjectJSON["delta_x"]; + root["delta_y-"+to_string(selectedObjectIndex)] = selectedObjectJSON["delta_y"]; + root["scale_x-"+to_string(selectedObjectIndex)] = selectedObjectJSON["scale_x"]; + root["scale_y-"+to_string(selectedObjectIndex)] = selectedObjectJSON["scale_y"]; + root["rotation-"+to_string(selectedObjectIndex)] = selectedObjectJSON["rotation"]; + } // return JsonValue return root; @@ -322,17 +332,31 @@ void ObjectDetection::SetJsonValue(const Json::Value root) { } } + // Set the selected object index + if (!root["selected_object_index"].isNull()) + selectedObjectIndex = root["selected_object_index"].asInt(); + for (auto const& trackedObject : trackedObjects){ Json::Value trackedObjectJSON; trackedObjectJSON["box_id"] = root["box_id-"+to_string(trackedObject.first)]; - trackedObjectJSON["delta_x"] = root["delta_x-"+to_string(trackedObject.first)]; - trackedObjectJSON["delta_y"] = root["delta_y-"+to_string(trackedObject.first)]; - trackedObjectJSON["scale_x"] = root["scale_x-"+to_string(trackedObject.first)]; - trackedObjectJSON["scale_y"] = root["scale_y-"+to_string(trackedObject.first)]; - trackedObjectJSON["rotation"] = root["rotation-"+to_string(trackedObject.first)]; - if (!trackedObjectJSON.isNull()) - trackedObject.second->SetJsonValue(trackedObjectJSON); - } + trackedObject.second->SetJsonValue(trackedObjectJSON); + } + + // Set the selectec object's properties + if (!root["box_id-"+to_string(selectedObjectIndex)].isNull()){ + Json::Value selectedObjectJSON; + selectedObjectJSON["box_id"] = root["box_id-"+to_string(selectedObjectIndex)]; + selectedObjectJSON["delta_x"] = root["delta_x-"+to_string(selectedObjectIndex)]; + selectedObjectJSON["delta_y"] = root["delta_y-"+to_string(selectedObjectIndex)]; + selectedObjectJSON["scale_x"] = root["scale_x-"+to_string(selectedObjectIndex)]; + selectedObjectJSON["scale_y"] = root["scale_y-"+to_string(selectedObjectIndex)]; + selectedObjectJSON["rotation"] = root["rotation-"+to_string(selectedObjectIndex)]; + if (!selectedObjectJSON.isNull()){ + auto selectedObject = trackedObjects.at(selectedObjectIndex); + if (selectedObject) + selectedObject->SetJsonValue(selectedObjectJSON); + } + } } // Get all properties for a specific frame @@ -341,27 +365,33 @@ std::string ObjectDetection::PropertiesJSON(int64_t requested_frame) const { // Generate JSON properties list Json::Value root; - // Add trackedObjects IDs to JSON - for (auto const& trackedObject : trackedObjects){ - // Save the trackedObject Id on root + // root["visible_objects"] = Json::Value(Json::arrayValue); + + 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"]; - - // 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"]; - } - } + if (trackedObjectJSON["visible"]["value"].asBool()) + root["box_id-"+to_string(trackedObject.first)] = trackedObjectJSON["box_id"]; + } + + // Add the selected object Json to root + auto selectedObject = trackedObjects.at(selectedObjectIndex); + if (selectedObject){ + Json::Value selectedObjectJSON = selectedObject->PropertiesJSON(requested_frame); + root["box_id-"+to_string(selectedObjectIndex)] = selectedObjectJSON["box_id"]; + root["visible-"+to_string(selectedObjectIndex)] = selectedObjectJSON["visible"]; + root["x1-"+to_string(selectedObjectIndex)] = selectedObjectJSON["x1"]; + root["y1-"+to_string(selectedObjectIndex)] = selectedObjectJSON["y1"]; + root["x2-"+to_string(selectedObjectIndex)] = selectedObjectJSON["x2"]; + root["y2-"+to_string(selectedObjectIndex)] = selectedObjectJSON["y2"]; + root["delta_x-"+to_string(selectedObjectIndex)] = selectedObjectJSON["delta_x"]; + root["delta_y-"+to_string(selectedObjectIndex)] = selectedObjectJSON["delta_y"]; + root["scale_x-"+to_string(selectedObjectIndex)] = selectedObjectJSON["scale_x"]; + root["scale_y-"+to_string(selectedObjectIndex)] = selectedObjectJSON["scale_y"]; + root["rotation-"+to_string(selectedObjectIndex)] = selectedObjectJSON["rotation"]; + } + root["selected_object_index"] = add_property_json("Selected Object", selectedObjectIndex, "int", "", NULL, 0, 200, false, requested_frame); root["id"] = add_property_json("ID", 0.0, "string", Id(), NULL, -1, -1, true, requested_frame); root["position"] = add_property_json("Position", Position(), "float", "", NULL, 0, 1000 * 60 * 30, false, requested_frame); root["layer"] = add_property_json("Track", Layer(), "int", "", NULL, 0, 20, false, requested_frame); diff --git a/src/effects/ObjectDetection.h b/src/effects/ObjectDetection.h index 64df91c3b..39f7f33c0 100644 --- a/src/effects/ObjectDetection.h +++ b/src/effects/ObjectDetection.h @@ -86,6 +86,9 @@ namespace openshot public: + /// Index of the Tracked Object that was selected to modify it's properties + int selectedObjectIndex; + /// Blank constructor, useful when using Json to load the effect properties ObjectDetection(std::string clipTrackerDataPath); From a94f09d105cebcea54b6132ef1ee0110dc73ff6c Mon Sep 17 00:00:00 2001 From: Brenno Date: Wed, 27 Jan 2021 17:18:23 -0300 Subject: [PATCH 29/84] ObjectDetection: updated object selection and transform handler Removed the necessity to append the detected object index (related to the frame) to the effect JSON - which makes the JSON smaller and the performance better. --- src/EffectBase.cpp | 1 + src/EffectBase.h | 3 + src/effects/ObjectDetection.cpp | 102 ++++++++++++++++++-------------- src/effects/ObjectDetection.h | 6 +- src/effects/Tracker.cpp | 97 +++++++++++++++++++----------- src/effects/Tracker.h | 3 + 6 files changed, 132 insertions(+), 80 deletions(-) diff --git a/src/EffectBase.cpp b/src/EffectBase.cpp index aa2bc4e42..9a48c1c9b 100644 --- a/src/EffectBase.cpp +++ b/src/EffectBase.cpp @@ -92,6 +92,7 @@ Json::Value EffectBase::JsonValue() const { root["description"] = info.description; root["has_video"] = info.has_video; root["has_audio"] = info.has_audio; + root["has_tracked_object"] = info.has_tracked_object; root["order"] = Order(); // return JsonValue diff --git a/src/EffectBase.h b/src/EffectBase.h index 320e840cf..ae5cf257f 100644 --- a/src/EffectBase.h +++ b/src/EffectBase.h @@ -97,6 +97,9 @@ namespace openshot /// Set parent clip object of this effect void ParentClip(openshot::ClipBase* new_clip); + /// Get the indexes and IDs of all visible objects in the given frame + virtual std::string GetVisibleObjects(int64_t frame_number) const {return {}; }; + /// Get and Set JSON methods virtual std::string Json() const = 0; ///< Generate JSON string of this object virtual void SetJson(const std::string value) = 0; ///< Load JSON string into this object diff --git a/src/effects/ObjectDetection.cpp b/src/effects/ObjectDetection.cpp index a9ee04114..e11ae91ca 100644 --- a/src/effects/ObjectDetection.cpp +++ b/src/effects/ObjectDetection.cpp @@ -28,8 +28,6 @@ * along with OpenShot Library. If not, see . */ -#include - #include "effects/ObjectDetection.h" #include "effects/Tracker.h" @@ -264,6 +262,28 @@ DetectionData ObjectDetection::GetTrackedData(size_t frameId){ } +// Get the indexes and IDs of all visible objects in the given frame +std::string ObjectDetection::GetVisibleObjects(int64_t frame_number) const{ + + // Initialize the JSON objects + Json::Value root; + root["visible_objects_index"] = Json::Value(Json::arrayValue); + root["visible_objects_id"] = Json::Value(Json::arrayValue); + + // Iterate through the tracked objects + for (const auto& trackedObject : trackedObjects){ + // Get the tracked object JSON properties for this frame + Json::Value trackedObjectJSON = trackedObject.second->PropertiesJSON(frame_number); + if (trackedObjectJSON["visible"]["value"].asBool()){ + // Save the object's index and ID if it's visible in this frame + root["visible_objects_index"].append(trackedObject.first); + root["visible_objects_id"].append(trackedObject.second->Id()); + } + } + + return root.toStyledString(); +} + // Generate JSON string of this object std::string ObjectDetection::Json() const { @@ -279,21 +299,22 @@ Json::Value ObjectDetection::JsonValue() const { root["type"] = info.class_name; root["protobuf_data_path"] = protobuf_data_path; root["selected_object_index"] = selectedObjectIndex; - + root["objects_id"] = Json::Value(Json::arrayValue); + for (auto const& trackedObject : trackedObjects){ Json::Value trackedObjectJSON = trackedObject.second->JsonValue(); - root["box_id-"+to_string(trackedObject.first)] = trackedObjectJSON["box_id"]; + root["objects_id"].append(trackedObject.second->Id()); } // Add the selected object Json to root auto selectedObject = trackedObjects.at(selectedObjectIndex); if (selectedObject){ Json::Value selectedObjectJSON = selectedObject->JsonValue(); - root["delta_x-"+to_string(selectedObjectIndex)] = selectedObjectJSON["delta_x"]; - root["delta_y-"+to_string(selectedObjectIndex)] = selectedObjectJSON["delta_y"]; - root["scale_x-"+to_string(selectedObjectIndex)] = selectedObjectJSON["scale_x"]; - root["scale_y-"+to_string(selectedObjectIndex)] = selectedObjectJSON["scale_y"]; - root["rotation-"+to_string(selectedObjectIndex)] = selectedObjectJSON["rotation"]; + root["delta_x"] = selectedObjectJSON["delta_x"]; + root["delta_y"] = selectedObjectJSON["delta_y"]; + root["scale_x"] = selectedObjectJSON["scale_x"]; + root["scale_y"] = selectedObjectJSON["scale_y"]; + root["rotation"] = selectedObjectJSON["rotation"]; } // return JsonValue @@ -336,26 +357,26 @@ void ObjectDetection::SetJsonValue(const Json::Value root) { if (!root["selected_object_index"].isNull()) selectedObjectIndex = root["selected_object_index"].asInt(); - for (auto const& trackedObject : trackedObjects){ + // Set the object's ids + if (!root["objects_id"].isNull()){ + for (auto const& trackedObject : trackedObjects){ Json::Value trackedObjectJSON; - trackedObjectJSON["box_id"] = root["box_id-"+to_string(trackedObject.first)]; + trackedObjectJSON["box_id"] = root["objects_id"][trackedObject.first].asString(); trackedObject.second->SetJsonValue(trackedObjectJSON); + } } - // Set the selectec object's properties - if (!root["box_id-"+to_string(selectedObjectIndex)].isNull()){ - Json::Value selectedObjectJSON; - selectedObjectJSON["box_id"] = root["box_id-"+to_string(selectedObjectIndex)]; - selectedObjectJSON["delta_x"] = root["delta_x-"+to_string(selectedObjectIndex)]; - selectedObjectJSON["delta_y"] = root["delta_y-"+to_string(selectedObjectIndex)]; - selectedObjectJSON["scale_x"] = root["scale_x-"+to_string(selectedObjectIndex)]; - selectedObjectJSON["scale_y"] = root["scale_y-"+to_string(selectedObjectIndex)]; - selectedObjectJSON["rotation"] = root["rotation-"+to_string(selectedObjectIndex)]; - if (!selectedObjectJSON.isNull()){ - auto selectedObject = trackedObjects.at(selectedObjectIndex); - if (selectedObject) - selectedObject->SetJsonValue(selectedObjectJSON); - } + // Set the selected object's properties + Json::Value selectedObjectJSON; + selectedObjectJSON["delta_x"] = root["delta_x"]; + selectedObjectJSON["delta_y"] = root["delta_y"]; + selectedObjectJSON["scale_x"] = root["scale_x"]; + selectedObjectJSON["scale_y"] = root["scale_y"]; + selectedObjectJSON["rotation"] = root["rotation"]; + if (!selectedObjectJSON.isNull()){ + auto selectedObject = trackedObjects.at(selectedObjectIndex); + if (selectedObject) + selectedObject->SetJsonValue(selectedObjectJSON); } } @@ -365,30 +386,21 @@ std::string ObjectDetection::PropertiesJSON(int64_t requested_frame) const { // Generate JSON properties list Json::Value root; - // root["visible_objects"] = Json::Value(Json::arrayValue); - - for (auto const& trackedObject : trackedObjects){ - Json::Value trackedObjectJSON = trackedObject.second->PropertiesJSON(requested_frame); - root["visible-"+to_string(trackedObject.first)] = trackedObjectJSON["visible"]; - if (trackedObjectJSON["visible"]["value"].asBool()) - root["box_id-"+to_string(trackedObject.first)] = trackedObjectJSON["box_id"]; - } - // Add the selected object Json to root auto selectedObject = trackedObjects.at(selectedObjectIndex); if (selectedObject){ Json::Value selectedObjectJSON = selectedObject->PropertiesJSON(requested_frame); - root["box_id-"+to_string(selectedObjectIndex)] = selectedObjectJSON["box_id"]; - root["visible-"+to_string(selectedObjectIndex)] = selectedObjectJSON["visible"]; - root["x1-"+to_string(selectedObjectIndex)] = selectedObjectJSON["x1"]; - root["y1-"+to_string(selectedObjectIndex)] = selectedObjectJSON["y1"]; - root["x2-"+to_string(selectedObjectIndex)] = selectedObjectJSON["x2"]; - root["y2-"+to_string(selectedObjectIndex)] = selectedObjectJSON["y2"]; - root["delta_x-"+to_string(selectedObjectIndex)] = selectedObjectJSON["delta_x"]; - root["delta_y-"+to_string(selectedObjectIndex)] = selectedObjectJSON["delta_y"]; - root["scale_x-"+to_string(selectedObjectIndex)] = selectedObjectJSON["scale_x"]; - root["scale_y-"+to_string(selectedObjectIndex)] = selectedObjectJSON["scale_y"]; - root["rotation-"+to_string(selectedObjectIndex)] = selectedObjectJSON["rotation"]; + root["box_id"] = selectedObjectJSON["box_id"]; + root["visible"] = selectedObjectJSON["visible"]; + root["x1"] = selectedObjectJSON["x1"]; + root["y1"] = selectedObjectJSON["y1"]; + root["x2"] = selectedObjectJSON["x2"]; + root["y2"] = selectedObjectJSON["y2"]; + root["delta_x"] = selectedObjectJSON["delta_x"]; + root["delta_y"] = selectedObjectJSON["delta_y"]; + root["scale_x"] = selectedObjectJSON["scale_x"]; + root["scale_y"] = selectedObjectJSON["scale_y"]; + root["rotation"] = selectedObjectJSON["rotation"]; } root["selected_object_index"] = add_property_json("Selected Object", selectedObjectIndex, "int", "", NULL, 0, 200, false, requested_frame); diff --git a/src/effects/ObjectDetection.h b/src/effects/ObjectDetection.h index 39f7f33c0..4f1ad4810 100644 --- a/src/effects/ObjectDetection.h +++ b/src/effects/ObjectDetection.h @@ -108,11 +108,15 @@ namespace openshot std::shared_ptr GetFrame(int64_t frame_number) override { return GetFrame(std::shared_ptr (new Frame()), frame_number); } - // Load protobuf data file + /// Load protobuf data file bool LoadObjDetectdData(std::string inputFilePath); + /// Get tracker info for the desired frame DetectionData GetTrackedData(size_t frameId); + /// Get the indexes and IDs of all visible objects in the given frame + std::string GetVisibleObjects(int64_t frame_number) const override; + /// 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 diff --git a/src/effects/Tracker.cpp b/src/effects/Tracker.cpp index ec7553929..f3b353571 100644 --- a/src/effects/Tracker.cpp +++ b/src/effects/Tracker.cpp @@ -126,6 +126,28 @@ std::shared_ptr Tracker::GetFrame(std::shared_ptr frame, int64_t f return frame; } +// Get the indexes and IDs of all visible objects in the given frame +std::string Tracker::GetVisibleObjects(int64_t frame_number) const{ + + // Initialize the JSON objects + Json::Value root; + root["visible_objects_index"] = Json::Value(Json::arrayValue); + root["visible_objects_id"] = Json::Value(Json::arrayValue); + + // Iterate through the tracked objects + for (const auto& trackedObject : trackedObjects){ + // Get the tracked object JSON properties for this frame + Json::Value trackedObjectJSON = trackedObject.second->PropertiesJSON(frame_number); + if (trackedObjectJSON["visible"]["value"].asBool()){ + // Save the object's index and ID if it's visible in this frame + root["visible_objects_index"].append(trackedObject.first); + root["visible_objects_id"].append(trackedObject.second->Id()); + } + } + + return root.toStyledString(); +} + // Generate JSON string of this object std::string Tracker::Json() const { @@ -145,21 +167,19 @@ Json::Value Tracker::JsonValue() const { root["BaseFPS"]["num"] = BaseFPS.num; root["BaseFPS"]["den"] = BaseFPS.den; root["TimeScale"] = this->TimeScale; + root["objects_id"] = Json::Value(Json::arrayValue); - // Get trackedData JSON - Json::Value trackedDataJSON; - trackedDataJSON = trackedData->JsonValue(); - - // Save the trackedData properties on root + // Add trackedObjects IDs to JSON for (auto const& trackedObject : trackedObjects){ + // Get the trackedObject JSON Json::Value trackedObjectJSON = trackedObject.second->JsonValue(); + root["objects_id"].append(trackedObject.second->Id()); // Save the trackedObject JSON on root - root["box_id-"+to_string(trackedObject.first)] = trackedObjectJSON["box_id"]; - 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["delta_x"] = trackedObjectJSON["delta_x"]; + root["delta_y"] = trackedObjectJSON["delta_y"]; + root["scale_x"] = trackedObjectJSON["scale_x"]; + root["scale_y"] = trackedObjectJSON["scale_y"]; + root["rotation"] = trackedObjectJSON["rotation"]; } // return JsonValue @@ -219,14 +239,22 @@ void Tracker::SetJsonValue(const Json::Value root) { } } + // Set the object's ids + if (!root["objects_id"].isNull()){ + for (auto const& trackedObject : trackedObjects){ + Json::Value trackedObjectJSON; + trackedObjectJSON["box_id"] = root["objects_id"][trackedObject.first].asString(); + trackedObject.second->SetJsonValue(trackedObjectJSON); + } + } + for (auto const& trackedObject : trackedObjects){ - Json::Value trackedObjectJSON; - trackedObjectJSON["box_id"] = root["box_id-"+to_string(trackedObject.first)]; - trackedObjectJSON["delta_x"] = root["delta_x-"+to_string(trackedObject.first)]; - trackedObjectJSON["delta_y"] = root["delta_y-"+to_string(trackedObject.first)]; - trackedObjectJSON["scale_x"] = root["scale_x-"+to_string(trackedObject.first)]; - trackedObjectJSON["scale_y"] = root["scale_y-"+to_string(trackedObject.first)]; - trackedObjectJSON["rotation"] = root["rotation-"+to_string(trackedObject.first)]; + Json::Value trackedObjectJSON; + trackedObjectJSON["delta_x"] = root["delta_x"]; + trackedObjectJSON["delta_y"] = root["delta_y"]; + trackedObjectJSON["scale_x"] = root["scale_x"]; + trackedObjectJSON["scale_y"] = root["scale_y"]; + trackedObjectJSON["rotation"] = root["rotation"]; if (!trackedObjectJSON.isNull()) trackedObject.second->SetJsonValue(trackedObjectJSON); } @@ -239,22 +267,23 @@ void Tracker::SetJsonValue(const Json::Value root) { std::string Tracker::PropertiesJSON(int64_t requested_frame) const { // Generate JSON properties list - Json::Value root; - - // Add trackedObjects properties to JSON + Json::Value root; + + // Add trackedObjects IDs to JSON 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"]; - 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"]; + // Save the trackedObject Id on root + Json::Value trackedObjectJSON = trackedObject.second->PropertiesJSON(requested_frame); + root["box_id"] = trackedObjectJSON["box_id"]; + root["visible"] = trackedObjectJSON["visible"]; + root["x1"] = trackedObjectJSON["x1"]; + root["y1"] = trackedObjectJSON["y1"]; + root["x2"] = trackedObjectJSON["x2"]; + root["y2"] = trackedObjectJSON["y2"]; + root["delta_x"] = trackedObjectJSON["delta_x"]; + root["delta_y"] = trackedObjectJSON["delta_y"]; + root["scale_x"] = trackedObjectJSON["scale_x"]; + root["scale_y"] = trackedObjectJSON["scale_y"]; + root["rotation"] = trackedObjectJSON["rotation"]; } // Append effect's properties @@ -268,4 +297,4 @@ std::string Tracker::PropertiesJSON(int64_t requested_frame) const { // Return formatted string return root.toStyledString(); -} +} \ No newline at end of file diff --git a/src/effects/Tracker.h b/src/effects/Tracker.h index e5cca0477..e52100941 100644 --- a/src/effects/Tracker.h +++ b/src/effects/Tracker.h @@ -85,6 +85,9 @@ namespace openshot std::shared_ptr GetFrame(std::shared_ptr frame, int64_t frame_number) override; std::shared_ptr GetFrame(int64_t frame_number) override { return GetFrame(std::shared_ptr (new Frame()), frame_number); } + /// Get the indexes and IDs of all visible objects in the given frame + std::string GetVisibleObjects(int64_t frame_number) const override; + /// 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 From 3f11361f09b964b193c3f8f06adab22a837ae6a2 Mon Sep 17 00:00:00 2001 From: Brenno Date: Wed, 27 Jan 2021 17:41:39 -0300 Subject: [PATCH 30/84] Added support to attach a clip to another clip --- src/Clip.cpp | 49 +++++++++++++++++++++++++++++++--------- src/Clip.h | 7 +++++- tests/KeyFrame_Tests.cpp | 2 +- 3 files changed, 45 insertions(+), 13 deletions(-) diff --git a/src/Clip.cpp b/src/Clip.cpp index b1ea5c315..af09db1ea 100644 --- a/src/Clip.cpp +++ b/src/Clip.cpp @@ -100,6 +100,10 @@ void Clip::init_settings() has_audio = Keyframe(-1.0); has_video = Keyframe(-1.0); + // Initialize the attached object and attached clip as null pointers + attachedObject = nullptr; + attachedClip = NULL; + // Init reader info struct and cache size init_reader_settings(); } @@ -245,22 +249,23 @@ Clip::~Clip() } // Attach clip to bounding box -void Clip::AttachToTracker(std::string tracked_id) +void Clip::AttachToObject(std::string object_id) { // Search for the tracked object on the timeline Timeline* parentTimeline = (Timeline *) ParentTimeline(); - - // Check if the clip has a parent timeline - if (parentTimeline){ + if (parentTimeline) { // Create a smart pointer to the tracked object from the timeline - std::shared_ptr trackedObject = parentTimeline->GetTrackedObject(tracked_id); - + std::shared_ptr trackedObject = parentTimeline->GetTrackedObject(object_id); + Clip* clipObject = parentTimeline->GetClip(object_id); + // Check for valid tracked object if (trackedObject){ SetAttachedObject(trackedObject); } - + else if (clipObject) { + SetAttachedClip(clipObject); + } } return; } @@ -271,6 +276,12 @@ void Clip::SetAttachedObject(std::shared_ptr tracke return; } +// Set the pointer to the clip this clip is attached to +void Clip::SetAttachedClip(Clip* clipObject){ + attachedClip = clipObject; + return; +} + /// Set the current reader void Clip::Reader(ReaderBase* new_reader) { @@ -979,13 +990,15 @@ void Clip::SetJsonValue(const Json::Value root) { cache.Clear(); // Set data from Json (if key is found) - if (!root["attached_id"].isNull()) + if (!root["attached_id"].isNull()){ attached_id = root["attached_id"].asString(); if (attached_id.size() > 0 && attached_id != "None"){ - AttachToTracker(attached_id); + AttachToObject(attached_id); } else{ attachedObject = nullptr; + attachedClip = NULL; } + } if (!root["gravity"].isNull()) gravity = (GravityType) root["gravity"].asInt(); if (!root["scale"].isNull()) @@ -1315,7 +1328,7 @@ void Clip::apply_keyframes(std::shared_ptr frame, int width, int height) break; } } - + // Initialize attached object's properties values float attached_location_x = 0.0; float attached_location_y = 0.0; @@ -1323,6 +1336,20 @@ void Clip::apply_keyframes(std::shared_ptr frame, int width, int height) float attached_scale_y = 1.0; float attached_rotation = 0.0; + if (attachedClip){ + + // Convert Clip's frame position to Timeline's frame position + long clip_start_position = round(Position() * info.fps.ToDouble()) + 1; + long clip_start_frame = (Start() * info.fps.ToDouble()) + 1; + double timeline_frame_number = frame->number + clip_start_position - clip_start_frame; + + attached_location_x = attachedClip->location_x.GetValue(timeline_frame_number); + attached_location_y = attachedClip->location_y.GetValue(timeline_frame_number); + attached_scale_x = attachedClip->scale_x.GetValue(timeline_frame_number); + attached_scale_y = attachedClip->scale_y.GetValue(timeline_frame_number); + attached_rotation = attachedClip->rotation.GetValue(timeline_frame_number); + } + /* TRANSFORM CLIP TO ATTACHED OBJECT'S POSITION AND DIMENSION */ if (attachedObject){ @@ -1371,7 +1398,7 @@ void Clip::apply_keyframes(std::shared_ptr frame, int width, int height) float sy = scale_y.GetValue(frame->number); // percentage Y scale // Compose clip's scale to attachedObject's scale - if(attached_scale_x > 0.0 && attached_scale_y > 0.0){ + if(attached_scale_x != 0.0 && attached_scale_y != 0.0){ sx*= attached_scale_x; sy*= attached_scale_y; } diff --git a/src/Clip.h b/src/Clip.h index 8b31405af..87673ece2 100644 --- a/src/Clip.h +++ b/src/Clip.h @@ -126,6 +126,7 @@ namespace openshot { bool is_open; ///> Is Reader opened std::string attached_id; ///< Id of the bounding box that this clip is attached to std::shared_ptr attachedObject; + Clip* attachedClip; ///< Clip object this clip is attached to // Audio resampler (if time mapping) openshot::AudioResampler *resampler; @@ -203,12 +204,16 @@ namespace openshot { void SetAttachedId(std::string value) { attached_id = value; }; /// Attach clip to bounding box - void AttachToTracker(std::string tracked_id); + void AttachToObject(std::string object_id); /// Set the pointer to the trackedObject this clip is attached to void SetAttachedObject(std::shared_ptr trackedObject); + /// Set the pointer to the clip this clip is attached to + void SetAttachedClip(Clip* clipObject); /// Return a pointer to the trackedObject this clip is attached to std::shared_ptr GetAttachedObject() const { return attachedObject; }; + /// Return a pointer to the clip this clip is attached to + Clip* GetAttachedClip() const { return attachedClip; }; /// Return the type name of the class std::string Name() override { return "Clip"; }; diff --git a/tests/KeyFrame_Tests.cpp b/tests/KeyFrame_Tests.cpp index 31d93c3fb..4444a9c99 100644 --- a/tests/KeyFrame_Tests.cpp +++ b/tests/KeyFrame_Tests.cpp @@ -666,7 +666,7 @@ TEST(Attach_test){ // Attach childClip to tracked object std::string tracked_id = trackedData->Id(); childClip.Open(); - childClip.AttachToTracker(tracked_id); + childClip.AttachToObject(tracked_id); std::shared_ptr trackedTest = std::static_pointer_cast(childClip.GetAttachedObject()); From fd88a60bb144399bb4aeb3169e15bbda9fc018bf Mon Sep 17 00:00:00 2001 From: Brenno Date: Wed, 27 Jan 2021 17:54:49 -0300 Subject: [PATCH 31/84] Updated variable names Updated "attached_id" to "parentObjectId", "attachedObject" to "parentTrackedObject", and "attachedClip" to "parentClipObject" --- src/Clip.cpp | 219 +++++++++++++++++++++++++++++---------------------- src/Clip.h | 20 ++--- 2 files changed, 137 insertions(+), 102 deletions(-) diff --git a/src/Clip.cpp b/src/Clip.cpp index af09db1ea..f61913f1a 100644 --- a/src/Clip.cpp +++ b/src/Clip.cpp @@ -58,7 +58,7 @@ void Clip::init_settings() mixing = VOLUME_MIX_NONE; waveform = false; previous_properties = ""; - attached_id = ""; + parentObjectId = ""; // Init scale curves scale_x = Keyframe(1.0); @@ -101,8 +101,8 @@ void Clip::init_settings() has_video = Keyframe(-1.0); // Initialize the attached object and attached clip as null pointers - attachedObject = nullptr; - attachedClip = NULL; + parentTrackedObject = nullptr; + parentClipObject = NULL; // Init reader info struct and cache size init_reader_settings(); @@ -272,13 +272,13 @@ void Clip::AttachToObject(std::string object_id) // Set the pointer to the trackedObject this clip is attached to void Clip::SetAttachedObject(std::shared_ptr trackedObject){ - attachedObject = trackedObject; + parentTrackedObject = trackedObject; return; } // Set the pointer to the clip this clip is attached to void Clip::SetAttachedClip(Clip* clipObject){ - attachedClip = clipObject; + parentClipObject = clipObject; return; } @@ -800,10 +800,10 @@ std::string Clip::PropertiesJSON(int64_t requested_frame) const { root["display"] = add_property_json("Frame Number", display, "int", "", NULL, 0, 3, false, requested_frame); root["mixing"] = add_property_json("Volume Mixing", mixing, "int", "", NULL, 0, 2, false, requested_frame); root["waveform"] = add_property_json("Waveform", waveform, "int", "", NULL, 0, 1, false, requested_frame); - if (!attached_id.empty()) { - root["attached_id"] = add_property_json("Attached ID", 0.0, "string", attached_id, NULL, -1, -1, false, requested_frame); + if (!parentObjectId.empty()) { + root["parentObjectId"] = add_property_json("Parent Object ID", 0.0, "string", parentObjectId, NULL, -1, -1, false, requested_frame); } else { - root["attached_id"] = add_property_json("Attached ID", 0.0, "string", "None", NULL, -1, -1, false, requested_frame); + root["parentObjectId"] = add_property_json("Parent Object ID", 0.0, "string", "None", NULL, -1, -1, false, requested_frame); } // Add gravity choices (dropdown style) root["gravity"]["choices"].append(add_property_choice_json("Top Left", GRAVITY_TOP_LEFT, gravity)); @@ -837,49 +837,76 @@ std::string Clip::PropertiesJSON(int64_t requested_frame) const { root["waveform"]["choices"].append(add_property_choice_json("Yes", true, waveform)); root["waveform"]["choices"].append(add_property_choice_json("No", false, waveform)); - if (attachedObject){ - + // Add the parentTrackedObject's properties + if (parentTrackedObject) + { // Convert Clip's frame position to Timeline's frame position long clip_start_position = round(Position() * info.fps.ToDouble()) + 1; long clip_start_frame = (Start() * info.fps.ToDouble()) + 1; double timeline_frame_number = requested_frame + clip_start_position - clip_start_frame; // Get attached object's parent clip properties - std::map< std::string, float > attached_clip_properties = attachedObject->GetParentClipProperties(timeline_frame_number); - double attached_frame_number = attached_clip_properties["frame_number"]; - + std::map< std::string, float > trackedObjectParentClipProperties = parentTrackedObject->GetParentClipProperties(timeline_frame_number); + double parentObject_frame_number = trackedObjectParentClipProperties["frame_number"]; // Get attached object properties - std::map< std::string, float > attached_properties = attachedObject->GetBoxValues(attached_frame_number); - - // Compose attachedObject's properties with it's parent clip's properties - float attached_location_x = attached_properties["cx"] - 0.5 + attached_clip_properties["cx"]; - float attached_location_y = attached_properties["cy"] - 0.5 + attached_clip_properties["cy"]; - float attached_scale_x = attached_properties["w"]*attached_properties["sx"]; - float attached_scale_y = attached_properties["h"]*attached_properties["sy"]; - float attached_rotation = attached_properties["r"] + attached_clip_properties["r"]; - - // Set JSON properties with composed attached object's properties - root["location_x"] = add_property_json("Location X", attached_location_x, "float", "", &location_x, -1.0, 1.0, false, requested_frame); - root["location_y"] = add_property_json("Location Y", attached_location_y, "float", "", &location_y, -1.0, 1.0, false, requested_frame); - root["scale_x"] = add_property_json("Scale X", attached_scale_x, "float", "", &scale_x, 0.0, 1.0, false, requested_frame); - root["scale_y"] = add_property_json("Scale Y", attached_scale_y, "float", "", &scale_y, 0.0, 1.0, false, requested_frame); - root["rotation"] = add_property_json("Rotation", attached_rotation, "float", "", &rotation, -360, 360, false, requested_frame); - - } else { + std::map< std::string, float > trackedObjectProperties = parentTrackedObject->GetBoxValues(parentObject_frame_number); - // Set JSON properties with clip's properties + // Correct the parent Tracked Object properties by the clip's reference system + float parentObject_location_x = trackedObjectProperties["cx"] - 0.5 + trackedObjectParentClipProperties["cx"]; + float parentObject_location_y = trackedObjectProperties["cy"] - 0.5 + trackedObjectParentClipProperties["cy"]; + float parentObject_scale_x = trackedObjectProperties["w"]*trackedObjectProperties["sx"]; + float parentObject_scale_y = trackedObjectProperties["h"]*trackedObjectProperties["sy"]; + float parentObject_rotation = trackedObjectProperties["r"] + trackedObjectParentClipProperties["r"]; + + // Add the parent Tracked Object properties to JSON + root["location_x"] = add_property_json("Location X", parentObject_location_x, "float", "", &location_x, -1.0, 1.0, false, requested_frame); + root["location_y"] = add_property_json("Location Y", parentObject_location_y, "float", "", &location_y, -1.0, 1.0, false, requested_frame); + root["scale_x"] = add_property_json("Scale X", parentObject_scale_x, "float", "", &scale_x, 0.0, 1.0, false, requested_frame); + root["scale_y"] = add_property_json("Scale Y", parentObject_scale_y, "float", "", &scale_y, 0.0, 1.0, false, requested_frame); + root["rotation"] = add_property_json("Rotation", parentObject_rotation, "float", "", &rotation, -360, 360, false, requested_frame); + root["shear_x"] = add_property_json("Shear X", shear_x.GetValue(requested_frame), "float", "", &shear_x, -1.0, 1.0, false, requested_frame); + root["shear_y"] = add_property_json("Shear Y", shear_y.GetValue(requested_frame), "float", "", &shear_y, -1.0, 1.0, false, requested_frame); + } + // Add the parentClipObject's properties + else if (parentClipObject) + { + // Convert Clip's frame position to Timeline's frame position + long clip_start_position = round(Position() * info.fps.ToDouble()) + 1; + long clip_start_frame = (Start() * info.fps.ToDouble()) + 1; + double timeline_frame_number = requested_frame + clip_start_position - clip_start_frame; + + // Correct the parent Clip Object properties by the clip's reference system + float parentObject_location_x = parentClipObject->location_x.GetValue(timeline_frame_number); + float parentObject_location_y = parentClipObject->location_y.GetValue(timeline_frame_number); + float parentObject_scale_x = parentClipObject->scale_x.GetValue(timeline_frame_number); + float parentObject_scale_y = parentClipObject->scale_y.GetValue(timeline_frame_number); + float parentObject_shear_x = parentClipObject->shear_x.GetValue(timeline_frame_number); + float parentObject_shear_y = parentClipObject->shear_y.GetValue(timeline_frame_number); + float parentObject_rotation = parentClipObject->rotation.GetValue(timeline_frame_number); + + // Add the parent Clip Object properties to JSON + root["location_x"] = add_property_json("Location X", parentObject_location_x, "float", "", &location_x, -1.0, 1.0, false, requested_frame); + root["location_y"] = add_property_json("Location Y", parentObject_location_y, "float", "", &location_y, -1.0, 1.0, false, requested_frame); + root["scale_x"] = add_property_json("Scale X", parentObject_scale_x, "float", "", &scale_x, 0.0, 1.0, false, requested_frame); + root["scale_y"] = add_property_json("Scale Y", parentObject_scale_y, "float", "", &scale_y, 0.0, 1.0, false, requested_frame); + root["rotation"] = add_property_json("Rotation", parentObject_rotation, "float", "", &rotation, -360, 360, false, requested_frame); + root["shear_x"] = add_property_json("Shear X", parentObject_shear_x, "float", "", &shear_x, -1.0, 1.0, false, requested_frame); + root["shear_y"] = add_property_json("Shear Y", parentObject_shear_y, "float", "", &shear_y, -1.0, 1.0, false, requested_frame); + } + else + { + // Add this own clip's properties to JSON root["location_x"] = add_property_json("Location X", location_x.GetValue(requested_frame), "float", "", &location_x, -1.0, 1.0, false, requested_frame); root["location_y"] = add_property_json("Location Y", location_y.GetValue(requested_frame), "float", "", &location_y, -1.0, 1.0, false, requested_frame); root["scale_x"] = add_property_json("Scale X", scale_x.GetValue(requested_frame), "float", "", &scale_x, 0.0, 1.0, false, requested_frame); root["scale_y"] = add_property_json("Scale Y", 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, -360, 360, false, requested_frame); - + root["shear_x"] = add_property_json("Shear X", shear_x.GetValue(requested_frame), "float", "", &shear_x, -1.0, 1.0, false, requested_frame); + root["shear_y"] = add_property_json("Shear Y", shear_y.GetValue(requested_frame), "float", "", &shear_y, -1.0, 1.0, false, requested_frame); } // Keyframes root["alpha"] = add_property_json("Alpha", alpha.GetValue(requested_frame), "float", "", &alpha, 0.0, 1.0, false, requested_frame); - root["shear_x"] = add_property_json("Shear X", shear_x.GetValue(requested_frame), "float", "", &shear_x, -1.0, 1.0, false, requested_frame); - root["shear_y"] = add_property_json("Shear Y", shear_y.GetValue(requested_frame), "float", "", &shear_y, -1.0, 1.0, false, requested_frame); root["origin_x"] = add_property_json("Origin X", origin_x.GetValue(requested_frame), "float", "", &origin_x, 0.0, 1.0, false, requested_frame); root["origin_y"] = add_property_json("Origin Y", origin_y.GetValue(requested_frame), "float", "", &origin_y, 0.0, 1.0, false, requested_frame); root["volume"] = add_property_json("Volume", volume.GetValue(requested_frame), "float", "", &volume, 0.0, 1.0, false, requested_frame); @@ -912,7 +939,7 @@ Json::Value Clip::JsonValue() const { // Create root json object Json::Value root = ClipBase::JsonValue(); // get parent properties - root["attached_id"] = attached_id; + root["parentObjectId"] = parentObjectId; root["gravity"] = gravity; root["scale"] = scale; root["anchor"] = anchor; @@ -990,13 +1017,13 @@ void Clip::SetJsonValue(const Json::Value root) { cache.Clear(); // Set data from Json (if key is found) - if (!root["attached_id"].isNull()){ - attached_id = root["attached_id"].asString(); - if (attached_id.size() > 0 && attached_id != "None"){ - AttachToObject(attached_id); + if (!root["parentObjectId"].isNull()){ + parentObjectId = root["parentObjectId"].asString(); + if (parentObjectId.size() > 0 && parentObjectId != "None"){ + AttachToObject(parentObjectId); } else{ - attachedObject = nullptr; - attachedClip = NULL; + parentTrackedObject = nullptr; + parentClipObject = NULL; } } if (!root["gravity"].isNull()) @@ -1288,7 +1315,7 @@ void Clip::apply_keyframes(std::shared_ptr frame, int width, int height) QSize source_size = source_image->size(); // Apply stretch scale to correctly fit the bounding-box - if (attachedObject){ + if (parentTrackedObject){ scale = SCALE_STRETCH; } @@ -1329,63 +1356,71 @@ void Clip::apply_keyframes(std::shared_ptr frame, int width, int height) } } - // Initialize attached object's properties values - float attached_location_x = 0.0; - float attached_location_y = 0.0; - float attached_scale_x = 1.0; - float attached_scale_y = 1.0; - float attached_rotation = 0.0; + // Initialize parent object's properties (Clip or Tracked Object) + float parentObject_location_x = 0.0; + float parentObject_location_y = 0.0; + float parentObject_scale_x = 1.0; + float parentObject_scale_y = 1.0; + float parentObject_shear_x = 0.0; + float parentObject_shear_y = 0.0; + float parentObject_rotation = 0.0; - if (attachedClip){ + // Get the parentClipObject properties + if (parentClipObject){ // Convert Clip's frame position to Timeline's frame position long clip_start_position = round(Position() * info.fps.ToDouble()) + 1; long clip_start_frame = (Start() * info.fps.ToDouble()) + 1; double timeline_frame_number = frame->number + clip_start_position - clip_start_frame; - attached_location_x = attachedClip->location_x.GetValue(timeline_frame_number); - attached_location_y = attachedClip->location_y.GetValue(timeline_frame_number); - attached_scale_x = attachedClip->scale_x.GetValue(timeline_frame_number); - attached_scale_y = attachedClip->scale_y.GetValue(timeline_frame_number); - attached_rotation = attachedClip->rotation.GetValue(timeline_frame_number); + // Get parent object's properties (Clip) + parentObject_location_x = parentClipObject->location_x.GetValue(timeline_frame_number); + parentObject_location_y = parentClipObject->location_y.GetValue(timeline_frame_number); + parentObject_scale_x = parentClipObject->scale_x.GetValue(timeline_frame_number); + parentObject_scale_y = parentClipObject->scale_y.GetValue(timeline_frame_number); + parentObject_shear_x = parentClipObject->shear_x.GetValue(timeline_frame_number); + parentObject_shear_y = parentClipObject->shear_y.GetValue(timeline_frame_number); + parentObject_rotation = parentClipObject->rotation.GetValue(timeline_frame_number); } - /* TRANSFORM CLIP TO ATTACHED OBJECT'S POSITION AND DIMENSION */ - if (attachedObject){ + // Get the parentTrackedObject properties + if (parentTrackedObject){ // Convert Clip's frame position to Timeline's frame position long clip_start_position = round(Position() * info.fps.ToDouble()) + 1; long clip_start_frame = (Start() * info.fps.ToDouble()) + 1; double timeline_frame_number = frame->number + clip_start_position - clip_start_frame; - // Get attached object's parent clip properties - std::map< std::string, float > attached_clip_properties = attachedObject->GetParentClipProperties(timeline_frame_number); - - // Get attachedObject's properties and compose with attachedObject's parent clip properties - if (!attached_clip_properties.empty()){ - - // Get attachedObject's parent clip frame number - double attached_frame_number = attached_clip_properties["frame_number"]; - - // Get attachedObject's properties values - std::map< std::string, float > attached_properties = attachedObject->GetBoxValues(attached_frame_number); - - attached_location_x = attached_properties["cx"] - 0.5 + attached_clip_properties["cx"]; - attached_location_y = attached_properties["cy"] - 0.5 + attached_clip_properties["cy"]; - attached_scale_x = attached_properties["w"]*attached_properties["sx"]; - attached_scale_y = attached_properties["h"]*attached_properties["sy"]; - attached_rotation = attached_properties["r"] + attached_clip_properties["r"]; - - } else { - // Get attachedObject's properties values - std::map< std::string, float > attached_properties = attachedObject->GetBoxValues(timeline_frame_number); - - attached_location_x = attached_properties["cx"] - 0.5; - attached_location_y = attached_properties["cy"] - 0.5; - attached_scale_x = attached_properties["w"]*attached_properties["sx"]; - attached_scale_y = attached_properties["h"]*attached_properties["sy"]; - attached_rotation = attached_properties["r"]; + // Get parentTrackedObject's parent clip's properties + std::map trackedObjectParentClipProperties = parentTrackedObject->GetParentClipProperties(timeline_frame_number); + // Get the attached object's parent clip's properties + if (!trackedObjectParentClipProperties.empty()) + { + // Get parent object's properties (Tracked Object) + float parentObject_frame_number = trackedObjectParentClipProperties["frame_number"]; + + // Access the parentTrackedObject's properties + std::map trackedObjectProperties = parentTrackedObject->GetBoxValues(parentObject_frame_number); + + // Get the Tracked Object's properties and correct them by the clip's reference system + parentObject_location_x = trackedObjectProperties["cx"] - 0.5 + trackedObjectParentClipProperties["location_x"]; + parentObject_location_y = trackedObjectProperties["cy"] - 0.5 + trackedObjectParentClipProperties["location_y"]; + parentObject_scale_x = trackedObjectProperties["w"]*trackedObjectProperties["sx"]; + parentObject_scale_y = trackedObjectProperties["h"]*trackedObjectProperties["sy"]; + parentObject_rotation = trackedObjectProperties["r"] + trackedObjectParentClipProperties["rotation"]; + } + else + { + // Access the parentTrackedObject's properties + std::map trackedObjectProperties = parentTrackedObject->GetBoxValues(timeline_frame_number); + + // Get the Tracked Object's properties and correct them by the clip's reference system + parentObject_location_x = trackedObjectProperties["cx"] - 0.5; + parentObject_location_y = trackedObjectProperties["cy"] - 0.5; + parentObject_scale_x = trackedObjectProperties["w"]*trackedObjectProperties["sx"]; + parentObject_scale_y = trackedObjectProperties["h"]*trackedObjectProperties["sy"]; + parentObject_rotation = trackedObjectProperties["r"]; } } @@ -1397,10 +1432,10 @@ void Clip::apply_keyframes(std::shared_ptr frame, int width, int height) float sx = scale_x.GetValue(frame->number); // percentage X scale float sy = scale_y.GetValue(frame->number); // percentage Y scale - // Compose clip's scale to attachedObject's scale - if(attached_scale_x != 0.0 && attached_scale_y != 0.0){ - sx*= attached_scale_x; - sy*= attached_scale_y; + // Change clip's scale to parentObject's scale + if(parentObject_scale_x != 0.0 && parentObject_scale_y != 0.0){ + sx*= parentObject_scale_x; + sy*= parentObject_scale_y; } float scaled_source_width = source_size.width() * sx; @@ -1447,11 +1482,11 @@ void Clip::apply_keyframes(std::shared_ptr frame, int width, int height) QTransform transform; /* LOCATION, ROTATION, AND SCALE */ - float r = rotation.GetValue(frame->number) + attached_rotation; // rotate in degrees - x += ( width * (location_x.GetValue(frame->number) + attached_location_x) ); // move in percentage of final width - y += ( height * (location_y.GetValue(frame->number) + attached_location_y) ); // move in percentage of final height - float shear_x_value = shear_x.GetValue(frame->number); - float shear_y_value = shear_y.GetValue(frame->number); + float r = rotation.GetValue(frame->number) + parentObject_rotation; // rotate in degrees + x += (width * (location_x.GetValue(frame->number) + parentObject_location_x )); // move in percentage of final width + y += (height * (location_y.GetValue(frame->number) + parentObject_location_y )); // move in percentage of final height + float shear_x_value = shear_x.GetValue(frame->number) + parentObject_shear_x; + float shear_y_value = shear_y.GetValue(frame->number) + parentObject_shear_y; float origin_x_value = origin_x.GetValue(frame->number); float origin_y_value = origin_y.GetValue(frame->number); diff --git a/src/Clip.h b/src/Clip.h index 87673ece2..cd0b1b6ab 100644 --- a/src/Clip.h +++ b/src/Clip.h @@ -124,9 +124,9 @@ namespace openshot { bool waveform; ///< Should a waveform be used instead of the clip's image std::list effects; /// Is Reader opened - std::string attached_id; ///< Id of the bounding box that this clip is attached to - std::shared_ptr attachedObject; - Clip* attachedClip; ///< Clip object this clip is attached to + std::string parentObjectId; ///< Id of the bounding box that this clip is attached to + std::shared_ptr parentTrackedObject; ///< Tracked object this clip is attached to + openshot::Clip* parentClipObject; ///< Clip object this clip is attached to // Audio resampler (if time mapping) openshot::AudioResampler *resampler; @@ -198,12 +198,12 @@ namespace openshot { /// Determine if reader is open or closed bool IsOpen() override { return is_open; }; - /// Get and set the bounding box that this clip is attached to - std::string GetAttachedId() const { return attached_id; }; - /// Set id of the bounding box that this clip is attached to - void SetAttachedId(std::string value) { attached_id = value; }; + /// Get and set the object id that this clip is attached to + std::string GetAttachedId() const { return parentObjectId; }; + /// Set id of the object id that this clip is attached to + void SetAttachedId(std::string value) { parentObjectId = value; }; - /// Attach clip to bounding box + /// Attach clip to Tracked Object or to another Clip void AttachToObject(std::string object_id); /// Set the pointer to the trackedObject this clip is attached to @@ -211,9 +211,9 @@ namespace openshot { /// Set the pointer to the clip this clip is attached to void SetAttachedClip(Clip* clipObject); /// Return a pointer to the trackedObject this clip is attached to - std::shared_ptr GetAttachedObject() const { return attachedObject; }; + std::shared_ptr GetAttachedObject() const { return parentTrackedObject; }; /// Return a pointer to the clip this clip is attached to - Clip* GetAttachedClip() const { return attachedClip; }; + Clip* GetAttachedClip() const { return parentClipObject; }; /// Return the type name of the class std::string Name() override { return "Clip"; }; From b875b4d2554631c8989df301ddf43af311e96151 Mon Sep 17 00:00:00 2001 From: Brenno Date: Sat, 30 Jan 2021 17:43:02 -0300 Subject: [PATCH 32/84] Fixed bug in ObjectDetection effect The bug made Openshot crash if two or more ObjectDetection effects were added to the any clip on the timeline. The bug was solved by removing the static int kf_count variable from KalmanTracker. This variable was being incremented even if the ObjectDetection effect was removed from the clip, that caused the wrong Tracked Objects indexes to be added to the trackedObjects map. --- src/sort_filter/KalmanTracker.cpp | 2 -- src/sort_filter/KalmanTracker.h | 10 +++------- src/sort_filter/sort.cpp | 4 ++-- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/src/sort_filter/KalmanTracker.cpp b/src/sort_filter/KalmanTracker.cpp index bb8519c25..726f4cdc6 100644 --- a/src/sort_filter/KalmanTracker.cpp +++ b/src/sort_filter/KalmanTracker.cpp @@ -7,8 +7,6 @@ using namespace std; using namespace cv; -int KalmanTracker::kf_count = 0; - // initialize Kalman filter void KalmanTracker::init_kf( StateType stateMat) diff --git a/src/sort_filter/KalmanTracker.h b/src/sort_filter/KalmanTracker.h index 03360f0da..648e704c8 100644 --- a/src/sort_filter/KalmanTracker.h +++ b/src/sort_filter/KalmanTracker.h @@ -21,18 +21,16 @@ class KalmanTracker m_hits = 0; m_hit_streak = 0; m_age = 0; - m_id = kf_count; - //kf_count++; + m_id = 0; } - KalmanTracker(StateType initRect, float confidence, int classId) : confidence(confidence), classId(classId) + KalmanTracker(StateType initRect, float confidence, int classId, int objectId) : confidence(confidence), classId(classId) { init_kf(initRect); m_time_since_update = 0; m_hits = 0; m_hit_streak = 0; m_age = 0; - m_id = kf_count; - kf_count++; + m_id = objectId; } ~KalmanTracker() @@ -47,8 +45,6 @@ class KalmanTracker StateType get_state(); StateType get_rect_xysr(float cx, float cy, float s, float r); - static int kf_count; - int m_time_since_update; int m_hits; int m_hit_streak; diff --git a/src/sort_filter/sort.cpp b/src/sort_filter/sort.cpp index 03225e179..221cae1ad 100644 --- a/src/sort_filter/sort.cpp +++ b/src/sort_filter/sort.cpp @@ -54,7 +54,7 @@ void SortTracker::update(vector detections_cv, int frame_count, double tb.confidence = confidences[i]; detections.push_back(tb); - KalmanTracker trk = KalmanTracker(detections[i].box, detections[i].confidence, detections[i].classId); + KalmanTracker trk = KalmanTracker(detections[i].box, detections[i].confidence, detections[i].classId, i); trackers.push_back(trk); } return; @@ -167,7 +167,7 @@ void SortTracker::update(vector detections_cv, int frame_count, double // create and initialise new trackers for unmatched detections for (auto umd : unmatchedDetections) { - KalmanTracker tracker = KalmanTracker(detections[umd].box, detections[umd].confidence, detections[umd].classId); + KalmanTracker tracker = KalmanTracker(detections[umd].box, detections[umd].confidence, detections[umd].classId, umd); trackers.push_back(tracker); } From 9df3b51082df8b53a0f1d910002cb4bf8d466fc8 Mon Sep 17 00:00:00 2001 From: Brenno Date: Mon, 1 Feb 2021 15:12:18 -0300 Subject: [PATCH 33/84] Removed unused class KeyframeBase Moved the functions IsPointBeforeX(), InterpolateLinearCurve() , InterpolateBezierCurve() and InterpolateBetween() from KeyFrameBase files to KeyFrame files --- src/CMakeLists.txt | 1 - src/Clip.cpp | 2 +- src/KeyFrame.cpp | 94 ++++++++++++++++++++++++++++++++------- src/KeyFrame.h | 17 +++++-- src/KeyFrameBase.cpp | 103 ------------------------------------------- src/KeyFrameBase.h | 85 ----------------------------------- 6 files changed, 92 insertions(+), 210 deletions(-) delete mode 100644 src/KeyFrameBase.cpp delete mode 100644 src/KeyFrameBase.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index adb7351a5..56e953707 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -86,7 +86,6 @@ set(OPENSHOT_SOURCES FrameMapper.cpp Json.cpp KeyFrame.cpp - KeyFrameBase.cpp TrackedObjectBase.cpp TrackedObjectBBox.cpp OpenShotVersion.cpp diff --git a/src/Clip.cpp b/src/Clip.cpp index 1ac5ac45d..146219330 100644 --- a/src/Clip.cpp +++ b/src/Clip.cpp @@ -1210,7 +1210,7 @@ void Clip::AddEffect(EffectBase* effect) // Sort effects sort_effects(); - // Add Tracker to Timeline + // Add Tracked Object to Timeline if (effect->info.has_tracked_object){ Timeline* parentTimeline = (Timeline *) ParentTimeline(); diff --git a/src/KeyFrame.cpp b/src/KeyFrame.cpp index 3b594a560..a178f2dad 100644 --- a/src/KeyFrame.cpp +++ b/src/KeyFrame.cpp @@ -31,35 +31,95 @@ #include "KeyFrame.h" #include "Exceptions.h" -#include // For assert() -#include // For std::cout -#include // For std::setprecision #include #include #include +#include // For assert() +#include // For std::cout +#include // For std::setprecision using namespace std; using namespace openshot; -namespace{ - template - int64_t SearchBetweenPoints(Point const & left, Point const & right, int64_t const current, Check check) { - int64_t start = left.co.X; - int64_t stop = right.co.X; - while (start < stop) { - int64_t const mid = (start + stop + 1) / 2; - double const value = InterpolateBetween(left, right, mid, 0.01); - if (check(round(value), current)) { - start = mid; - } else { - stop = mid - 1; +namespace openshot{ + + // Check if the X coordinate of a given Point is lower than a given value + bool IsPointBeforeX(Point const & p, double const x) { + return p.co.X < x; + } + + // Linear interpolation between two points + double InterpolateLinearCurve(Point const & left, Point const & right, double const target) { + double const diff_Y = right.co.Y - left.co.Y; + double const diff_X = right.co.X - left.co.X; + double const slope = diff_Y / diff_X; + return left.co.Y + slope * (target - left.co.X); + } + + // Bezier interpolation between two points + double InterpolateBezierCurve(Point const & left, Point const & right, double const target, double const allowed_error) { + double const X_diff = right.co.X - left.co.X; + double const Y_diff = right.co.Y - left.co.Y; + Coordinate const p0 = left.co; + Coordinate const p1 = Coordinate(p0.X + left.handle_right.X * X_diff, p0.Y + left.handle_right.Y * Y_diff); + Coordinate const p2 = Coordinate(p0.X + right.handle_left.X * X_diff, p0.Y + right.handle_left.Y * Y_diff); + Coordinate const p3 = right.co; + + double t = 0.5; + double t_step = 0.25; + do { + // Bernstein polynoms + double B[4] = {1, 3, 3, 1}; + double oneMinTExp = 1; + double tExp = 1; + for (int i = 0; i < 4; ++i, tExp *= t) { + B[i] *= tExp; + } + for (int i = 0; i < 4; ++i, oneMinTExp *= 1 - t) { + B[4 - i - 1] *= oneMinTExp; + } + double const x = p0.X * B[0] + p1.X * B[1] + p2.X * B[2] + p3.X * B[3]; + double const y = p0.Y * B[0] + p1.Y * B[1] + p2.Y * B[2] + p3.Y * B[3]; + if (fabs(target - x) < allowed_error) { + return y; } + if (x > target) { + t -= t_step; + } + else { + t += t_step; + } + t_step /= 2; + } while (true); + } + + // Interpolate two points using the right Point's interpolation method + double InterpolateBetween(Point const & left, Point const & right, double target, double allowed_error) { + assert(left.co.X < target); + assert(target <= right.co.X); + switch (right.interpolation) { + case CONSTANT: return left.co.Y; + case LINEAR: return InterpolateLinearCurve(left, right, target); + case BEZIER: return InterpolateBezierCurve(left, right, target, allowed_error); } - return start; } } - +template +int64_t SearchBetweenPoints(Point const & left, Point const & right, int64_t const current, Check check) { + int64_t start = left.co.X; + int64_t stop = right.co.X; + while (start < stop) { + int64_t const mid = (start + stop + 1) / 2; + double const value = InterpolateBetween(left, right, mid, 0.01); + if (check(round(value), current)) { + start = mid; + } else { + stop = mid - 1; + } + } + return start; +} // Constructor which sets the default point & coordinate at X=1 Keyframe::Keyframe(double value) { diff --git a/src/KeyFrame.h b/src/KeyFrame.h index 7306fd7bc..14dee7bf0 100644 --- a/src/KeyFrame.h +++ b/src/KeyFrame.h @@ -37,10 +37,21 @@ #include "Fraction.h" #include "Point.h" #include "Json.h" -#include "KeyFrameBase.h" namespace openshot { + /// Check if the X coordinate of a given Point is lower than a given value + bool IsPointBeforeX(Point const & p, double const x); + + /// Linear interpolation between two points + double InterpolateLinearCurve(Point const & left, Point const & right, double const target); + + /// Bezier interpolation between two points + double InterpolateBezierCurve(Point const & left, Point const & right, double const target, double const allowed_error); + + /// Interpolate two points using the right Point's interpolation method + double InterpolateBetween(Point const & left, Point const & right, double target, double allowed_error); + /** * @brief A Keyframe is a collection of Point instances, which is used to vary a number or property over time. * @@ -58,7 +69,7 @@ namespace openshot { * kf.PrintValues(); * \endcode */ - class Keyframe : public KeyframeBase { + class Keyframe { private: @@ -143,7 +154,7 @@ namespace openshot { /// Scale all points by a percentage (good for evenly lengthening or shortening an openshot::Keyframe) /// 1.0 = same size, 1.05 = 5% increase, etc... - void ScalePoints(double scale) override; + void ScalePoints(double scale); /// Replace an existing point with a new point void UpdatePoint(int64_t index, Point p); diff --git a/src/KeyFrameBase.cpp b/src/KeyFrameBase.cpp deleted file mode 100644 index 79f4f5281..000000000 --- a/src/KeyFrameBase.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/** - * @file - * @brief Source file for the KeyframeBase class - * @author Jonathan Thomas - * - * @ref License - */ - -/* LICENSE - * - * Copyright (c) 2008-2019 OpenShot Studios, LLC - * . This file is part of - * OpenShot Library (libopenshot), an open-source project dedicated to - * delivering high quality video editing and animation solutions to the - * world. For more information visit . - * - * OpenShot Library (libopenshot) is free software: you can redistribute it - * and/or modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * OpenShot Library (libopenshot) is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with OpenShot Library. If not, see . - */ - -#include "KeyFrameBase.h" -#include -#include -#include - - -namespace openshot{ - - // Check if the X coordinate of a given Point is lower than a given value - bool IsPointBeforeX(Point const & p, double const x) { - return p.co.X < x; - } - - // Linear interpolation between two points - double InterpolateLinearCurve(Point const & left, Point const & right, double const target) { - double const diff_Y = right.co.Y - left.co.Y; - double const diff_X = right.co.X - left.co.X; - double const slope = diff_Y / diff_X; - return left.co.Y + slope * (target - left.co.X); - } - - // Bezier interpolation between two points - double InterpolateBezierCurve(Point const & left, Point const & right, double const target, double const allowed_error) { - double const X_diff = right.co.X - left.co.X; - double const Y_diff = right.co.Y - left.co.Y; - Coordinate const p0 = left.co; - Coordinate const p1 = Coordinate(p0.X + left.handle_right.X * X_diff, p0.Y + left.handle_right.Y * Y_diff); - Coordinate const p2 = Coordinate(p0.X + right.handle_left.X * X_diff, p0.Y + right.handle_left.Y * Y_diff); - Coordinate const p3 = right.co; - - double t = 0.5; - double t_step = 0.25; - do { - // Bernstein polynoms - double B[4] = {1, 3, 3, 1}; - double oneMinTExp = 1; - double tExp = 1; - for (int i = 0; i < 4; ++i, tExp *= t) { - B[i] *= tExp; - } - for (int i = 0; i < 4; ++i, oneMinTExp *= 1 - t) { - B[4 - i - 1] *= oneMinTExp; - } - double const x = p0.X * B[0] + p1.X * B[1] + p2.X * B[2] + p3.X * B[3]; - double const y = p0.Y * B[0] + p1.Y * B[1] + p2.Y * B[2] + p3.Y * B[3]; - if (fabs(target - x) < allowed_error) { - return y; - } - if (x > target) { - t -= t_step; - } - else { - t += t_step; - } - t_step /= 2; - } while (true); - } - - // Interpolate two points using the right Point's interpolation method - double InterpolateBetween(Point const & left, Point const & right, double target, double allowed_error) { - assert(left.co.X < target); - assert(target <= right.co.X); - switch (right.interpolation) { - case CONSTANT: return left.co.Y; - case LINEAR: return InterpolateLinearCurve(left, right, target); - case BEZIER: return InterpolateBezierCurve(left, right, target, allowed_error); - } - } - - KeyframeBase::KeyframeBase(){ - - } -} \ No newline at end of file diff --git a/src/KeyFrameBase.h b/src/KeyFrameBase.h deleted file mode 100644 index 14b94c198..000000000 --- a/src/KeyFrameBase.h +++ /dev/null @@ -1,85 +0,0 @@ -/** - * @file - * @brief Header file for the KeyframeBase class - * @author Jonathan Thomas - * - * @ref License - */ - -/* LICENSE - * - * Copyright (c) 2008-2019 OpenShot Studios, LLC - * . This file is part of - * OpenShot Library (libopenshot), an open-source project dedicated to - * delivering high quality video editing and animation solutions to the - * world. For more information visit . - * - * OpenShot Library (libopenshot) is free software: you can redistribute it - * and/or modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * OpenShot Library (libopenshot) is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with OpenShot Library. If not, see . - */ - -#ifndef OPENSHOT_KEYFRAMEBASE_H -#define OPENSHOT_KEYFRAMEBASE_H - -#include -#include -#include -#include -#include -#include -#include "Exceptions.h" -#include "Fraction.h" -#include "Coordinate.h" -#include "Point.h" -#include "Json.h" - - -namespace openshot { - - /// Check if the X coordinate of a given Point is lower than a given value - bool IsPointBeforeX(Point const & p, double const x); - - /// Linear interpolation between two points - double InterpolateLinearCurve(Point const & left, Point const & right, double const target); - - /// Bezier interpolation between two points - double InterpolateBezierCurve(Point const & left, Point const & right, double const target, double const allowed_error); - - /// Interpolate two points using the right Point's interpolation method - double InterpolateBetween(Point const & left, Point const & right, double target, double allowed_error); - - /** - * @brief This abstract class is the base class of all Keyframes. - * - * A Keyframe is a collection of Point instances, which is used to vary a number or property over time. - * - * Keyframes are used to animate and interpolate values of properties over time. For example, a single property - * can use a Keyframe instead of a constant value. Assume you want to slide an image (from left to right) over - * a video. You can create a Keyframe which will adjust the X value of the image over 100 frames (or however many - * frames the animation needs to last) from the value of 0 to 640. - */ - class KeyframeBase{ - - public: - - /// Blank constructor - KeyframeBase(); - - /// Scale all points by a percentage (good for evenly lengthening or shortening an openshot::Keyframe) - /// 1.0 = same size, 1.05 = 5% increase, etc... - virtual void ScalePoints(double scale) { return; }; - - }; -} // Namespace openshot - -#endif From 2e47325c8fec026cca88a561882ad1a0d6a1fcf0 Mon Sep 17 00:00:00 2001 From: Brenno Date: Thu, 4 Feb 2021 15:09:13 -0300 Subject: [PATCH 34/84] Added support to set the visibility of a Tracked Object Added the property "Keyframe visible" to TrackedObjectBase, so the user can set the Tracked Object to be visible or invisible along the chosen frames. --- src/TrackedObjectBBox.cpp | 9 +++++---- src/TrackedObjectBBox.h | 1 - src/TrackedObjectBase.cpp | 6 ++++-- src/TrackedObjectBase.h | 4 ++++ src/effects/ObjectDetection.cpp | 6 ++++-- src/effects/Tracker.cpp | 5 +++-- 6 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/TrackedObjectBBox.cpp b/src/TrackedObjectBBox.cpp index ed8e152a8..16329acac 100644 --- a/src/TrackedObjectBBox.cpp +++ b/src/TrackedObjectBBox.cpp @@ -323,6 +323,7 @@ Json::Value TrackedObjectBBox::JsonValue() const root["scale_x"] = scale_x.JsonValue(); root["scale_y"] = scale_y.JsonValue(); root["rotation"] = rotation.JsonValue(); + root["visible"] = visible.JsonValue(); // return JsonValue return root; @@ -385,7 +386,9 @@ void TrackedObjectBBox::SetJsonValue(const Json::Value root) scale_y.SetJsonValue(root["scale_y"]); if (!root["rotation"].isNull()) rotation.SetJsonValue(root["rotation"]); - + if (!root["visible"].isNull()) + visible.SetJsonValue(root["visible"]); + return; } @@ -400,9 +403,6 @@ 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 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); @@ -415,6 +415,7 @@ Json::Value TrackedObjectBBox::PropertiesJSON(int64_t requested_frame) const 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["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); // Return formatted string return root; diff --git a/src/TrackedObjectBBox.h b/src/TrackedObjectBBox.h index 182853a46..2cdd27a67 100644 --- a/src/TrackedObjectBBox.h +++ b/src/TrackedObjectBBox.h @@ -157,7 +157,6 @@ namespace openshot class TrackedObjectBBox : public TrackedObjectBase { private: - bool visible; Fraction BaseFps; double TimeScale; diff --git a/src/TrackedObjectBase.cpp b/src/TrackedObjectBase.cpp index 157f55b39..234104de7 100644 --- a/src/TrackedObjectBase.cpp +++ b/src/TrackedObjectBase.cpp @@ -37,13 +37,15 @@ namespace openshot{ // Blank constructor - TrackedObjectBase::TrackedObjectBase(){ + TrackedObjectBase::TrackedObjectBase() : visible(1.0) + { // Initializes the id as "None" id = "None"; } // Default constructor - TrackedObjectBase::TrackedObjectBase(std::string _id){ + TrackedObjectBase::TrackedObjectBase(std::string _id) : visible(1.0) + { Id(_id); } } \ No newline at end of file diff --git a/src/TrackedObjectBase.h b/src/TrackedObjectBase.h index 52499ed04..7d3ee870f 100644 --- a/src/TrackedObjectBase.h +++ b/src/TrackedObjectBase.h @@ -40,6 +40,7 @@ #include "Exceptions.h" #include "Fraction.h" #include "Coordinate.h" +#include "KeyFrame.h" #include "Point.h" #include "Json.h" #include "ClipBase.h" @@ -57,9 +58,12 @@ namespace openshot { private: std::string id; ClipBase* parentClip; + public: + Keyframe visible; + /// Blank constructor TrackedObjectBase(); diff --git a/src/effects/ObjectDetection.cpp b/src/effects/ObjectDetection.cpp index 11bc38e9f..6d0e199cf 100644 --- a/src/effects/ObjectDetection.cpp +++ b/src/effects/ObjectDetection.cpp @@ -104,8 +104,8 @@ std::shared_ptr ObjectDetection::GetFrame(std::shared_ptr frame, i std::shared_ptr trackedObject = std::static_pointer_cast(trackedObject_it->second); // Check if the tracked object has data for this frame - if (trackedObject->Contains(frame_number)){ - + if (trackedObject->Contains(frame_number) && trackedObject->visible.GetValue(frame_number) == 1) + { // Get the bounding-box of given frame BBox trackedBox = trackedObject->GetBox(frame_number); cv::Rect2d box( @@ -316,6 +316,7 @@ Json::Value ObjectDetection::JsonValue() const { root["scale_x"] = selectedObjectJSON["scale_x"]; root["scale_y"] = selectedObjectJSON["scale_y"]; root["rotation"] = selectedObjectJSON["rotation"]; + root["visible"] = selectedObjectJSON["visible"]; } // return JsonValue @@ -374,6 +375,7 @@ void ObjectDetection::SetJsonValue(const Json::Value root) { selectedObjectJSON["scale_x"] = root["scale_x"]; selectedObjectJSON["scale_y"] = root["scale_y"]; selectedObjectJSON["rotation"] = root["rotation"]; + selectedObjectJSON["visible"] = root["visible"]; if (!selectedObjectJSON.isNull()){ auto selectedObject = trackedObjects.at(selectedObjectIndex); if (selectedObject) diff --git a/src/effects/Tracker.cpp b/src/effects/Tracker.cpp index 5b3f278d4..fa9f1a0b7 100644 --- a/src/effects/Tracker.cpp +++ b/src/effects/Tracker.cpp @@ -96,7 +96,7 @@ std::shared_ptr Tracker::GetFrame(std::shared_ptr frame, int64_t f if(!frame_image.empty()) { // Check if track data exists for the requested frame - if (trackedData->Contains(frame_number)) + if (trackedData->Contains(frame_number) && trackedData->visible.GetValue(frame_number) == 1) { // Get the width and height of the image float fw = frame_image.size().width; @@ -181,6 +181,7 @@ Json::Value Tracker::JsonValue() const { root["scale_x"] = trackedObjectJSON["scale_x"]; root["scale_y"] = trackedObjectJSON["scale_y"]; root["rotation"] = trackedObjectJSON["rotation"]; + root["visible"] = trackedObjectJSON["visible"]; } // return JsonValue @@ -256,6 +257,7 @@ void Tracker::SetJsonValue(const Json::Value root) { trackedObjectJSON["scale_x"] = root["scale_x"]; trackedObjectJSON["scale_y"] = root["scale_y"]; trackedObjectJSON["rotation"] = root["rotation"]; + trackedObjectJSON["visible"] = root["visible"]; if (!trackedObjectJSON.isNull()) trackedObject.second->SetJsonValue(trackedObjectJSON); } @@ -288,7 +290,6 @@ std::string Tracker::PropertiesJSON(int64_t requested_frame) const { } // Append effect's properties - root["name"] = add_property_json("Tracker", 0.0, "string", "", NULL, -1, -1, true, requested_frame); root["id"] = add_property_json("ID", 0.0, "string", Id(), NULL, -1, -1, true, requested_frame); root["position"] = add_property_json("Position", Position(), "float", "", NULL, 0, 1000 * 60 * 30, false, requested_frame); root["layer"] = add_property_json("Track", Layer(), "int", "", NULL, 0, 20, false, requested_frame); From d24c2e451c5ea6a21ab08495b9532c2ced60352d Mon Sep 17 00:00:00 2001 From: Brenno Date: Thu, 4 Feb 2021 15:45:33 -0300 Subject: [PATCH 35/84] 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 146219330..3fbd975ef 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 16329acac..cbdc76289 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 234104de7..c1fde78f8 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 7d3ee870f..49f84c942 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 fa9f1a0b7..c46b23117 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 From c60dd400c127d5d612b2d25be0e14e7f4395fb9b Mon Sep 17 00:00:00 2001 From: Brenno Date: Thu, 4 Feb 2021 15:57:30 -0300 Subject: [PATCH 36/84] Updated JSON functions related to Tracked Objects --- src/TrackedObjectBBox.cpp | 2 +- src/TrackedObjectBBox.h | 2 +- src/TrackedObjectBase.h | 3 ++ src/effects/ObjectDetection.cpp | 56 +++++++++----------------------- src/effects/Tracker.cpp | 57 +++++++-------------------------- 5 files changed, 33 insertions(+), 87 deletions(-) diff --git a/src/TrackedObjectBBox.cpp b/src/TrackedObjectBBox.cpp index cbdc76289..6eb005e69 100644 --- a/src/TrackedObjectBBox.cpp +++ b/src/TrackedObjectBBox.cpp @@ -354,7 +354,7 @@ void TrackedObjectBBox::SetJsonValue(const Json::Value root) { // Set the Id by the given JSON object - if (!root["box_id"].isNull()) + if (!root["box_id"].isNull() && root["box_id"].asString() != "None") Id(root["box_id"].asString()); // Set the BaseFps by the given JSON object diff --git a/src/TrackedObjectBBox.h b/src/TrackedObjectBBox.h index 2cdd27a67..693cac8b6 100644 --- a/src/TrackedObjectBBox.h +++ b/src/TrackedObjectBBox.h @@ -187,7 +187,7 @@ namespace openshot /// Check if there is a bounding-box in the given frame 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; + bool ExactlyContains(int64_t frame_number) const override; /// Get the size of BoxVec map int64_t GetLength() const; diff --git a/src/TrackedObjectBase.h b/src/TrackedObjectBase.h index 49f84c942..6d1038ef3 100644 --- a/src/TrackedObjectBase.h +++ b/src/TrackedObjectBase.h @@ -82,6 +82,9 @@ namespace openshot { std::string ChildClipId() const { return childClipId; }; void ChildClipId(std::string _childClipId) { childClipId = _childClipId; }; + /// Check if there is data for the exact frame number + virtual bool ExactlyContains(int64_t frame_number) const { return {}; }; + /// Scale an object's property virtual void ScalePoints(double scale) { return; }; /// Return the main properties of a TrackedObjectBBox instance - such as position, size and rotation diff --git a/src/effects/ObjectDetection.cpp b/src/effects/ObjectDetection.cpp index 6d0e199cf..6be796681 100644 --- a/src/effects/ObjectDetection.cpp +++ b/src/effects/ObjectDetection.cpp @@ -275,7 +275,7 @@ std::string ObjectDetection::GetVisibleObjects(int64_t frame_number) const{ for (const auto& trackedObject : trackedObjects){ // Get the tracked object JSON properties for this frame Json::Value trackedObjectJSON = trackedObject.second->PropertiesJSON(frame_number); - if (trackedObjectJSON["visible"]["value"].asBool()){ + if (trackedObjectJSON["visible"]["value"].asBool() && trackedObject.second->ExactlyContains(frame_number)){ // Save the object's index and ID if it's visible in this frame root["visible_objects_index"].append(trackedObject.first); root["visible_objects_id"].append(trackedObject.second->Id()); @@ -300,8 +300,9 @@ Json::Value ObjectDetection::JsonValue() const { root["type"] = info.class_name; root["protobuf_data_path"] = protobuf_data_path; root["selected_object_index"] = selectedObjectIndex; + + // Add tracked object's IDs to root root["objects_id"] = Json::Value(Json::arrayValue); - for (auto const& trackedObject : trackedObjects){ Json::Value trackedObjectJSON = trackedObject.second->JsonValue(); root["objects_id"].append(trackedObject.second->Id()); @@ -311,12 +312,8 @@ Json::Value ObjectDetection::JsonValue() const { auto selectedObject = trackedObjects.at(selectedObjectIndex); if (selectedObject){ Json::Value selectedObjectJSON = selectedObject->JsonValue(); - root["delta_x"] = selectedObjectJSON["delta_x"]; - root["delta_y"] = selectedObjectJSON["delta_y"]; - root["scale_x"] = selectedObjectJSON["scale_x"]; - root["scale_y"] = selectedObjectJSON["scale_y"]; - root["rotation"] = selectedObjectJSON["rotation"]; - root["visible"] = selectedObjectJSON["visible"]; + for (auto const& key : selectedObjectJSON.getMemberNames()) + root[key] = selectedObjectJSON[key]; } // return JsonValue @@ -346,8 +343,8 @@ void ObjectDetection::SetJsonValue(const Json::Value root) { // Set parent data EffectBase::SetJsonValue(root); // Set data from Json (if key is found) - if (!root["protobuf_data_path"].isNull()){ - protobuf_data_path = (root["protobuf_data_path"].asString()); + if (!root["protobuf_data_path"].isNull() && protobuf_data_path.size() <= 1){ + protobuf_data_path = root["protobuf_data_path"].asString(); if(!LoadObjDetectdData(protobuf_data_path)){ std::cout<<"Invalid protobuf data path"; @@ -359,28 +356,19 @@ void ObjectDetection::SetJsonValue(const Json::Value root) { if (!root["selected_object_index"].isNull()) selectedObjectIndex = root["selected_object_index"].asInt(); - // Set the object's ids + // Set the tracked object's ids if (!root["objects_id"].isNull()){ for (auto const& trackedObject : trackedObjects){ - Json::Value trackedObjectJSON; - trackedObjectJSON["box_id"] = root["objects_id"][trackedObject.first].asString(); - trackedObject.second->SetJsonValue(trackedObjectJSON); + Json::Value trackedObjectJSON; + trackedObjectJSON["box_id"] = root["objects_id"][trackedObject.first].asString(); + trackedObject.second->SetJsonValue(trackedObjectJSON); } } // Set the selected object's properties - Json::Value selectedObjectJSON; - selectedObjectJSON["delta_x"] = root["delta_x"]; - selectedObjectJSON["delta_y"] = root["delta_y"]; - selectedObjectJSON["scale_x"] = root["scale_x"]; - selectedObjectJSON["scale_y"] = root["scale_y"]; - selectedObjectJSON["rotation"] = root["rotation"]; - selectedObjectJSON["visible"] = root["visible"]; - if (!selectedObjectJSON.isNull()){ - auto selectedObject = trackedObjects.at(selectedObjectIndex); - if (selectedObject) - selectedObject->SetJsonValue(selectedObjectJSON); - } + auto selectedObject = trackedObjects.at(selectedObjectIndex); + if (selectedObject) + selectedObject->SetJsonValue(root); } // Get all properties for a specific frame @@ -391,20 +379,8 @@ std::string ObjectDetection::PropertiesJSON(int64_t requested_frame) const { // Add the selected object Json to root auto selectedObject = trackedObjects.at(selectedObjectIndex); - if (selectedObject){ - Json::Value selectedObjectJSON = selectedObject->PropertiesJSON(requested_frame); - root["box_id"] = selectedObjectJSON["box_id"]; - root["visible"] = selectedObjectJSON["visible"]; - root["x1"] = selectedObjectJSON["x1"]; - root["y1"] = selectedObjectJSON["y1"]; - root["x2"] = selectedObjectJSON["x2"]; - root["y2"] = selectedObjectJSON["y2"]; - root["delta_x"] = selectedObjectJSON["delta_x"]; - root["delta_y"] = selectedObjectJSON["delta_y"]; - root["scale_x"] = selectedObjectJSON["scale_x"]; - root["scale_y"] = selectedObjectJSON["scale_y"]; - root["rotation"] = selectedObjectJSON["rotation"]; - } + if (selectedObject) + root = selectedObject->PropertiesJSON(requested_frame); root["selected_object_index"] = add_property_json("Selected Object", selectedObjectIndex, "int", "", NULL, 0, 200, false, requested_frame); 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 c46b23117..ebbdef471 100644 --- a/src/effects/Tracker.cpp +++ b/src/effects/Tracker.cpp @@ -218,13 +218,8 @@ Json::Value Tracker::JsonValue() const { Json::Value trackedObjectJSON = trackedObject.second->JsonValue(); root["objects_id"].append(trackedObject.second->Id()); // Save the trackedObject JSON on root - root["delta_x"] = trackedObjectJSON["delta_x"]; - root["delta_y"] = trackedObjectJSON["delta_y"]; - root["scale_x"] = trackedObjectJSON["scale_x"]; - root["scale_y"] = trackedObjectJSON["scale_y"]; - root["rotation"] = trackedObjectJSON["rotation"]; - root["visible"] = trackedObjectJSON["visible"]; - root["child_clip_id"] = trackedObjectJSON["child_clip_id"]; + for (auto const& key : trackedObjectJSON.getMemberNames()) + root[key] = trackedObjectJSON[key]; } // return JsonValue @@ -274,9 +269,9 @@ void Tracker::SetJsonValue(const Json::Value root) { TimeScale = (double) root["TimeScale"].asDouble(); // Set data from Json (if key is found) - if (!root["protobuf_data_path"].isNull()) + if (!root["protobuf_data_path"].isNull() && protobuf_data_path.size() <= 1) { - protobuf_data_path = (root["protobuf_data_path"].asString()); + protobuf_data_path = root["protobuf_data_path"].asString(); if(!trackedData->LoadBoxData(protobuf_data_path)) { std::cout<<"Invalid protobuf data path"; @@ -284,26 +279,12 @@ void Tracker::SetJsonValue(const Json::Value root) { } } - // Set the object's ids - if (!root["objects_id"].isNull()){ - for (auto const& trackedObject : trackedObjects){ - Json::Value trackedObjectJSON; - trackedObjectJSON["box_id"] = root["objects_id"][trackedObject.first].asString(); - trackedObject.second->SetJsonValue(trackedObjectJSON); - } - } - + // Set the tracked object's properties for (auto const& trackedObject : trackedObjects){ - Json::Value trackedObjectJSON; - trackedObjectJSON["delta_x"] = root["delta_x"]; - trackedObjectJSON["delta_y"] = root["delta_y"]; - trackedObjectJSON["scale_x"] = root["scale_x"]; - 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); + Json::Value trackedObjectJSON = root; + if (!root["objects_id"].isNull()) + trackedObjectJSON["box_id"] = root["objects_id"][trackedObject.first].asString(); + trackedObject.second->SetJsonValue(trackedObjectJSON); } return; @@ -316,23 +297,9 @@ std::string Tracker::PropertiesJSON(int64_t requested_frame) const { // Generate JSON properties list Json::Value root; - // Add trackedObjects IDs to JSON - for (auto const& trackedObject : trackedObjects){ - // Save the trackedObject Id on root - Json::Value trackedObjectJSON = trackedObject.second->PropertiesJSON(requested_frame); - root["box_id"] = trackedObjectJSON["box_id"]; - root["visible"] = trackedObjectJSON["visible"]; - root["x1"] = trackedObjectJSON["x1"]; - root["y1"] = trackedObjectJSON["y1"]; - root["x2"] = trackedObjectJSON["x2"]; - root["y2"] = trackedObjectJSON["y2"]; - root["delta_x"] = trackedObjectJSON["delta_x"]; - root["delta_y"] = trackedObjectJSON["delta_y"]; - root["scale_x"] = trackedObjectJSON["scale_x"]; - root["scale_y"] = trackedObjectJSON["scale_y"]; - root["rotation"] = trackedObjectJSON["rotation"]; - root["child_clip_id"] = trackedObjectJSON["child_clip_id"]; - } + // Add trackedObject properties to JSON + for (auto const& trackedObject : trackedObjects) + root = trackedObject.second->PropertiesJSON(requested_frame); // Append effect's properties root["id"] = add_property_json("ID", 0.0, "string", Id(), NULL, -1, -1, true, requested_frame); From 67895f7c23a0be4fd50b0e23f4acf91535a67870 Mon Sep 17 00:00:00 2001 From: Brenno Date: Thu, 4 Feb 2021 16:11:27 -0300 Subject: [PATCH 37/84] Added support to set an effect's properties by it's parent effect --- src/Clip.cpp | 8 +++- src/EffectBase.cpp | 76 +++++++++++++++++++++++++++++++++++-- src/EffectBase.h | 14 ++++++- src/Timeline.cpp | 19 ++++++++++ src/Timeline.h | 3 ++ src/effects/Bars.cpp | 3 ++ src/effects/Blur.cpp | 3 ++ src/effects/Caption.cpp | 3 ++ src/effects/ChromaKey.cpp | 3 ++ src/effects/ColorShift.cpp | 3 ++ src/effects/Crop.cpp | 3 ++ src/effects/Deinterlace.cpp | 3 ++ src/effects/Hue.cpp | 3 ++ src/effects/Mask.cpp | 3 ++ src/effects/Negate.cpp | 3 ++ src/effects/Pixelate.cpp | 3 ++ src/effects/Saturation.cpp | 3 ++ src/effects/Shift.cpp | 3 ++ src/effects/Stabilizer.cpp | 3 ++ src/effects/Wave.cpp | 3 ++ 20 files changed, 157 insertions(+), 8 deletions(-) diff --git a/src/Clip.cpp b/src/Clip.cpp index 3fbd975ef..eb22d225b 100644 --- a/src/Clip.cpp +++ b/src/Clip.cpp @@ -1210,10 +1210,14 @@ void Clip::AddEffect(EffectBase* effect) // Sort effects sort_effects(); + // Get the parent timeline of this clip + Timeline* parentTimeline = (Timeline *) ParentTimeline(); + + if (parentTimeline) + effect->ParentTimeline(parentTimeline); + // Add Tracked Object to Timeline if (effect->info.has_tracked_object){ - - Timeline* parentTimeline = (Timeline *) ParentTimeline(); // Check if this clip has a parent timeline if (parentTimeline){ diff --git a/src/EffectBase.cpp b/src/EffectBase.cpp index 4d4ed241d..6f51b45db 100644 --- a/src/EffectBase.cpp +++ b/src/EffectBase.cpp @@ -30,6 +30,7 @@ #include "EffectBase.h" #include "Exceptions.h" +#include "Timeline.h" using namespace openshot; @@ -44,11 +45,14 @@ void EffectBase::InitEffectInfo() Order(0); ParentClip(NULL); + parentEffect = NULL; + info.has_video = false; info.has_audio = false; + info.has_tracked_object = false; info.name = ""; info.description = ""; - info.has_tracked_object = false; + info.parent_effect_id = "None"; } // Display file information @@ -91,6 +95,7 @@ Json::Value EffectBase::JsonValue() const { root["name"] = info.name; root["class_name"] = info.class_name; root["description"] = info.description; + root["parent_effect_id"] = info.parent_effect_id; root["has_video"] = info.has_video; root["has_audio"] = info.has_audio; root["has_tracked_object"] = info.has_tracked_object; @@ -101,12 +106,12 @@ Json::Value EffectBase::JsonValue() const { } // Load JSON string into this object -void EffectBase::SetJson(const std::string value) { +void EffectBase::SetJson(std::string value) { // Parse JSON string into JSON objects try { - const Json::Value root = openshot::stringToJson(value); + Json::Value root = openshot::stringToJson(value); // Set all values that match SetJsonValue(root); } @@ -118,7 +123,29 @@ void EffectBase::SetJson(const std::string value) { } // Load Json::Value into this object -void EffectBase::SetJsonValue(const Json::Value root) { +void EffectBase::SetJsonValue(Json::Value root) { + + if (ParentTimeline()){ + // Get parent timeline + Timeline* parentTimeline = (Timeline *) ParentTimeline(); + + // Get the list of effects on the timeline + std::list effects = parentTimeline->ClipEffects(); + + // Loop through the effects + for (auto const& effect : effects){ + // Set the properties of all effects which parentEffect points to this + if (effect->info.parent_effect_id == this->Id()) + effect->SetJsonValue(root); + } + } + + // Set this effect properties with the parent effect properties (except the id and parent_effect_id) + if (parentEffect){ + root = parentEffect->JsonValue(); + root["id"] = this->Id(); + root["parent_effect_id"] = this->info.parent_effect_id; + } // Set parent data ClipBase::SetJsonValue(root); @@ -126,6 +153,14 @@ void EffectBase::SetJsonValue(const Json::Value root) { // Set data from Json (if key is found) if (!root["order"].isNull()) Order(root["order"].asInt()); + + if (!root["parent_effect_id"].isNull()){ + info.parent_effect_id = root["parent_effect_id"].asString(); + if (info.parent_effect_id.size() > 0 && info.parent_effect_id != "None" && parentEffect == NULL) + SetParentEffect(info.parent_effect_id); + else + parentEffect = NULL; + } } // Generate Json::Value for this object @@ -152,3 +187,36 @@ openshot::ClipBase* EffectBase::ParentClip() { void EffectBase::ParentClip(openshot::ClipBase* new_clip) { clip = new_clip; } + +// Set the parent effect from which this properties will be set to +void EffectBase::SetParentEffect(std::string parentEffect_id) { + + // Get parent Timeline + Timeline* parentTimeline = (Timeline *) ParentTimeline(); + + if (parentTimeline){ + + // Get a pointer to the parentEffect + EffectBase* parentEffectPtr = parentTimeline->GetClipEffect(parentEffect_id); + + if (parentEffectPtr){ + // Set the parent Effect + parentEffect = parentEffectPtr; + + // Set the properties of this effect with the parent effect's properties + Json::Value EffectJSON = parentEffect->JsonValue(); + EffectJSON["id"] = this->Id(); + EffectJSON["parent_effect_id"] = this->info.parent_effect_id; + this->SetJsonValue(EffectJSON); + } + } + return; +} + +// Return the ID of this effect's parent clip +std::string EffectBase::ParentClipId() const{ + if(clip) + return clip->Id(); + else + return "None"; +} \ No newline at end of file diff --git a/src/EffectBase.h b/src/EffectBase.h index ae5cf257f..8b45442b9 100644 --- a/src/EffectBase.h +++ b/src/EffectBase.h @@ -53,6 +53,7 @@ namespace openshot 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 + std::string parent_effect_id; ///< Id of the parent effect (if there is one) 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 bool has_tracked_object; ///< Determines if this effect track objects through the clip @@ -75,6 +76,9 @@ namespace openshot public: + /// Parent effect (which properties will set this effect properties) + EffectBase* parentEffect; + /// Map of Tracked Object's by their indices (used by Effects that track objects on clips) std::map > trackedObjects; @@ -96,15 +100,21 @@ namespace openshot /// Set parent clip object of this effect void ParentClip(openshot::ClipBase* new_clip); + + /// Set the parent effect from which this properties will be set to + void SetParentEffect(std::string parentEffect_id); + + /// Return the ID of this effect's parent clip + std::string ParentClipId() const; /// Get the indexes and IDs of all visible objects in the given frame virtual std::string GetVisibleObjects(int64_t frame_number) const {return {}; }; /// Get and Set JSON methods virtual std::string Json() const = 0; ///< Generate JSON string of this object - virtual void SetJson(const std::string value) = 0; ///< Load JSON string into this object + virtual void SetJson(std::string value) = 0; ///< Load JSON string into this object virtual Json::Value JsonValue() const = 0; ///< Generate Json::Value for this object - virtual void SetJsonValue(const Json::Value root) = 0; ///< Load Json::Value into this object + virtual void SetJsonValue(Json::Value root) = 0; ///< Load Json::Value into this object virtual std::string Json(int64_t requested_frame) const{ return {}; diff --git a/src/Timeline.cpp b/src/Timeline.cpp index 161b008d3..614dca8f8 100644 --- a/src/Timeline.cpp +++ b/src/Timeline.cpp @@ -432,6 +432,25 @@ openshot::EffectBase* Timeline::GetClipEffect(const std::string& id) return nullptr; } +// Return the list of effects on all clips +std::list Timeline::ClipEffects() const { + + // Initialize the list + std::list ClipEffects; + + // Loop through all clips + for (const auto& clip : clips) { + + // Get the clip's list of effects + std::list clipEffects = clip->Effects(); + + // Append the clip's effects to the list + ClipEffects.insert(ClipEffects.end(), clipEffects.begin(), clipEffects.end()); + } + + return ClipEffects; +} + // Compute the end time of the latest timeline element double Timeline::GetMaxTime() { double last_clip = 0.0; diff --git a/src/Timeline.h b/src/Timeline.h index b17d164e1..afc7f8053 100644 --- a/src/Timeline.h +++ b/src/Timeline.h @@ -296,6 +296,9 @@ namespace openshot { /// Return the list of effects on the timeline std::list Effects() { return effects; }; + /// Return the list of effects on all clips + std::list ClipEffects() const; + /// Get the cache object used by this reader openshot::CacheBase* GetCache() override { return final_cache; }; diff --git a/src/effects/Bars.cpp b/src/effects/Bars.cpp index 562ce8c37..20fdef55a 100644 --- a/src/effects/Bars.cpp +++ b/src/effects/Bars.cpp @@ -196,6 +196,9 @@ std::string Bars::PropertiesJSON(int64_t requested_frame) const { root["right"] = add_property_json("Right Size", right.GetValue(requested_frame), "float", "", &right, 0.0, 0.5, false, requested_frame); root["bottom"] = add_property_json("Bottom Size", bottom.GetValue(requested_frame), "float", "", &bottom, 0.0, 0.5, false, requested_frame); + // Set the parent effect which properties this effect will inherit + root["parent_effect_id"] = add_property_json("Parent Effect ID", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); + // Return formatted string return root.toStyledString(); } diff --git a/src/effects/Blur.cpp b/src/effects/Blur.cpp index b301f1e85..da025a672 100644 --- a/src/effects/Blur.cpp +++ b/src/effects/Blur.cpp @@ -243,6 +243,9 @@ std::string Blur::PropertiesJSON(int64_t requested_frame) const { root["sigma"] = add_property_json("Sigma", sigma.GetValue(requested_frame), "float", "", &sigma, 0, 100, false, requested_frame); root["iterations"] = add_property_json("Iterations", iterations.GetValue(requested_frame), "float", "", &iterations, 0, 100, false, requested_frame); + // Set the parent effect which properties this effect will inherit + root["parent_effect_id"] = add_property_json("Parent Effect ID", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); + // Return formatted string return root.toStyledString(); } diff --git a/src/effects/Caption.cpp b/src/effects/Caption.cpp index 73c53cc24..c27eaa8ed 100644 --- a/src/effects/Caption.cpp +++ b/src/effects/Caption.cpp @@ -429,6 +429,9 @@ std::string Caption::PropertiesJSON(int64_t requested_frame) const { root["caption_text"] = add_property_json("Captions", 0.0, "caption", caption_text, NULL, -1, -1, false, requested_frame); root["caption_font"] = add_property_json("Font", 0.0, "font", font_name, NULL, -1, -1, false, requested_frame); + // Set the parent effect which properties this effect will inherit + root["parent_effect_id"] = add_property_json("Parent Effect ID", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); + // Return formatted string return root.toStyledString(); } diff --git a/src/effects/ChromaKey.cpp b/src/effects/ChromaKey.cpp index 721c6a0ec..b4e358e04 100644 --- a/src/effects/ChromaKey.cpp +++ b/src/effects/ChromaKey.cpp @@ -170,6 +170,9 @@ std::string ChromaKey::PropertiesJSON(int64_t requested_frame) const { root["color"]["green"] = add_property_json("Green", color.green.GetValue(requested_frame), "float", "", &color.green, 0, 255, false, requested_frame); root["fuzz"] = add_property_json("Fuzz", fuzz.GetValue(requested_frame), "float", "", &fuzz, 0, 25, false, requested_frame); + // Set the parent effect which properties this effect will inherit + root["parent_effect_id"] = add_property_json("Parent Effect ID", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); + // Return formatted string return root.toStyledString(); } diff --git a/src/effects/ColorShift.cpp b/src/effects/ColorShift.cpp index 1140d0253..c32ee4a13 100644 --- a/src/effects/ColorShift.cpp +++ b/src/effects/ColorShift.cpp @@ -282,6 +282,9 @@ std::string ColorShift::PropertiesJSON(int64_t requested_frame) const { root["alpha_x"] = add_property_json("Alpha X Shift", alpha_x.GetValue(requested_frame), "float", "", &alpha_x, -1, 1, false, requested_frame); root["alpha_y"] = add_property_json("Alpha Y Shift", alpha_y.GetValue(requested_frame), "float", "", &alpha_y, -1, 1, false, requested_frame); + // Set the parent effect which properties this effect will inherit + root["parent_effect_id"] = add_property_json("Parent Effect ID", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); + // Return formatted string return root.toStyledString(); } diff --git a/src/effects/Crop.cpp b/src/effects/Crop.cpp index 6b3c6f8a6..3e3eff31f 100644 --- a/src/effects/Crop.cpp +++ b/src/effects/Crop.cpp @@ -189,6 +189,9 @@ std::string Crop::PropertiesJSON(int64_t requested_frame) const { root["right"] = add_property_json("Right Size", right.GetValue(requested_frame), "float", "", &right, 0.0, 1.0, false, requested_frame); root["bottom"] = add_property_json("Bottom Size", bottom.GetValue(requested_frame), "float", "", &bottom, 0.0, 1.0, false, requested_frame); + // Set the parent effect which properties this effect will inherit + root["parent_effect_id"] = add_property_json("Parent Effect ID", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); + // Return formatted string return root.toStyledString(); } diff --git a/src/effects/Deinterlace.cpp b/src/effects/Deinterlace.cpp index 6d4dfa152..2fe571a9e 100644 --- a/src/effects/Deinterlace.cpp +++ b/src/effects/Deinterlace.cpp @@ -162,6 +162,9 @@ std::string Deinterlace::PropertiesJSON(int64_t requested_frame) const { root["isOdd"]["choices"].append(add_property_choice_json("Yes", true, isOdd)); root["isOdd"]["choices"].append(add_property_choice_json("No", false, isOdd)); + // Set the parent effect which properties this effect will inherit + root["parent_effect_id"] = add_property_json("Parent Effect ID", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); + // Return formatted string return root.toStyledString(); } diff --git a/src/effects/Hue.cpp b/src/effects/Hue.cpp index f2c50c62b..355bb0679 100644 --- a/src/effects/Hue.cpp +++ b/src/effects/Hue.cpp @@ -164,6 +164,9 @@ std::string Hue::PropertiesJSON(int64_t requested_frame) const { // Keyframes root["hue"] = add_property_json("Hue", hue.GetValue(requested_frame), "float", "", &hue, 0.0, 1.0, false, requested_frame); + // Set the parent effect which properties this effect will inherit + root["parent_effect_id"] = add_property_json("Parent Effect ID", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); + // Return formatted string return root.toStyledString(); } diff --git a/src/effects/Mask.cpp b/src/effects/Mask.cpp index 75e38a6ad..92b912193 100644 --- a/src/effects/Mask.cpp +++ b/src/effects/Mask.cpp @@ -293,6 +293,9 @@ std::string Mask::PropertiesJSON(int64_t requested_frame) const { else root["reader"] = add_property_json("Source", 0.0, "reader", "{}", NULL, 0, 1, false, requested_frame); + // Set the parent effect which properties this effect will inherit + root["parent_effect_id"] = add_property_json("Parent Effect ID", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); + // Return formatted string return root.toStyledString(); } diff --git a/src/effects/Negate.cpp b/src/effects/Negate.cpp index c6772b31d..a0483e934 100644 --- a/src/effects/Negate.cpp +++ b/src/effects/Negate.cpp @@ -113,6 +113,9 @@ std::string Negate::PropertiesJSON(int64_t requested_frame) const { root["end"] = add_property_json("End", End(), "float", "", NULL, 0, 30 * 60 * 60 * 48, false, requested_frame); root["duration"] = add_property_json("Duration", Duration(), "float", "", NULL, 0, 30 * 60 * 60 * 48, true, requested_frame); + // Set the parent effect which properties this effect will inherit + root["parent_effect_id"] = add_property_json("Parent Effect ID", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); + // Return formatted string return root.toStyledString(); } diff --git a/src/effects/Pixelate.cpp b/src/effects/Pixelate.cpp index 6d1962bbb..7761ea366 100644 --- a/src/effects/Pixelate.cpp +++ b/src/effects/Pixelate.cpp @@ -184,6 +184,9 @@ std::string Pixelate::PropertiesJSON(int64_t requested_frame) const { root["right"] = add_property_json("Right Margin", right.GetValue(requested_frame), "float", "", &right, 0.0, 1.0, false, requested_frame); root["bottom"] = add_property_json("Bottom Margin", bottom.GetValue(requested_frame), "float", "", &bottom, 0.0, 1.0, false, requested_frame); + // Set the parent effect which properties this effect will inherit + root["parent_effect_id"] = add_property_json("Parent Effect ID", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); + // Return formatted string return root.toStyledString(); } diff --git a/src/effects/Saturation.cpp b/src/effects/Saturation.cpp index 119c30651..894a50e4c 100644 --- a/src/effects/Saturation.cpp +++ b/src/effects/Saturation.cpp @@ -235,6 +235,9 @@ std::string Saturation::PropertiesJSON(int64_t requested_frame) const { root["saturation_G"] = add_property_json("Saturation (Green)", saturation_G.GetValue(requested_frame), "float", "", &saturation_G, 0.0, 4.0, false, requested_frame); root["saturation_B"] = add_property_json("Saturation (Blue)", saturation_B.GetValue(requested_frame), "float", "", &saturation_B, 0.0, 4.0, false, requested_frame); + // Set the parent effect which properties this effect will inherit + root["parent_effect_id"] = add_property_json("Parent Effect ID", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); + // Return formatted string return root.toStyledString(); } diff --git a/src/effects/Shift.cpp b/src/effects/Shift.cpp index 38b5be584..45b8bf6f5 100644 --- a/src/effects/Shift.cpp +++ b/src/effects/Shift.cpp @@ -199,6 +199,9 @@ std::string Shift::PropertiesJSON(int64_t requested_frame) const { root["x"] = add_property_json("X Shift", x.GetValue(requested_frame), "float", "", &x, -1, 1, false, requested_frame); root["y"] = add_property_json("Y Shift", y.GetValue(requested_frame), "float", "", &y, -1, 1, false, requested_frame); + // Set the parent effect which properties this effect will inherit + root["parent_effect_id"] = add_property_json("Parent Effect ID", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); + // Return formatted string return root.toStyledString(); } diff --git a/src/effects/Stabilizer.cpp b/src/effects/Stabilizer.cpp index baf531dc0..6e6042480 100644 --- a/src/effects/Stabilizer.cpp +++ b/src/effects/Stabilizer.cpp @@ -239,6 +239,9 @@ std::string Stabilizer::PropertiesJSON(int64_t requested_frame) const { root["zoom"] = add_property_json("Zoom", zoom.GetValue(requested_frame), "float", "", &zoom, 0.0, 2.0, false, requested_frame); + // Set the parent effect which properties this effect will inherit + root["parent_effect_id"] = add_property_json("Parent Effect ID", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); + // Return formatted string return root.toStyledString(); } diff --git a/src/effects/Wave.cpp b/src/effects/Wave.cpp index ff8a8230b..5fdbf94db 100644 --- a/src/effects/Wave.cpp +++ b/src/effects/Wave.cpp @@ -187,6 +187,9 @@ std::string Wave::PropertiesJSON(int64_t requested_frame) const { root["shift_x"] = add_property_json("X Shift", shift_x.GetValue(requested_frame), "float", "", &shift_x, 0.0, 1000.0, false, requested_frame); root["speed_y"] = add_property_json("Vertical speed", speed_y.GetValue(requested_frame), "float", "", &speed_y, 0.0, 300.0, false, requested_frame); + // Set the parent effect which properties this effect will inherit + root["parent_effect_id"] = add_property_json("Parent Effect ID", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); + // Return formatted string return root.toStyledString(); } From b71f67e6385603a1977bd78d5fae2fe6877eaac8 Mon Sep 17 00:00:00 2001 From: Brenno Date: Thu, 4 Feb 2021 16:24:03 -0300 Subject: [PATCH 38/84] Minor fix --- src/effects/Brightness.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/effects/Brightness.cpp b/src/effects/Brightness.cpp index dbb80f376..c1f796f80 100644 --- a/src/effects/Brightness.cpp +++ b/src/effects/Brightness.cpp @@ -163,6 +163,9 @@ std::string Brightness::PropertiesJSON(int64_t requested_frame) const { root["brightness"] = add_property_json("Brightness", brightness.GetValue(requested_frame), "float", "", &brightness, -1.0, 1.0, false, requested_frame); root["contrast"] = add_property_json("Contrast", contrast.GetValue(requested_frame), "float", "", &contrast, 0.0, 100.0, false, requested_frame); + // Set the parent effect which properties this effect will inherit + root["parent_effect_id"] = add_property_json("Parent Effect ID", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); + // Return formatted string return root.toStyledString(); } From 1f4d33dfe85996040235f46aeccb4f0f8bb23e58 Mon Sep 17 00:00:00 2001 From: Brenno Date: Mon, 15 Mar 2021 21:45:31 -0300 Subject: [PATCH 39/84] Using normalized initial bounding box on CVTracker --- src/CVTracker.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/CVTracker.cpp b/src/CVTracker.cpp index f86448594..74cd46b1d 100644 --- a/src/CVTracker.cpp +++ b/src/CVTracker.cpp @@ -108,6 +108,12 @@ void CVTracker::trackClip(openshot::Clip& video, size_t _start, size_t _end, boo // Grab OpenCV Mat image cv::Mat cvimage = f->GetImageCV(); + if(frame == start){ + // Take the normalized inital bounding box and multiply to the current video shape + bbox = cv::Rect2d(bbox.x*cvimage.cols,bbox.y*cvimage.rows,bbox.width*cvimage.cols, + bbox.height*cvimage.rows); + } + // Pass the first frame to initialize the tracker if(!trackerInit){ @@ -284,10 +290,10 @@ void CVTracker::SetJsonValue(const Json::Value root) { } if (!root["region"].isNull()){ - double x = root["region"]["x"].asDouble(); - double y = root["region"]["y"].asDouble(); - double w = root["region"]["width"].asDouble(); - double h = root["region"]["height"].asDouble(); + double x = root["region"]["normalized_x"].asDouble(); + double y = root["region"]["normalized_y"].asDouble(); + double w = root["region"]["normalized_width"].asDouble(); + double h = root["region"]["normalized_height"].asDouble(); cv::Rect2d prev_bbox(x,y,w,h); bbox = prev_bbox; } From a33497a63091d5bdbe360832d1f390a6cc9f70b9 Mon Sep 17 00:00:00 2001 From: Brenno Date: Tue, 16 Mar 2021 13:15:55 -0300 Subject: [PATCH 40/84] Added jitter filter on Tracked boxes --- src/CVTracker.cpp | 42 +++++++++++++++++++++++++++--------------- src/CVTracker.h | 3 ++- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/src/CVTracker.cpp b/src/CVTracker.cpp index 74cd46b1d..5eab0d4cf 100644 --- a/src/CVTracker.cpp +++ b/src/CVTracker.cpp @@ -178,30 +178,42 @@ bool CVTracker::trackFrame(cv::Mat &frame, size_t frameId){ float fw = frame.size().width; float fh = frame.size().height; - std::vector bboxes = {bbox}; - std::vector confidence = {1.0}; - std::vector classId = {1}; - - sort.update(bboxes, frameId, sqrt(pow(frame.rows, 2) + pow(frame.cols, 2)), confidence, classId); - - for(auto TBox : sort.frameTrackingResult) - bbox = TBox.box; - + cv::Rect2d filtered_box = filter_box_jitter(frameId); // Add new frame data - trackedDataById[frameId] = FrameData(frameId, 0, (bbox.x)/fw, - (bbox.y)/fh, - (bbox.x+bbox.width)/fw, - (bbox.y+bbox.height)/fh); + trackedDataById[frameId] = FrameData(frameId, 0, (filtered_box.x)/fw, + (filtered_box.y)/fh, + (filtered_box.x+filtered_box.width)/fw, + (filtered_box.y+filtered_box.height)/fh); } else { - // Add new frame data - trackedDataById[frameId] = FrameData(frameId); + // Copy the last frame data if the tracker get lost + trackedDataById[frameId] = trackedDataById[frameId-1]; } return ok; } +cv::Rect2d CVTracker::filter_box_jitter(size_t frameId){ + // get tracked data for the previous frame + float last_box_width = trackedDataById[frameId-1].x2 - trackedDataById[frameId-1].x1; + float last_box_height = trackedDataById[frameId-1].y2 - trackedDataById[frameId-1].y1; + + float curr_box_width = bbox.width; + float curr_box_height = bbox.height; + // keep the last width and height if the difference is less than 1% + float threshold = 0.01; + + cv::Rect2d filtered_box = bbox; + if(std::abs(1-(curr_box_width/last_box_width)) <= threshold){ + filtered_box.width = last_box_width; + } + if(std::abs(1-(curr_box_height/last_box_height)) <= threshold){ + filtered_box.height = last_box_height; + } + return filtered_box; +} + bool CVTracker::SaveTrackedData(){ // Create tracker message pb_tracker::Tracker trackerMessage; diff --git a/src/CVTracker.h b/src/CVTracker.h index 918072ce0..f5a090cf6 100644 --- a/src/CVTracker.h +++ b/src/CVTracker.h @@ -122,7 +122,8 @@ namespace openshot // Track object in the hole clip or in a given interval // If start, end and process_interval are passed as argument, clip will be processed in [start,end) void trackClip(openshot::Clip& video, size_t _start=0, size_t _end=0, bool process_interval=false); - + // Filter current bounding box jitter + cv::Rect2d filter_box_jitter(size_t frameId); // Get tracked data for a given frame FrameData GetTrackedData(size_t frameId); From 7272ff0928b44bb18fac0c85d26e7302b3c9597d Mon Sep 17 00:00:00 2001 From: Brenno Date: Thu, 18 Mar 2021 12:25:22 -0300 Subject: [PATCH 41/84] Allow the user to hide the blue bounding box on the Tracker effect This will still keep the child clip visible --- src/TrackedObjectBBox.cpp | 7 +++++++ src/TrackedObjectBase.cpp | 13 ++++++++++++- src/TrackedObjectBase.h | 4 ++++ src/effects/Tracker.cpp | 4 +++- 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/TrackedObjectBBox.cpp b/src/TrackedObjectBBox.cpp index 6eb005e69..c58aaca9e 100644 --- a/src/TrackedObjectBBox.cpp +++ b/src/TrackedObjectBBox.cpp @@ -326,6 +326,7 @@ Json::Value TrackedObjectBBox::JsonValue() const root["scale_y"] = scale_y.JsonValue(); root["rotation"] = rotation.JsonValue(); root["visible"] = visible.JsonValue(); + root["draw_box"] = draw_box.JsonValue(); // return JsonValue return root; @@ -394,6 +395,8 @@ void TrackedObjectBBox::SetJsonValue(const Json::Value root) rotation.SetJsonValue(root["rotation"]); if (!root["visible"].isNull()) visible.SetJsonValue(root["visible"]); + if (!root["draw_box"].isNull()) + draw_box.SetJsonValue(root["draw_box"]); return; } @@ -425,6 +428,10 @@ 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))); // Return formatted string return root; diff --git a/src/TrackedObjectBase.cpp b/src/TrackedObjectBase.cpp index c1fde78f8..780a9f53c 100644 --- a/src/TrackedObjectBase.cpp +++ b/src/TrackedObjectBase.cpp @@ -37,7 +37,7 @@ namespace openshot{ // Blank constructor - TrackedObjectBase::TrackedObjectBase() : visible(1.0) + TrackedObjectBase::TrackedObjectBase() : visible(1.0), draw_box(1) { // Initializes the id as "None" id = "None"; @@ -50,4 +50,15 @@ namespace openshot{ Id(_id); childClipId = "None"; } + + Json::Value TrackedObjectBase::add_property_choice_json(std::string name, int value, int selected_value) const { + // Create choice + Json::Value new_choice = Json::Value(Json::objectValue); + new_choice["name"] = name; + new_choice["value"] = value; + new_choice["selected"] = (value == selected_value); + + // return JsonValue + return new_choice; + } } \ No newline at end of file diff --git a/src/TrackedObjectBase.h b/src/TrackedObjectBase.h index 6d1038ef3..20e70fcf6 100644 --- a/src/TrackedObjectBase.h +++ b/src/TrackedObjectBase.h @@ -64,6 +64,7 @@ namespace openshot { public: Keyframe visible; + Keyframe draw_box; /// Blank constructor TrackedObjectBase(); @@ -104,6 +105,9 @@ namespace openshot { /// Get all properties for a specific frame (perfect for a UI to display the current state /// of all properties at any time) virtual Json::Value PropertiesJSON(int64_t requested_frame) const = 0; + /// Generate JSON choice for a property (dropdown properties) + Json::Value add_property_choice_json(std::string name, int value, int selected_value) const; + }; } // Namespace openshot diff --git a/src/effects/Tracker.cpp b/src/effects/Tracker.cpp index ebbdef471..bc9aff542 100644 --- a/src/effects/Tracker.cpp +++ b/src/effects/Tracker.cpp @@ -105,7 +105,9 @@ std::shared_ptr Tracker::GetFrame(std::shared_ptr frame, int64_t f if(!frame_image.empty()) { // Check if track data exists for the requested frame - if (trackedData->Contains(frame_number) && trackedData->visible.GetValue(frame_number) == 1) + if (trackedData->Contains(frame_number) && + trackedData->visible.GetValue(frame_number) == 1 && + trackedData->draw_box.GetValue(frame_number) == 1) { // Get the width and height of the image float fw = frame_image.size().width; From 3729188f18376d42ed29fd82cd4a65fa8774cd35 Mon Sep 17 00:00:00 2001 From: Brenno Date: Thu, 18 Mar 2021 13:05:21 -0300 Subject: [PATCH 42/84] Protect against linking the tracked object with the parent clip --- src/TrackedObjectBBox.cpp | 12 +++++++++--- src/TrackedObjectBase.cpp | 13 +++++++------ src/TrackedObjectBase.h | 2 +- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/TrackedObjectBBox.cpp b/src/TrackedObjectBBox.cpp index c58aaca9e..19cc80929 100644 --- a/src/TrackedObjectBBox.cpp +++ b/src/TrackedObjectBBox.cpp @@ -378,9 +378,15 @@ 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 id of the child clip + // Does not allow to link to the parent clip + if (!root["child_clip_id"].isNull()){ + Clip* parentClip = (Clip *) ParentClip(); + + if(parentClip && (root["child_clip_id"].asString() != parentClip->Id())){ + ChildClipId(root["child_clip_id"].asString()); + } + } // Set the Keyframes by the given JSON object if (!root["delta_x"].isNull()) diff --git a/src/TrackedObjectBase.cpp b/src/TrackedObjectBase.cpp index 780a9f53c..acdc9e399 100644 --- a/src/TrackedObjectBase.cpp +++ b/src/TrackedObjectBase.cpp @@ -33,16 +33,16 @@ #include #include - -namespace openshot{ +namespace openshot +{ // Blank constructor - TrackedObjectBase::TrackedObjectBase() : visible(1.0), draw_box(1) + TrackedObjectBase::TrackedObjectBase() : visible(1.0), draw_box(1) { // Initializes the id as "None" id = "None"; childClipId = "None"; - } + } // Default constructor TrackedObjectBase::TrackedObjectBase(std::string _id) : visible(1.0) @@ -51,7 +51,8 @@ namespace openshot{ childClipId = "None"; } - Json::Value TrackedObjectBase::add_property_choice_json(std::string name, int value, int selected_value) const { + Json::Value TrackedObjectBase::add_property_choice_json(std::string name, int value, int selected_value) const + { // Create choice Json::Value new_choice = Json::Value(Json::objectValue); new_choice["name"] = name; @@ -61,4 +62,4 @@ namespace openshot{ // return JsonValue return new_choice; } -} \ No newline at end of file +} // namespace openshot \ No newline at end of file diff --git a/src/TrackedObjectBase.h b/src/TrackedObjectBase.h index 20e70fcf6..c0f6c6601 100644 --- a/src/TrackedObjectBase.h +++ b/src/TrackedObjectBase.h @@ -55,7 +55,7 @@ namespace openshot { * predicted along the frames of a clip. */ class TrackedObjectBase { - private: + protected: std::string id; std::string childClipId; From aa3068239de59938d7f28aac1b5c442cc2f6fbf8 Mon Sep 17 00:00:00 2001 From: Brenno Date: Thu, 18 Mar 2021 13:13:34 -0300 Subject: [PATCH 43/84] Fixed draw_box scope --- src/effects/Tracker.cpp | 57 +++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/src/effects/Tracker.cpp b/src/effects/Tracker.cpp index bc9aff542..8ea249428 100644 --- a/src/effects/Tracker.cpp +++ b/src/effects/Tracker.cpp @@ -102,20 +102,20 @@ std::shared_ptr Tracker::GetFrame(std::shared_ptr frame, int64_t f std::shared_ptr childClipImage = nullptr; // Check if frame isn't NULL - if(!frame_image.empty()) + if(!frame_image.empty() && + trackedData->Contains(frame_number) && + trackedData->visible.GetValue(frame_number) == 1) { - // Check if track data exists for the requested frame - if (trackedData->Contains(frame_number) && - trackedData->visible.GetValue(frame_number) == 1 && - trackedData->draw_box.GetValue(frame_number) == 1) - { - // Get the width and height of the image - float fw = frame_image.size().width; - float fh = frame_image.size().height; + // Get the width and height of the image + float fw = frame_image.size().width; + float fh = frame_image.size().height; - // Get the bounding-box of given frame - BBox fd = trackedData->GetBox(frame_number); + // Get the bounding-box of given frame + BBox fd = trackedData->GetBox(frame_number); + // Check if track data exists for the requested frame + if (trackedData->draw_box.GetValue(frame_number) == 1) + { // 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) ), @@ -128,25 +128,26 @@ 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) ); - } + } + + // 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) ); } } - } + } + } // Set image with drawn box to frame From 013a61bab9d7976b99bedd40411a27ee1f6e16f1 Mon Sep 17 00:00:00 2001 From: Brenno Date: Fri, 26 Mar 2021 21:10:10 -0300 Subject: [PATCH 44/84] Renamed "Parent Effect ID" to "Parent" --- src/effects/Bars.cpp | 2 +- src/effects/Blur.cpp | 2 +- src/effects/Brightness.cpp | 2 +- src/effects/Caption.cpp | 2 +- src/effects/ChromaKey.cpp | 2 +- src/effects/ColorShift.cpp | 2 +- src/effects/Crop.cpp | 2 +- src/effects/Deinterlace.cpp | 2 +- src/effects/Hue.cpp | 2 +- src/effects/Mask.cpp | 2 +- src/effects/Negate.cpp | 2 +- src/effects/Pixelate.cpp | 2 +- src/effects/Saturation.cpp | 2 +- src/effects/Shift.cpp | 2 +- src/effects/Stabilizer.cpp | 2 +- src/effects/Wave.cpp | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/effects/Bars.cpp b/src/effects/Bars.cpp index 20fdef55a..7a19a96b0 100644 --- a/src/effects/Bars.cpp +++ b/src/effects/Bars.cpp @@ -197,7 +197,7 @@ std::string Bars::PropertiesJSON(int64_t requested_frame) const { root["bottom"] = add_property_json("Bottom Size", bottom.GetValue(requested_frame), "float", "", &bottom, 0.0, 0.5, false, requested_frame); // Set the parent effect which properties this effect will inherit - root["parent_effect_id"] = add_property_json("Parent Effect ID", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); + root["parent_effect_id"] = add_property_json("Parent", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); // Return formatted string return root.toStyledString(); diff --git a/src/effects/Blur.cpp b/src/effects/Blur.cpp index da025a672..169286cba 100644 --- a/src/effects/Blur.cpp +++ b/src/effects/Blur.cpp @@ -244,7 +244,7 @@ std::string Blur::PropertiesJSON(int64_t requested_frame) const { root["iterations"] = add_property_json("Iterations", iterations.GetValue(requested_frame), "float", "", &iterations, 0, 100, false, requested_frame); // Set the parent effect which properties this effect will inherit - root["parent_effect_id"] = add_property_json("Parent Effect ID", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); + root["parent_effect_id"] = add_property_json("Parent", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); // Return formatted string return root.toStyledString(); diff --git a/src/effects/Brightness.cpp b/src/effects/Brightness.cpp index c1f796f80..4b80f9d78 100644 --- a/src/effects/Brightness.cpp +++ b/src/effects/Brightness.cpp @@ -164,7 +164,7 @@ std::string Brightness::PropertiesJSON(int64_t requested_frame) const { root["contrast"] = add_property_json("Contrast", contrast.GetValue(requested_frame), "float", "", &contrast, 0.0, 100.0, false, requested_frame); // Set the parent effect which properties this effect will inherit - root["parent_effect_id"] = add_property_json("Parent Effect ID", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); + root["parent_effect_id"] = add_property_json("Parent", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); // Return formatted string return root.toStyledString(); diff --git a/src/effects/Caption.cpp b/src/effects/Caption.cpp index c27eaa8ed..ec56468f0 100644 --- a/src/effects/Caption.cpp +++ b/src/effects/Caption.cpp @@ -430,7 +430,7 @@ std::string Caption::PropertiesJSON(int64_t requested_frame) const { root["caption_font"] = add_property_json("Font", 0.0, "font", font_name, NULL, -1, -1, false, requested_frame); // Set the parent effect which properties this effect will inherit - root["parent_effect_id"] = add_property_json("Parent Effect ID", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); + root["parent_effect_id"] = add_property_json("Parent", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); // Return formatted string return root.toStyledString(); diff --git a/src/effects/ChromaKey.cpp b/src/effects/ChromaKey.cpp index b4e358e04..f66707e8b 100644 --- a/src/effects/ChromaKey.cpp +++ b/src/effects/ChromaKey.cpp @@ -171,7 +171,7 @@ std::string ChromaKey::PropertiesJSON(int64_t requested_frame) const { root["fuzz"] = add_property_json("Fuzz", fuzz.GetValue(requested_frame), "float", "", &fuzz, 0, 25, false, requested_frame); // Set the parent effect which properties this effect will inherit - root["parent_effect_id"] = add_property_json("Parent Effect ID", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); + root["parent_effect_id"] = add_property_json("Parent", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); // Return formatted string return root.toStyledString(); diff --git a/src/effects/ColorShift.cpp b/src/effects/ColorShift.cpp index c32ee4a13..6b1323e3f 100644 --- a/src/effects/ColorShift.cpp +++ b/src/effects/ColorShift.cpp @@ -283,7 +283,7 @@ std::string ColorShift::PropertiesJSON(int64_t requested_frame) const { root["alpha_y"] = add_property_json("Alpha Y Shift", alpha_y.GetValue(requested_frame), "float", "", &alpha_y, -1, 1, false, requested_frame); // Set the parent effect which properties this effect will inherit - root["parent_effect_id"] = add_property_json("Parent Effect ID", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); + root["parent_effect_id"] = add_property_json("Parent", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); // Return formatted string return root.toStyledString(); diff --git a/src/effects/Crop.cpp b/src/effects/Crop.cpp index 3e3eff31f..bf89b2575 100644 --- a/src/effects/Crop.cpp +++ b/src/effects/Crop.cpp @@ -190,7 +190,7 @@ std::string Crop::PropertiesJSON(int64_t requested_frame) const { root["bottom"] = add_property_json("Bottom Size", bottom.GetValue(requested_frame), "float", "", &bottom, 0.0, 1.0, false, requested_frame); // Set the parent effect which properties this effect will inherit - root["parent_effect_id"] = add_property_json("Parent Effect ID", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); + root["parent_effect_id"] = add_property_json("Parent", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); // Return formatted string return root.toStyledString(); diff --git a/src/effects/Deinterlace.cpp b/src/effects/Deinterlace.cpp index 2fe571a9e..870f4a887 100644 --- a/src/effects/Deinterlace.cpp +++ b/src/effects/Deinterlace.cpp @@ -163,7 +163,7 @@ std::string Deinterlace::PropertiesJSON(int64_t requested_frame) const { root["isOdd"]["choices"].append(add_property_choice_json("No", false, isOdd)); // Set the parent effect which properties this effect will inherit - root["parent_effect_id"] = add_property_json("Parent Effect ID", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); + root["parent_effect_id"] = add_property_json("Parent", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); // Return formatted string return root.toStyledString(); diff --git a/src/effects/Hue.cpp b/src/effects/Hue.cpp index 355bb0679..29db7c53e 100644 --- a/src/effects/Hue.cpp +++ b/src/effects/Hue.cpp @@ -165,7 +165,7 @@ std::string Hue::PropertiesJSON(int64_t requested_frame) const { root["hue"] = add_property_json("Hue", hue.GetValue(requested_frame), "float", "", &hue, 0.0, 1.0, false, requested_frame); // Set the parent effect which properties this effect will inherit - root["parent_effect_id"] = add_property_json("Parent Effect ID", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); + root["parent_effect_id"] = add_property_json("Parent", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); // Return formatted string return root.toStyledString(); diff --git a/src/effects/Mask.cpp b/src/effects/Mask.cpp index 92b912193..0d5d335e0 100644 --- a/src/effects/Mask.cpp +++ b/src/effects/Mask.cpp @@ -294,7 +294,7 @@ std::string Mask::PropertiesJSON(int64_t requested_frame) const { root["reader"] = add_property_json("Source", 0.0, "reader", "{}", NULL, 0, 1, false, requested_frame); // Set the parent effect which properties this effect will inherit - root["parent_effect_id"] = add_property_json("Parent Effect ID", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); + root["parent_effect_id"] = add_property_json("Parent", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); // Return formatted string return root.toStyledString(); diff --git a/src/effects/Negate.cpp b/src/effects/Negate.cpp index a0483e934..50db5f2f9 100644 --- a/src/effects/Negate.cpp +++ b/src/effects/Negate.cpp @@ -114,7 +114,7 @@ std::string Negate::PropertiesJSON(int64_t requested_frame) const { root["duration"] = add_property_json("Duration", Duration(), "float", "", NULL, 0, 30 * 60 * 60 * 48, true, requested_frame); // Set the parent effect which properties this effect will inherit - root["parent_effect_id"] = add_property_json("Parent Effect ID", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); + root["parent_effect_id"] = add_property_json("Parent", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); // Return formatted string return root.toStyledString(); diff --git a/src/effects/Pixelate.cpp b/src/effects/Pixelate.cpp index 7761ea366..a68097922 100644 --- a/src/effects/Pixelate.cpp +++ b/src/effects/Pixelate.cpp @@ -185,7 +185,7 @@ std::string Pixelate::PropertiesJSON(int64_t requested_frame) const { root["bottom"] = add_property_json("Bottom Margin", bottom.GetValue(requested_frame), "float", "", &bottom, 0.0, 1.0, false, requested_frame); // Set the parent effect which properties this effect will inherit - root["parent_effect_id"] = add_property_json("Parent Effect ID", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); + root["parent_effect_id"] = add_property_json("Parent", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); // Return formatted string return root.toStyledString(); diff --git a/src/effects/Saturation.cpp b/src/effects/Saturation.cpp index 894a50e4c..4b9f12410 100644 --- a/src/effects/Saturation.cpp +++ b/src/effects/Saturation.cpp @@ -236,7 +236,7 @@ std::string Saturation::PropertiesJSON(int64_t requested_frame) const { root["saturation_B"] = add_property_json("Saturation (Blue)", saturation_B.GetValue(requested_frame), "float", "", &saturation_B, 0.0, 4.0, false, requested_frame); // Set the parent effect which properties this effect will inherit - root["parent_effect_id"] = add_property_json("Parent Effect ID", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); + root["parent_effect_id"] = add_property_json("Parent", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); // Return formatted string return root.toStyledString(); diff --git a/src/effects/Shift.cpp b/src/effects/Shift.cpp index 45b8bf6f5..0a9c496d5 100644 --- a/src/effects/Shift.cpp +++ b/src/effects/Shift.cpp @@ -200,7 +200,7 @@ std::string Shift::PropertiesJSON(int64_t requested_frame) const { root["y"] = add_property_json("Y Shift", y.GetValue(requested_frame), "float", "", &y, -1, 1, false, requested_frame); // Set the parent effect which properties this effect will inherit - root["parent_effect_id"] = add_property_json("Parent Effect ID", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); + root["parent_effect_id"] = add_property_json("Parent", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); // Return formatted string return root.toStyledString(); diff --git a/src/effects/Stabilizer.cpp b/src/effects/Stabilizer.cpp index 6e6042480..087959c26 100644 --- a/src/effects/Stabilizer.cpp +++ b/src/effects/Stabilizer.cpp @@ -240,7 +240,7 @@ std::string Stabilizer::PropertiesJSON(int64_t requested_frame) const { root["zoom"] = add_property_json("Zoom", zoom.GetValue(requested_frame), "float", "", &zoom, 0.0, 2.0, false, requested_frame); // Set the parent effect which properties this effect will inherit - root["parent_effect_id"] = add_property_json("Parent Effect ID", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); + root["parent_effect_id"] = add_property_json("Parent", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); // Return formatted string return root.toStyledString(); diff --git a/src/effects/Wave.cpp b/src/effects/Wave.cpp index 5fdbf94db..07e0372a5 100644 --- a/src/effects/Wave.cpp +++ b/src/effects/Wave.cpp @@ -188,7 +188,7 @@ std::string Wave::PropertiesJSON(int64_t requested_frame) const { root["speed_y"] = add_property_json("Vertical speed", speed_y.GetValue(requested_frame), "float", "", &speed_y, 0.0, 300.0, false, requested_frame); // Set the parent effect which properties this effect will inherit - root["parent_effect_id"] = add_property_json("Parent Effect ID", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); + root["parent_effect_id"] = add_property_json("Parent", 0.0, "string", info.parent_effect_id, NULL, -1, -1, false, requested_frame); // Return formatted string return root.toStyledString(); From 65e33a5b7736fb3523d8381d001d6c1dac073a8b Mon Sep 17 00:00:00 2001 From: Brenno Date: Fri, 26 Mar 2021 21:50:41 -0300 Subject: [PATCH 45/84] Renamed "Parent Object ID" to "Parent" --- src/Clip.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Clip.cpp b/src/Clip.cpp index 0928f90af..e94b7d0c3 100644 --- a/src/Clip.cpp +++ b/src/Clip.cpp @@ -747,9 +747,9 @@ std::string Clip::PropertiesJSON(int64_t requested_frame) const { root["mixing"] = add_property_json("Volume Mixing", mixing, "int", "", NULL, 0, 2, false, requested_frame); root["waveform"] = add_property_json("Waveform", waveform, "int", "", NULL, 0, 1, false, requested_frame); if (!parentObjectId.empty()) { - root["parentObjectId"] = add_property_json("Parent Object ID", 0.0, "string", parentObjectId, NULL, -1, -1, false, requested_frame); + root["parentObjectId"] = add_property_json("Parent", 0.0, "string", parentObjectId, NULL, -1, -1, false, requested_frame); } else { - root["parentObjectId"] = add_property_json("Parent Object ID", 0.0, "string", "None", NULL, -1, -1, false, requested_frame); + root["parentObjectId"] = add_property_json("Parent", 0.0, "string", "None", NULL, -1, -1, false, requested_frame); } // Add gravity choices (dropdown style) root["gravity"]["choices"].append(add_property_choice_json("Top Left", GRAVITY_TOP_LEFT, gravity)); From 4ea85ec859150d902900a86bbdfa5702d26285d0 Mon Sep 17 00:00:00 2001 From: Brenno Date: Sat, 27 Mar 2021 22:50:01 -0300 Subject: [PATCH 46/84] 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)); } } From c55efd189723a6b13065b2278ec5e0508b481a55 Mon Sep 17 00:00:00 2001 From: Brenno Date: Sun, 28 Mar 2021 15:55:22 -0300 Subject: [PATCH 47/84] 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 647031de2..301e2d5f4 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 6b9518134..d6a0d2d79 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 e1d1e16fa..bf058ea72 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 e52100941..749ec1b4b 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 From 6b6b6d5a3d5d44518b74c35b88c9b2f2286b6940 Mon Sep 17 00:00:00 2001 From: Brenno Date: Wed, 7 Apr 2021 21:49:58 -0300 Subject: [PATCH 48/84] Protecting ObjectDetection when no object is found --- src/TrackedObjectBBox.cpp | 2 +- src/effects/ObjectDetection.cpp | 28 +++++++++++++++++----------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/TrackedObjectBBox.cpp b/src/TrackedObjectBBox.cpp index 301e2d5f4..2099e509a 100644 --- a/src/TrackedObjectBBox.cpp +++ b/src/TrackedObjectBBox.cpp @@ -388,7 +388,7 @@ void TrackedObjectBBox::SetJsonValue(const Json::Value root) // Set the id of the child clip // Does not allow to link to the parent clip - if (!root["child_clip_id"].isNull()){ + if (!root["child_clip_id"].isNull() && root["box_id"].asString() != "None"){ Clip* parentClip = (Clip *) ParentClip(); if(parentClip && (root["child_clip_id"].asString() != parentClip->Id())){ diff --git a/src/effects/ObjectDetection.cpp b/src/effects/ObjectDetection.cpp index 6be796681..a6b6d975e 100644 --- a/src/effects/ObjectDetection.cpp +++ b/src/effects/ObjectDetection.cpp @@ -309,11 +309,13 @@ Json::Value ObjectDetection::JsonValue() const { } // Add the selected object Json to root - auto selectedObject = trackedObjects.at(selectedObjectIndex); - if (selectedObject){ - Json::Value selectedObjectJSON = selectedObject->JsonValue(); - for (auto const& key : selectedObjectJSON.getMemberNames()) - root[key] = selectedObjectJSON[key]; + if(trackedObjects.count(selectedObjectIndex) != 0){ + auto selectedObject = trackedObjects.at(selectedObjectIndex); + if (selectedObject){ + Json::Value selectedObjectJSON = selectedObject->JsonValue(); + for (auto const& key : selectedObjectJSON.getMemberNames()) + root[key] = selectedObjectJSON[key]; + } } // return JsonValue @@ -366,9 +368,11 @@ void ObjectDetection::SetJsonValue(const Json::Value root) { } // Set the selected object's properties - auto selectedObject = trackedObjects.at(selectedObjectIndex); - if (selectedObject) - selectedObject->SetJsonValue(root); + if(trackedObjects.count(selectedObjectIndex) != 0){ + auto selectedObject = trackedObjects.at(selectedObjectIndex); + if (selectedObject) + selectedObject->SetJsonValue(root); + } } // Get all properties for a specific frame @@ -378,9 +382,11 @@ std::string ObjectDetection::PropertiesJSON(int64_t requested_frame) const { Json::Value root; // Add the selected object Json to root - auto selectedObject = trackedObjects.at(selectedObjectIndex); - if (selectedObject) - root = selectedObject->PropertiesJSON(requested_frame); + if(trackedObjects.count(selectedObjectIndex) != 0){ + auto selectedObject = trackedObjects.at(selectedObjectIndex); + if (selectedObject) + root = selectedObject->PropertiesJSON(requested_frame); + } root["selected_object_index"] = add_property_json("Selected Object", selectedObjectIndex, "int", "", NULL, 0, 200, false, requested_frame); root["id"] = add_property_json("ID", 0.0, "string", Id(), NULL, -1, -1, true, requested_frame); From 1e32ef8d20f3803a76ef260f003de3162dd66cc8 Mon Sep 17 00:00:00 2001 From: Brenno Date: Thu, 8 Apr 2021 21:32:39 -0300 Subject: [PATCH 49/84] Fixed ObjectDetection crash (disabled effect parenting) --- src/EffectBase.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/EffectBase.cpp b/src/EffectBase.cpp index 6f51b45db..8f453ca50 100644 --- a/src/EffectBase.cpp +++ b/src/EffectBase.cpp @@ -132,12 +132,16 @@ void EffectBase::SetJsonValue(Json::Value root) { // Get the list of effects on the timeline std::list effects = parentTimeline->ClipEffects(); - // Loop through the effects - for (auto const& effect : effects){ - // Set the properties of all effects which parentEffect points to this - if (effect->info.parent_effect_id == this->Id()) - effect->SetJsonValue(root); - } + // TODO: Fix recursive call for Object Detection + + // // Loop through the effects and check if we have a child effect linked to this effect + // for (auto const& effect : effects){ + // // Set the properties of all effects which parentEffect points to this + // if ((effect->info.parent_effect_id == this->Id()) && (effect->Id() != this->Id())) + // std::cout<<"passou3 \n"; + + // effect->SetJsonValue(root); + // } } // Set this effect properties with the parent effect properties (except the id and parent_effect_id) @@ -218,5 +222,5 @@ std::string EffectBase::ParentClipId() const{ if(clip) return clip->Id(); else - return "None"; + return ""; } \ No newline at end of file From a106ed5671478d11ac69ba73f484f8ea2dce8b5d Mon Sep 17 00:00:00 2001 From: Brenno Date: Thu, 8 Apr 2021 21:36:59 -0300 Subject: [PATCH 50/84] Added Color selection, stroke size and opacity to ObjectDetection rectangles --- src/effects/ObjectDetection.cpp | 79 ++++++++++++++++++++++++++++----- src/effects/ObjectDetection.h | 3 ++ 2 files changed, 72 insertions(+), 10 deletions(-) diff --git a/src/effects/ObjectDetection.cpp b/src/effects/ObjectDetection.cpp index a6b6d975e..215d493e5 100644 --- a/src/effects/ObjectDetection.cpp +++ b/src/effects/ObjectDetection.cpp @@ -104,18 +104,34 @@ std::shared_ptr ObjectDetection::GetFrame(std::shared_ptr frame, i std::shared_ptr trackedObject = std::static_pointer_cast(trackedObject_it->second); // Check if the tracked object has data for this frame - if (trackedObject->Contains(frame_number) && trackedObject->visible.GetValue(frame_number) == 1) + if (trackedObject->Contains(frame_number) && + trackedObject->visible.GetValue(frame_number) == 1) { // Get the bounding-box of given frame BBox trackedBox = trackedObject->GetBox(frame_number); - cv::Rect2d box( - (int)( (trackedBox.cx-trackedBox.width/2)*fw), - (int)( (trackedBox.cy-trackedBox.height/2)*fh), - (int)( trackedBox.width*fw), - (int)( trackedBox.height*fh) - ); - drawPred(detections.classIds.at(i), detections.confidences.at(i), - box, cv_image, detections.objectIds.at(i)); + + std::vector stroke_rgba = trackedObject->stroke.GetColorRGBA(frame_number); + int stroke_width = trackedObject->stroke_width.GetValue(frame_number); + float stroke_alpha = trackedObject->stroke_alpha.GetValue(frame_number); + std::vector bg_rgba = trackedObject->background.GetColorRGBA(frame_number); + float bg_alpha = trackedObject->background_alpha.GetValue(frame_number); + + // Create a rotated rectangle object that holds the bounding box + cv::RotatedRect box ( cv::Point2f( (int)(trackedBox.cx*fw), (int)(trackedBox.cy*fh) ), + cv::Size2f( (int)(trackedBox.width*fw), (int)(trackedBox.height*fh) ), + (int) (trackedBox.angle) ); + + DrawRectangleRGBA(cv_image, box, bg_rgba, bg_alpha, 1, true); + DrawRectangleRGBA(cv_image, box, stroke_rgba, stroke_alpha, stroke_width, false); + + // cv::Rect2d box( + // (int)( (trackedBox.cx-trackedBox.width/2)*fw), + // (int)( (trackedBox.cy-trackedBox.height/2)*fh), + // (int)( trackedBox.width*fw), + // (int)( trackedBox.height*fh) + // ); + // drawPred(detections.classIds.at(i), detections.confidences.at(i), + // box, cv_image, detections.objectIds.at(i)); } } } @@ -127,6 +143,46 @@ std::shared_ptr ObjectDetection::GetFrame(std::shared_ptr frame, i return frame; } +void ObjectDetection::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); + } +} + void ObjectDetection::drawPred(int classId, float conf, cv::Rect2d box, cv::Mat& frame, int objectNumber) { @@ -328,6 +384,7 @@ void ObjectDetection::SetJson(const std::string value) { // Parse JSON string into JSON objects try { + std::cout<<"entrou no objectDetection SetJson \n"< color, float alpha, int thickness, bool is_background); + public: From 94992117a9800019ac7e22f75fcfbe615d6c4e99 Mon Sep 17 00:00:00 2001 From: Brenno Date: Thu, 8 Apr 2021 22:07:03 -0300 Subject: [PATCH 51/84] Added default class colors --- src/TrackedObjectBBox.cpp | 7 +++++++ src/TrackedObjectBBox.h | 1 + src/effects/ObjectDetection.cpp | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/TrackedObjectBBox.cpp b/src/TrackedObjectBBox.cpp index 2099e509a..f4288876e 100644 --- a/src/TrackedObjectBBox.cpp +++ b/src/TrackedObjectBBox.cpp @@ -48,6 +48,13 @@ TrackedObjectBBox::TrackedObjectBBox() : delta_x(0.0), delta_y(0.0), scale_x(1.0 return; } +TrackedObjectBBox::TrackedObjectBBox(int Red, int Green, int Blue, int Alfa) : 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.0), stroke_alpha(0.0), background_corner(0), + stroke(Red,Green,Blue,Alfa), background(0,0,255,0) +{ + this->TimeScale = 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) diff --git a/src/TrackedObjectBBox.h b/src/TrackedObjectBBox.h index d6a0d2d79..e50f3cf8b 100644 --- a/src/TrackedObjectBBox.h +++ b/src/TrackedObjectBBox.h @@ -179,6 +179,7 @@ namespace openshot /// Default Constructor TrackedObjectBBox(); + TrackedObjectBBox(int Red, int Green, int Blue, int Alfa); /// Add a BBox to the BoxVec map void AddBox(int64_t _frame_num, float _cx, float _cy, float _width, float _height, float _angle) override; diff --git a/src/effects/ObjectDetection.cpp b/src/effects/ObjectDetection.cpp index 215d493e5..48c996151 100644 --- a/src/effects/ObjectDetection.cpp +++ b/src/effects/ObjectDetection.cpp @@ -281,7 +281,7 @@ bool ObjectDetection::LoadObjDetectdData(std::string inputFilePath){ else { // There is no tracked object with that id, so insert a new one - TrackedObjectBBox trackedObj; + TrackedObjectBBox trackedObj((int)classesColor[classId](0), (int)classesColor[classId](1), (int)classesColor[classId](2), (int)0); trackedObj.AddBox(id, x+(w/2), y+(h/2), w, h, 0.0); std::shared_ptr trackedObjPtr = std::make_shared(trackedObj); trackedObjects.insert({objectId, trackedObjPtr}); From 9fb4c4ae32a514a71dbcad4cb47c74e8b894af51 Mon Sep 17 00:00:00 2001 From: Brenno Date: Fri, 9 Apr 2021 00:07:19 -0300 Subject: [PATCH 52/84] Added confidence threshold --- src/effects/ObjectDetection.cpp | 54 ++++++++++++++++++++++++--------- src/effects/ObjectDetection.h | 5 +++ 2 files changed, 45 insertions(+), 14 deletions(-) diff --git a/src/effects/ObjectDetection.cpp b/src/effects/ObjectDetection.cpp index 48c996151..a85272beb 100644 --- a/src/effects/ObjectDetection.cpp +++ b/src/effects/ObjectDetection.cpp @@ -94,6 +94,11 @@ std::shared_ptr ObjectDetection::GetFrame(std::shared_ptr frame, i DetectionData detections = detectionsData[frame_number]; for(int i = 0; i ObjectDetection::GetFrame(std::shared_ptr frame, i float bg_alpha = trackedObject->background_alpha.GetValue(frame_number); // Create a rotated rectangle object that holds the bounding box - cv::RotatedRect box ( cv::Point2f( (int)(trackedBox.cx*fw), (int)(trackedBox.cy*fh) ), - cv::Size2f( (int)(trackedBox.width*fw), (int)(trackedBox.height*fh) ), - (int) (trackedBox.angle) ); + // cv::RotatedRect box ( cv::Point2f( (int)(trackedBox.cx*fw), (int)(trackedBox.cy*fh) ), + // cv::Size2f( (int)(trackedBox.width*fw), (int)(trackedBox.height*fh) ), + // (int) (trackedBox.angle) ); - DrawRectangleRGBA(cv_image, box, bg_rgba, bg_alpha, 1, true); - DrawRectangleRGBA(cv_image, box, stroke_rgba, stroke_alpha, stroke_width, false); + // DrawRectangleRGBA(cv_image, box, bg_rgba, bg_alpha, 1, true); + // DrawRectangleRGBA(cv_image, box, stroke_rgba, stroke_alpha, stroke_width, false); - // cv::Rect2d box( - // (int)( (trackedBox.cx-trackedBox.width/2)*fw), - // (int)( (trackedBox.cy-trackedBox.height/2)*fh), - // (int)( trackedBox.width*fw), - // (int)( trackedBox.height*fh) - // ); - // drawPred(detections.classIds.at(i), detections.confidences.at(i), - // box, cv_image, detections.objectIds.at(i)); + cv::Rect2d box( + (int)( (trackedBox.cx-trackedBox.width/2)*fw), + (int)( (trackedBox.cy-trackedBox.height/2)*fh), + (int)( trackedBox.width*fw), + (int)( trackedBox.height*fh) + ); + drawPred(detections.classIds.at(i), detections.confidences.at(i), + box, cv_image, detections.objectIds.at(i)); } } } @@ -327,15 +332,30 @@ std::string ObjectDetection::GetVisibleObjects(int64_t frame_number) const{ root["visible_objects_index"] = Json::Value(Json::arrayValue); root["visible_objects_id"] = Json::Value(Json::arrayValue); + // Check if track data exists for the requested frame + if (detectionsData.find(frame_number) == detectionsData.end()){ + return root.toStyledString(); + } + DetectionData detections = detectionsData.at(frame_number); + // Iterate through the tracked objects + int idx = 0; for (const auto& trackedObject : trackedObjects){ + // Does not show boxes with confidence below the threshold + if(detections.confidences.at(idx) < confidence_threshold){ + continue; + } + // Get the tracked object JSON properties for this frame Json::Value trackedObjectJSON = trackedObject.second->PropertiesJSON(frame_number); - if (trackedObjectJSON["visible"]["value"].asBool() && trackedObject.second->ExactlyContains(frame_number)){ + + if (trackedObjectJSON["visible"]["value"].asBool() && + trackedObject.second->ExactlyContains(frame_number)){ // Save the object's index and ID if it's visible in this frame root["visible_objects_index"].append(trackedObject.first); root["visible_objects_id"].append(trackedObject.second->Id()); } + idx++; } return root.toStyledString(); @@ -356,6 +376,7 @@ Json::Value ObjectDetection::JsonValue() const { root["type"] = info.class_name; root["protobuf_data_path"] = protobuf_data_path; root["selected_object_index"] = selectedObjectIndex; + root["confidence_threshold"] = confidence_threshold; // Add tracked object's IDs to root root["objects_id"] = Json::Value(Json::arrayValue); @@ -416,6 +437,10 @@ void ObjectDetection::SetJsonValue(const Json::Value root) { // Set the selected object index if (!root["selected_object_index"].isNull()) selectedObjectIndex = root["selected_object_index"].asInt(); + + // Set the selected object index + if (!root["confidence_threshold"].isNull()) + confidence_threshold = root["confidence_threshold"].asFloat(); // Set the tracked object's ids if (!root["objects_id"].isNull()){ @@ -454,6 +479,7 @@ std::string ObjectDetection::PropertiesJSON(int64_t requested_frame) const { root["start"] = add_property_json("Start", Start(), "float", "", NULL, 0, 1000 * 60 * 30, false, requested_frame); root["end"] = add_property_json("End", End(), "float", "", NULL, 0, 1000 * 60 * 30, false, requested_frame); root["duration"] = add_property_json("Duration", Duration(), "float", "", NULL, 0, 1000 * 60 * 30, true, requested_frame); + root["confidence_threshold"] = add_property_json("Confidence Theshold", confidence_threshold, "float", "", NULL, 0, 1, false, requested_frame); // Return formatted string return root.toStyledString(); diff --git a/src/effects/ObjectDetection.h b/src/effects/ObjectDetection.h index 822746cb7..bc4d6bed3 100644 --- a/src/effects/ObjectDetection.h +++ b/src/effects/ObjectDetection.h @@ -79,6 +79,11 @@ namespace openshot std::vector classesColor; + /// Minimum confidence value to display the detected objects + float confidence_threshold = 0.5; + /// Contain the user selected classes for visualization + std::vector display_classes; + /// Init effect settings void init_effect_details(); From 5e9f5e3f52c7a4d96d95e8efdc0e43e0a9b2870f Mon Sep 17 00:00:00 2001 From: Brenno Date: Fri, 9 Apr 2021 22:19:12 -0300 Subject: [PATCH 53/84] Added class filter and updated visualization --- src/effects/ObjectDetection.cpp | 297 ++++++++++++++++++-------------- src/effects/ObjectDetection.h | 6 +- 2 files changed, 176 insertions(+), 127 deletions(-) diff --git a/src/effects/ObjectDetection.cpp b/src/effects/ObjectDetection.cpp index a85272beb..dbb00522c 100644 --- a/src/effects/ObjectDetection.cpp +++ b/src/effects/ObjectDetection.cpp @@ -40,7 +40,7 @@ using namespace openshot; ObjectDetection::ObjectDetection(std::string clipObDetectDataPath) { // Init effect properties - init_effect_details(); + init_effect_details(); // Tries to load the tracker data from protobuf LoadObjDetectdData(clipObDetectDataPath); @@ -52,8 +52,8 @@ ObjectDetection::ObjectDetection(std::string clipObDetectDataPath) // Default constructor ObjectDetection::ObjectDetection() { - // Init effect properties - init_effect_details(); + // Init effect properties + init_effect_details(); // Initialize the selected object index as the first object index selectedObjectIndex = trackedObjects.begin()->first; @@ -62,15 +62,15 @@ ObjectDetection::ObjectDetection() // Init effect settings void ObjectDetection::init_effect_details() { - /// Initialize the values of the EffectInfo struct. - InitEffectInfo(); - - /// Set the effect info - info.class_name = "Object Detector"; - info.name = "Object Detector"; - info.description = "Detect objects through the video."; - info.has_audio = false; - info.has_video = true; + /// Initialize the values of the EffectInfo struct. + InitEffectInfo(); + + /// Set the effect info + info.class_name = "Object Detector"; + info.name = "Object Detector"; + info.description = "Detect objects through the video."; + info.has_audio = false; + info.has_video = true; info.has_tracked_object = true; } @@ -79,7 +79,7 @@ void ObjectDetection::init_effect_details() std::shared_ptr ObjectDetection::GetFrame(std::shared_ptr frame, int64_t frame_number) { // Get the frame's image - cv::Mat cv_image = frame->GetImageCV(); + cv::Mat cv_image = frame->GetImageCV(); // Check if frame isn't NULL if(cv_image.empty()){ @@ -98,6 +98,11 @@ std::shared_ptr ObjectDetection::GetFrame(std::shared_ptr frame, i if(detections.confidences.at(i) < confidence_threshold){ continue; } + // Just display selected classes + if( display_classes.size() > 0 && + std::find(display_classes.begin(), display_classes.end(), classNames[detections.classIds.at(i)]) == display_classes.end()){ + continue; + } // Get the object id int objectId = detections.objectIds.at(i); @@ -136,81 +141,103 @@ std::shared_ptr ObjectDetection::GetFrame(std::shared_ptr frame, i (int)( trackedBox.height*fh) ); drawPred(detections.classIds.at(i), detections.confidences.at(i), - box, cv_image, detections.objectIds.at(i)); + box, cv_image, detections.objectIds.at(i), bg_rgba, bg_alpha, 1, true); + drawPred(detections.classIds.at(i), detections.confidences.at(i), + box, cv_image, detections.objectIds.at(i), stroke_rgba, stroke_alpha, stroke_width, false); } } } - // Set image with drawn box to frame - // If the input image is NULL or doesn't have tracking data, it's returned as it came - frame->SetImageCV(cv_image); + // Update Qt image with new Opencv frame + frame->SetImageCV(cv_image); - return frame; + return frame; } -void ObjectDetection::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); - } +void ObjectDetection::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); + } } -void ObjectDetection::drawPred(int classId, float conf, cv::Rect2d box, cv::Mat& frame, int objectNumber) +void ObjectDetection::drawPred(int classId, float conf, cv::Rect2d box, cv::Mat& frame, int objectNumber, std::vector color, + float alpha, int thickness, bool is_background) { - //Draw a rectangle displaying the bounding box - cv::rectangle(frame, box, classesColor[classId], 2); + if(is_background){ + cv::Mat overlayFrame; + frame.copyTo(overlayFrame); - //Get the label for the class name and its confidence - std::string label = cv::format("%.2f", conf); - if (!classNames.empty()) - { - CV_Assert(classId < (int)classNames.size()); - label = classNames[classId] + ":" + label; + //Draw a rectangle displaying the bounding box + cv::rectangle(overlayFrame, box, cv::Scalar(color[2],color[1],color[0]), cv::FILLED); + + // add opacity + cv::addWeighted(overlayFrame, 1-alpha, frame, alpha, 0, frame); } + else{ + cv::Mat overlayFrame; + frame.copyTo(overlayFrame); - //Display the label at the top of the bounding box - int baseLine; - cv::Size labelSize = cv::getTextSize(label, cv::FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine); + //Draw a rectangle displaying the bounding box + cv::rectangle(overlayFrame, box, cv::Scalar(color[2],color[1],color[0]), thickness); - double left = box.x; - double top = std::max((int)box.y, labelSize.height); + //Get the label for the class name and its confidence + std::string label = cv::format("%.2f", conf); + if (!classNames.empty()) + { + CV_Assert(classId < (int)classNames.size()); + label = classNames[classId] + ":" + label; + } - cv::rectangle(frame, cv::Point(left, top - round(1.025*labelSize.height)), cv::Point(left + round(1.025*labelSize.width), top + baseLine), classesColor[classId], cv::FILLED); - putText(frame, label, cv::Point(left+1, top), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0,0,0),1); + //Display the label at the top of the bounding box + int baseLine; + cv::Size labelSize = cv::getTextSize(label, cv::FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine); + + double left = box.x; + double top = std::max((int)box.y, labelSize.height); + + cv::rectangle(overlayFrame, cv::Point(left, top - round(1.025*labelSize.height)), cv::Point(left + round(1.025*labelSize.width), top + baseLine), + cv::Scalar(color[2],color[1],color[0]), cv::FILLED); + putText(overlayFrame, label, cv::Point(left+1, top), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0,0,0),1); + + // add opacity + cv::addWeighted(overlayFrame, 1-alpha, frame, alpha, 0, frame); + } } // Load protobuf data file @@ -288,7 +315,7 @@ bool ObjectDetection::LoadObjDetectdData(std::string inputFilePath){ // There is no tracked object with that id, so insert a new one TrackedObjectBBox trackedObj((int)classesColor[classId](0), (int)classesColor[classId](1), (int)classesColor[classId](2), (int)0); trackedObj.AddBox(id, x+(w/2), y+(h/2), w, h, 0.0); - std::shared_ptr trackedObjPtr = std::make_shared(trackedObj); + std::shared_ptr trackedObjPtr = std::make_shared(trackedObj); trackedObjects.insert({objectId, trackedObjPtr}); } @@ -315,7 +342,7 @@ bool ObjectDetection::LoadObjDetectdData(std::string inputFilePath){ // Get tracker info for the desired frame DetectionData ObjectDetection::GetTrackedData(size_t frameId){ - // Check if the tracker info for the requested frame exists + // Check if the tracker info for the requested frame exists if ( detectionsData.find(frameId) == detectionsData.end() ) { return DetectionData(); } else { @@ -339,23 +366,31 @@ std::string ObjectDetection::GetVisibleObjects(int64_t frame_number) const{ DetectionData detections = detectionsData.at(frame_number); // Iterate through the tracked objects - int idx = 0; - for (const auto& trackedObject : trackedObjects){ + for(int i = 0; i 0 && + std::find(display_classes.begin(), display_classes.end(), classNames[detections.classIds.at(i)]) == display_classes.end()){ + continue; + } + + int objectId = detections.objectIds.at(i); + // Search for the object in the trackedObjects map + auto trackedObject = trackedObjects.find(objectId); + // Get the tracked object JSON properties for this frame - Json::Value trackedObjectJSON = trackedObject.second->PropertiesJSON(frame_number); + Json::Value trackedObjectJSON = trackedObject->second->PropertiesJSON(frame_number); if (trackedObjectJSON["visible"]["value"].asBool() && - trackedObject.second->ExactlyContains(frame_number)){ + trackedObject->second->ExactlyContains(frame_number)){ // Save the object's index and ID if it's visible in this frame - root["visible_objects_index"].append(trackedObject.first); - root["visible_objects_id"].append(trackedObject.second->Id()); + root["visible_objects_index"].append(trackedObject->first); + root["visible_objects_id"].append(trackedObject->second->Id()); } - idx++; } return root.toStyledString(); @@ -364,17 +399,17 @@ std::string ObjectDetection::GetVisibleObjects(int64_t frame_number) const{ // Generate JSON string of this object std::string ObjectDetection::Json() const { - // Return formatted string - return JsonValue().toStyledString(); + // Return formatted string + return JsonValue().toStyledString(); } // Generate Json::Value for this object Json::Value ObjectDetection::JsonValue() const { - // Create root json object - Json::Value root = EffectBase::JsonValue(); // get parent properties - root["type"] = info.class_name; - root["protobuf_data_path"] = protobuf_data_path; + // Create root json object + Json::Value root = EffectBase::JsonValue(); // get parent properties + root["type"] = info.class_name; + root["protobuf_data_path"] = protobuf_data_path; root["selected_object_index"] = selectedObjectIndex; root["confidence_threshold"] = confidence_threshold; @@ -395,53 +430,65 @@ Json::Value ObjectDetection::JsonValue() const { } } - // return JsonValue - return root; + // return JsonValue + return root; } // Load JSON string into this object void ObjectDetection::SetJson(const std::string value) { - // Parse JSON string into JSON objects - try - { + // Parse JSON string into JSON objects + try + { std::cout<<"entrou no objectDetection SetJson \n"< display_classes; + std::string class_filter; /// Init effect settings void init_effect_details(); - - void drawPred(int classId, float conf, cv::Rect2d box, cv::Mat& frame, int objectNumber); + /// Draw bounding box with class and score text + void drawPred(int classId, float conf, cv::Rect2d box, cv::Mat& frame, int objectNumber, std::vector color, float alpha, + int thickness, bool is_background); /// Draw rotated rectangle with alpha channel void DrawRectangleRGBA(cv::Mat &frame_image, cv::RotatedRect box, std::vector color, float alpha, int thickness, bool is_background); From 93306a42a8869a4086b3d3c316009f68426f833c Mon Sep 17 00:00:00 2001 From: Frank Dana Date: Sat, 10 Apr 2021 23:54:11 +0000 Subject: [PATCH 54/84] tests/KeyFrame.cpp: Typo --- tests/KeyFrame.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/KeyFrame.cpp b/tests/KeyFrame.cpp index 286878bdd..08296679c 100644 --- a/tests/KeyFrame.cpp +++ b/tests/KeyFrame.cpp @@ -536,7 +536,7 @@ TEST_CASE( "TrackedObjectBBox AddBox and RemoveBox" "[libopenshot][keyframe]" ) CHECK(kfb.GetLength() == 0); } -TEST_CASE( "TrackedObjectBBox GetVal" "[libopenshot][keyframe]" ) +TEST_CASE( "TrackedObjectBBox GetVal", "[libopenshot][keyframe]" ) { TrackedObjectBBox kfb; @@ -704,4 +704,3 @@ TEST_CASE( "GetBoxValues", "[libopenshot][keyframe]" ) CHECK(boxValues["h"] == 20.0); CHECK(boxValues["ang"] == 30.0); } - From cd22b0681b032cdcd1a8bbf63bb87698a53f7fe2 Mon Sep 17 00:00:00 2001 From: Frank Dana Date: Sat, 10 Apr 2021 23:54:29 +0000 Subject: [PATCH 55/84] tests/KeyFrame.cpp: Typo --- tests/KeyFrame.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/KeyFrame.cpp b/tests/KeyFrame.cpp index 08296679c..f3ebdb745 100644 --- a/tests/KeyFrame.cpp +++ b/tests/KeyFrame.cpp @@ -521,7 +521,7 @@ TEST_CASE( "TrackedObjectBBox init", "[libopenshot][keyframe]" ) // like confirming some default values in the new object. } -TEST_CASE( "TrackedObjectBBox AddBox and RemoveBox" "[libopenshot][keyframe]" ) +TEST_CASE( "TrackedObjectBBox AddBox and RemoveBox", "[libopenshot][keyframe]" ) { TrackedObjectBBox kfb; From c6d91295c92a845ea135319adbaab6191885195c Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Sat, 10 Apr 2021 20:14:49 -0400 Subject: [PATCH 56/84] src/effects/Tracker.h: Fix bad merge --- src/effects/Tracker.h | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/effects/Tracker.h b/src/effects/Tracker.h index e543b0fc3..2faafcb27 100644 --- a/src/effects/Tracker.h +++ b/src/effects/Tracker.h @@ -64,13 +64,11 @@ namespace openshot double TimeScale; public: - std::string protobuf_data_path; ///< Path to the protobuf file that holds the bounding-box data - std::shared_ptr trackedData; ///< Pointer to an object that holds the bounding-box data and it's Keyframes + std::string protobuf_data_path; ///< Path to the protobuf file that holds the bounding-box data + std::shared_ptr trackedData; ///< Pointer to an object that holds the bounding-box data and it's Keyframes - std::map trackedDataById; // Save object tracking box data - - /// Blank constructor, useful when using Json to load the effect properties - Tracker(std::string clipTrackerDataPath); + /// Blank constructor, useful when using Json to load the effect properties + Tracker(std::string clipTrackerDataPath); /// Default constructor Tracker(); From f5d94d32fbb8879dafe60595ecd74f13a876f61f Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Sat, 10 Apr 2021 20:40:32 -0400 Subject: [PATCH 57/84] effects/ObjectDetection: Declare drawPred correctly --- src/effects/ObjectDetection.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/effects/ObjectDetection.h b/src/effects/ObjectDetection.h index 2e00d359e..8feb47ca3 100644 --- a/src/effects/ObjectDetection.h +++ b/src/effects/ObjectDetection.h @@ -80,9 +80,9 @@ namespace openshot std::vector classesColor; /// Init effect settings - void init_effect_details(); + void init_effect_details(); - void drawPred(int classId, float conf, cv::Rect2d box, cv::Mat& frame); + void drawPred(int classId, float conf, cv::Rect2d box, cv::Mat& frame, int objectNumber); public: /// Index of the Tracked Object that was selected to modify it's properties From f26b4bf80af49f66235c97df0b980e6c7088d7ba Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Sat, 10 Apr 2021 21:03:17 -0400 Subject: [PATCH 58/84] Give SWIG's Ruby code a namespace hint --- src/EffectBase.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/EffectBase.h b/src/EffectBase.h index 8e15ebaf4..6e7418506 100644 --- a/src/EffectBase.h +++ b/src/EffectBase.h @@ -80,7 +80,7 @@ namespace openshot EffectBase* parentEffect; /// Map of Tracked Object's by their indices (used by Effects that track objects on clips) - std::map > trackedObjects; + std::map > trackedObjects; /// Information about the current effect EffectInfoStruct info; @@ -100,7 +100,7 @@ namespace openshot /// Set parent clip object of this effect void ParentClip(openshot::ClipBase* new_clip); - + /// Set the parent effect from which this properties will be set to void SetParentEffect(std::string parentEffect_id); @@ -122,7 +122,7 @@ namespace openshot virtual void SetJson(int64_t requested_frame, const std::string value) { return; }; - + Json::Value JsonInfo() const; ///< Generate JSON object of meta data / info /// Get the order that this effect should be executed. From d1d9293870e7a28cf600bdbacf9c4fd57a50a0a5 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Sun, 11 Apr 2021 23:52:35 -0400 Subject: [PATCH 59/84] tests/KeyFrame: Split a CHECK(), for readability --- tests/KeyFrame.cpp | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/tests/KeyFrame.cpp b/tests/KeyFrame.cpp index f3ebdb745..f476faafa 100644 --- a/tests/KeyFrame.cpp +++ b/tests/KeyFrame.cpp @@ -541,12 +541,12 @@ TEST_CASE( "TrackedObjectBBox GetVal", "[libopenshot][keyframe]" ) TrackedObjectBBox kfb; kfb.AddBox(1, 10.0, 10.0, 100.0, 100.0, 0.0); - + BBox val = kfb.GetBox(1); - + CHECK(val.cx == 10.0); CHECK(val.cy == 10.0); - CHECK(val.width) == 100.0; + CHECK(val.width == 100.0); CHECK(val.height == 100.0); CHECK(val.angle == 0.0); } @@ -557,9 +557,9 @@ TEST_CASE( "TrackedObjectBBox GetVal interpolation", "[libopenshot][keyframe]" ) kfb.AddBox(1, 10.0, 10.0, 100.0, 100.0, 0.0); kfb.AddBox(11, 20.0, 20.0, 100.0, 100.0, 0.0); - kfb.AddBox(21, 30.0, 30.0, 100.0, 100.0, 0.0); + kfb.AddBox(21, 30.0, 30.0, 100.0, 100.0, 0.0); kfb.AddBox(31, 40.0, 40.0, 100.0, 100.0, 0.0); - + BBox val = kfb.GetBox(5); CHECK(val.cx == 14.0); @@ -568,14 +568,14 @@ TEST_CASE( "TrackedObjectBBox GetVal interpolation", "[libopenshot][keyframe]" ) CHECK(val.height == 100.0); val = kfb.GetBox(15); - + CHECK(val.cx == 24.0); CHECK(val.cy == 24.0); CHECK(val.width == 100.0); CHECK(val.height == 100.0); val = kfb.GetBox(25); - + CHECK(val.cx == 34.0); CHECK(val.cy == 34.0); CHECK(val.width == 100.0); @@ -590,7 +590,7 @@ TEST_CASE( "TrackedObjectBBox SetJson", "[libopenshot][keyframe]" ) kfb.AddBox(1, 10.0, 10.0, 100.0, 100.0, 0.0); kfb.AddBox(10, 20.0, 20.0, 100.0, 100.0, 0.0); - kfb.AddBox(20, 30.0, 30.0, 100.0, 100.0, 0.0); + kfb.AddBox(20, 30.0, 30.0, 100.0, 100.0, 0.0); kfb.AddBox(30, 40.0, 40.0, 100.0, 100.0, 0.0); kfb.scale_x.AddPoint(1, 2.0); @@ -602,8 +602,10 @@ TEST_CASE( "TrackedObjectBBox SetJson", "[libopenshot][keyframe]" ) TrackedObjectBBox fromJSON_kfb; fromJSON_kfb.SetJson(dataJSON); - CHECK(kfb.GetBaseFPS().num == fromJSON_kfb.GetBaseFPS().num); - + int num_kfb = kfb.GetBaseFPS().num; + int num_fromJSON_kfb = fromJSON_kfb.GetBaseFPS().num; + CHECK(num_kfb == num_fromJSON_kfb); + double time_kfb = kfb.FrameNToTime(1, 1.0); double time_fromJSON_kfb = fromJSON_kfb.FrameNToTime(1, 1.0); CHECK(time_kfb == time_fromJSON_kfb); @@ -625,9 +627,9 @@ TEST_CASE( "TrackedObjectBBox scaling", "[libopenshot][keyframe]" ) kfb.AddBox(1, 10.0, 10.0, 10.0, 10.0, 0.0); kfb.scale_x.AddPoint(1.0, 2.0); kfb.scale_y.AddPoint(1.0, 3.0); - + BBox bbox = kfb.GetBox(1); - + CHECK(bbox.width == 20.0); CHECK(bbox.height == 30.0); } @@ -679,11 +681,11 @@ TEST_CASE( "AttachToObject", "[libopenshot][keyframe]" ) std::string tracked_id = trackedData->Id(); childClip.Open(); childClip.AttachToObject(tracked_id); - + std::shared_ptr trackedTest = std::static_pointer_cast(childClip.GetAttachedObject()); - + CHECK(trackedData->scale_x.GetValue(1) == trackedTest->scale_x.GetValue(1)); - + auto frameTest = childClip.GetFrame(1); childClip.Close(); // XXX: Here, too, there needs to be some sort of actual _testing_ of the results @@ -695,7 +697,7 @@ TEST_CASE( "GetBoxValues", "[libopenshot][keyframe]" ) trackedDataObject.AddBox(1, 10.0, 10.0, 20.0, 20.0, 30.0); std::shared_ptr trackedData = std::make_shared(trackedDataObject); - + auto boxValues = trackedData->GetBoxValues(1); CHECK(boxValues["cx"] == 10.0); From 99b5d1e7ab6bc75de28696147229383ddee8e730 Mon Sep 17 00:00:00 2001 From: Brenno Date: Mon, 12 Apr 2021 21:18:21 -0300 Subject: [PATCH 60/84] Fixed variable names and comments thanks to Frank Dana --- examples/CMakeLists.txt | 7 ++----- src/Timeline.cpp | 8 ++++---- src/TrackedObjectBase.h | 4 ++-- tests/Point.cpp | 1 + 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 3f77d7009..3e54ef1d0 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -65,16 +65,13 @@ if (BLACKMAGIC_FOUND) endif() ############### OPENCV EXAMPLE ################ -find_package( OpenCV 4 ) -if (OpenCV_FOUND) +if (DEFINED CACHE{HAVE_OPENCV}) # Create test executable add_executable(openshot-example-opencv Example_opencv.cpp) target_compile_definitions(openshot-example-opencv PRIVATE - -DTEST_MEDIA_PATH="${TEST_MEDIA_PATH}" ) - + -DTEST_MEDIA_PATH="${TEST_MEDIA_PATH}" ) # Link test executable to the new library target_link_libraries(openshot-example-opencv openshot) - endif() diff --git a/src/Timeline.cpp b/src/Timeline.cpp index ac6c8f0a3..291944106 100644 --- a/src/Timeline.cpp +++ b/src/Timeline.cpp @@ -438,19 +438,19 @@ openshot::EffectBase* Timeline::GetClipEffect(const std::string& id) std::list Timeline::ClipEffects() const { // Initialize the list - std::list ClipEffects; + std::list timelineEffectsList; // Loop through all clips for (const auto& clip : clips) { // Get the clip's list of effects - std::list clipEffects = clip->Effects(); + std::list clipEffectsList = clip->Effects(); // Append the clip's effects to the list - ClipEffects.insert(ClipEffects.end(), clipEffects.begin(), clipEffects.end()); + timelineEffectsList.insert(timelineEffectsList.end(), clipEffectsList.begin(), clipEffectsList.end()); } - return ClipEffects; + return timelineEffectsList; } // Compute the end time of the latest timeline element diff --git a/src/TrackedObjectBase.h b/src/TrackedObjectBase.h index c0f6c6601..af74e45e6 100644 --- a/src/TrackedObjectBase.h +++ b/src/TrackedObjectBase.h @@ -66,10 +66,10 @@ namespace openshot { Keyframe visible; Keyframe draw_box; - /// Blank constructor + /// Default constructor TrackedObjectBase(); - /// Default constructor + /// Constructor which takes an object ID TrackedObjectBase(std::string _id); /// Get the id of this object diff --git a/tests/Point.cpp b/tests/Point.cpp index 45f493e07..965d9574f 100644 --- a/tests/Point.cpp +++ b/tests/Point.cpp @@ -29,6 +29,7 @@ */ #include +#include #include "Point.h" #include "Enums.h" From 32033e01e4f01549e6825e912901b2388ed0f6f4 Mon Sep 17 00:00:00 2001 From: Brenno Date: Mon, 12 Apr 2021 21:21:42 -0300 Subject: [PATCH 61/84] Changed formatting from tab to spaces --- src/TrackedObjectBBox.cpp | 732 +++++++++++++-------------- src/TrackedObjectBBox.h | 376 +++++++------- src/TrackedObjectBase.h | 32 +- src/effects/ObjectDetection.cpp | 852 ++++++++++++++++---------------- 4 files changed, 996 insertions(+), 996 deletions(-) diff --git a/src/TrackedObjectBBox.cpp b/src/TrackedObjectBBox.cpp index f4288876e..899829323 100644 --- a/src/TrackedObjectBBox.cpp +++ b/src/TrackedObjectBBox.cpp @@ -41,413 +41,413 @@ 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.0), stroke_alpha(0.0), 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; + this->TimeScale = 1.0; + return; } TrackedObjectBBox::TrackedObjectBBox(int Red, int Green, int Blue, int Alfa) : 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.0), stroke_alpha(0.0), background_corner(0), - stroke(Red,Green,Blue,Alfa), background(0,0,255,0) + stroke_width(2) , background_alpha(1.0), stroke_alpha(0.0), background_corner(0), + stroke(Red,Green,Blue,Alfa), background(0,0,255,0) { - this->TimeScale = 1.0; - return; + this->TimeScale = 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) { - // Check if the given frame number is valid - if (_frame_num < 0) - return; - - // Instantiate a new bounding-box - BBox newBBox = BBox(_cx, _cy, _width, _height, _angle); - - // 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 - auto BBoxIterator = BoxVec.find(time); - - if (BBoxIterator != BoxVec.end()) - { - // There is a bounding-box indexed by the time of given frame, update-it - BBoxIterator->second = newBBox; - } - else - { - // There isn't a bounding-box indexed by the time of given frame, insert a new one - BoxVec.insert({time, newBBox}); - } + // Check if the given frame number is valid + if (_frame_num < 0) + return; + + // Instantiate a new bounding-box + BBox newBBox = BBox(_cx, _cy, _width, _height, _angle); + + // 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 + auto BBoxIterator = BoxVec.find(time); + + if (BBoxIterator != BoxVec.end()) + { + // There is a bounding-box indexed by the time of given frame, update-it + BBoxIterator->second = newBBox; + } + else + { + // There isn't a bounding-box indexed by the time of given frame, insert a new one + BoxVec.insert({time, newBBox}); + } } // Get the size of BoxVec map int64_t TrackedObjectBBox::GetLength() const { - if (BoxVec.empty()) - return 0; - if (BoxVec.size() == 1) - return 1; - return BoxVec.size(); + if (BoxVec.empty()) + return 0; + if (BoxVec.size() == 1) + return 1; + return BoxVec.size(); } // Check if there is a bounding-box in the given frame 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()){ - // BoxVec pair not found - return false; - } - return true; + // 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()){ + // 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; + // 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; } // Remove a bounding-box from the BoxVec map void TrackedObjectBBox::RemoveBox(int64_t frame_number) { - // Get the time of given frame - double time = this->FrameNToTime(frame_number, 1.0); - // Create an iterator that points to the BoxVec pair indexed by the time of given frame - auto it = BoxVec.find(time); - if (it != BoxVec.end()) - { - // The BoxVec pair exists, so remove it - BoxVec.erase(time); - } - return; + // Get the time of given frame + double time = this->FrameNToTime(frame_number, 1.0); + // Create an iterator that points to the BoxVec pair indexed by the time of given frame + auto it = BoxVec.find(time); + if (it != BoxVec.end()) + { + // The BoxVec pair exists, so remove it + BoxVec.erase(time); + } + return; } // Return a bounding-box from BoxVec with it's properties adjusted by the Keyframes BBox TrackedObjectBBox::GetBox(int64_t frame_number) { - // Get the time position of the given frame. - double time = this->FrameNToTime(frame_number, this->TimeScale); - - // Return a iterator pointing to the BoxVec pair indexed by time or to the pair indexed - // by the closest upper time value. - auto currentBBoxIterator = BoxVec.lower_bound(time); - - // Check if there is a pair indexed by time, returns an empty bbox if there isn't. - if (currentBBoxIterator == BoxVec.end()) - { - // Create and return an empty bounding-box object - BBox emptyBBox; - return emptyBBox; - } - - // Check if the iterator matches a BBox indexed by time or points to the first element of BoxVec - if ((currentBBoxIterator->first == time) || (currentBBoxIterator == BoxVec.begin())) - { - // Get the BBox indexed by time - BBox currentBBox = currentBBoxIterator->second; - - // Adjust the BBox properties by the Keyframes values - currentBBox.cx += this->delta_x.GetValue(frame_number); - currentBBox.cy += this->delta_y.GetValue(frame_number); - currentBBox.width *= this->scale_x.GetValue(frame_number); - currentBBox.height *= this->scale_y.GetValue(frame_number); - currentBBox.angle += this->rotation.GetValue(frame_number); - - return currentBBox; - } - - // BBox indexed by the closest upper time - BBox currentBBox = currentBBoxIterator->second; - // BBox indexed by the closet lower time - BBox previousBBox = prev(currentBBoxIterator, 1)->second; - - // Interpolate a BBox in the middle of previousBBox and currentBBox - BBox interpolatedBBox = InterpolateBoxes(prev(currentBBoxIterator, 1)->first, currentBBoxIterator->first, - previousBBox, currentBBox, time); - - // Adjust the BBox properties by the Keyframes values - interpolatedBBox.cx += this->delta_x.GetValue(frame_number); - interpolatedBBox.cy += this->delta_y.GetValue(frame_number); - interpolatedBBox.width *= this->scale_x.GetValue(frame_number); - interpolatedBBox.height *= this->scale_y.GetValue(frame_number); - interpolatedBBox.angle += this->rotation.GetValue(frame_number); - - return interpolatedBBox; + // Get the time position of the given frame. + double time = this->FrameNToTime(frame_number, this->TimeScale); + + // Return a iterator pointing to the BoxVec pair indexed by time or to the pair indexed + // by the closest upper time value. + auto currentBBoxIterator = BoxVec.lower_bound(time); + + // Check if there is a pair indexed by time, returns an empty bbox if there isn't. + if (currentBBoxIterator == BoxVec.end()) + { + // Create and return an empty bounding-box object + BBox emptyBBox; + return emptyBBox; + } + + // Check if the iterator matches a BBox indexed by time or points to the first element of BoxVec + if ((currentBBoxIterator->first == time) || (currentBBoxIterator == BoxVec.begin())) + { + // Get the BBox indexed by time + BBox currentBBox = currentBBoxIterator->second; + + // Adjust the BBox properties by the Keyframes values + currentBBox.cx += this->delta_x.GetValue(frame_number); + currentBBox.cy += this->delta_y.GetValue(frame_number); + currentBBox.width *= this->scale_x.GetValue(frame_number); + currentBBox.height *= this->scale_y.GetValue(frame_number); + currentBBox.angle += this->rotation.GetValue(frame_number); + + return currentBBox; + } + + // BBox indexed by the closest upper time + BBox currentBBox = currentBBoxIterator->second; + // BBox indexed by the closet lower time + BBox previousBBox = prev(currentBBoxIterator, 1)->second; + + // Interpolate a BBox in the middle of previousBBox and currentBBox + BBox interpolatedBBox = InterpolateBoxes(prev(currentBBoxIterator, 1)->first, currentBBoxIterator->first, + previousBBox, currentBBox, time); + + // Adjust the BBox properties by the Keyframes values + interpolatedBBox.cx += this->delta_x.GetValue(frame_number); + interpolatedBBox.cy += this->delta_y.GetValue(frame_number); + interpolatedBBox.width *= this->scale_x.GetValue(frame_number); + interpolatedBBox.height *= this->scale_y.GetValue(frame_number); + interpolatedBBox.angle += this->rotation.GetValue(frame_number); + + return interpolatedBBox; } // Interpolate the bouding-boxes properties BBox TrackedObjectBBox::InterpolateBoxes(double t1, double t2, BBox left, BBox right, double target) { - // Interpolate the x-coordinate of the center point - Point cx_left(t1, left.cx, openshot::InterpolationType::LINEAR); - Point cx_right(t2, right.cx, openshot::InterpolationType::LINEAR); - Point cx = InterpolateBetween(cx_left, cx_right, target, 0.01); - - // Interpolate de y-coordinate of the center point - Point cy_left(t1, left.cy, openshot::InterpolationType::LINEAR); - Point cy_right(t2, right.cy, openshot::InterpolationType::LINEAR); - Point cy = InterpolateBetween(cy_left, cy_right, target, 0.01); - - // Interpolate the width - Point width_left(t1, left.width, openshot::InterpolationType::LINEAR); - Point width_right(t2, right.width, openshot::InterpolationType::LINEAR); - Point width = InterpolateBetween(width_left, width_right, target, 0.01); - - // Interpolate the height - Point height_left(t1, left.height, openshot::InterpolationType::LINEAR); - Point height_right(t2, right.height, openshot::InterpolationType::LINEAR); - Point height = InterpolateBetween(height_left, height_right, target, 0.01); - - // Interpolate the rotation angle - Point angle_left(t1, left.angle, openshot::InterpolationType::LINEAR); - Point angle_right(t1, right.angle, openshot::InterpolationType::LINEAR); - Point angle = InterpolateBetween(angle_left, angle_right, target, 0.01); - - // Create a bounding box with the interpolated points - BBox interpolatedBox(cx.co.Y, cy.co.Y, width.co.Y, height.co.Y, angle.co.Y); - - return interpolatedBox; + // Interpolate the x-coordinate of the center point + Point cx_left(t1, left.cx, openshot::InterpolationType::LINEAR); + Point cx_right(t2, right.cx, openshot::InterpolationType::LINEAR); + Point cx = InterpolateBetween(cx_left, cx_right, target, 0.01); + + // Interpolate de y-coordinate of the center point + Point cy_left(t1, left.cy, openshot::InterpolationType::LINEAR); + Point cy_right(t2, right.cy, openshot::InterpolationType::LINEAR); + Point cy = InterpolateBetween(cy_left, cy_right, target, 0.01); + + // Interpolate the width + Point width_left(t1, left.width, openshot::InterpolationType::LINEAR); + Point width_right(t2, right.width, openshot::InterpolationType::LINEAR); + Point width = InterpolateBetween(width_left, width_right, target, 0.01); + + // Interpolate the height + Point height_left(t1, left.height, openshot::InterpolationType::LINEAR); + Point height_right(t2, right.height, openshot::InterpolationType::LINEAR); + Point height = InterpolateBetween(height_left, height_right, target, 0.01); + + // Interpolate the rotation angle + Point angle_left(t1, left.angle, openshot::InterpolationType::LINEAR); + Point angle_right(t1, right.angle, openshot::InterpolationType::LINEAR); + Point angle = InterpolateBetween(angle_left, angle_right, target, 0.01); + + // Create a bounding box with the interpolated points + BBox interpolatedBox(cx.co.Y, cy.co.Y, width.co.Y, height.co.Y, angle.co.Y); + + return interpolatedBox; } // Update object's BaseFps void TrackedObjectBBox::SetBaseFPS(Fraction fps){ - this->BaseFps = fps; - return; + this->BaseFps = fps; + return; } // Return the object's BaseFps Fraction TrackedObjectBBox::GetBaseFPS(){ - return BaseFps; + return BaseFps; } // Get the time of the given frame double TrackedObjectBBox::FrameNToTime(int64_t frame_number, double time_scale) const{ - double time = ((double)frame_number) * this->BaseFps.Reciprocal().ToDouble() * (1.0 / time_scale); + double time = ((double)frame_number) * this->BaseFps.Reciprocal().ToDouble() * (1.0 / time_scale); - return time; + return time; } // Update the TimeScale member variable void TrackedObjectBBox::ScalePoints(double time_scale){ - this->TimeScale = time_scale; + this->TimeScale = time_scale; } // Load the bounding-boxes information from the protobuf file bool TrackedObjectBBox::LoadBoxData(std::string inputFilePath) { - // Variable to hold the loaded data - pb_tracker::Tracker bboxMessage; - - // Read the existing tracker message. - fstream input(inputFilePath, ios::in | ios::binary); - - // Check if it was able to read the protobuf data - if (!bboxMessage.ParseFromIstream(&input)) - { - cerr << "Failed to parse protobuf message." << endl; - return false; - } - - this->clear(); - - // Iterate over all frames of the saved message - for (size_t i = 0; i < bboxMessage.frame_size(); i++) - { - // Get data of the i-th frame - const pb_tracker::Frame &pbFrameData = bboxMessage.frame(i); - - // Get frame number - size_t frame_number = pbFrameData.id(); - - // Get bounding box data from current frame - const pb_tracker::Frame::Box &box = pbFrameData.bounding_box(); - - float width = box.x2() - box.x1(); - float height = box.y2() - box.y1(); - float cx = box.x1() + width/2; - float cy = box.y1() + height/2; - float angle = 0.0; - - - if ( (cx >= 0.0) && (cy >= 0.0) && (width >= 0.0) && (height >= 0.0) ) - { - // The bounding-box properties are valid, so add it to the BoxVec map - this->AddBox(frame_number, cx, cy, width, height, angle); - } - } - - // Show the time stamp from the last update in tracker data file - if (bboxMessage.has_last_updated()) - { - cout << " Loaded Data. Saved Time Stamp: " << TimeUtil::ToString(bboxMessage.last_updated()) << endl; - } - - // Delete all global objects allocated by libprotobuf. - google::protobuf::ShutdownProtobufLibrary(); - - return true; + // Variable to hold the loaded data + pb_tracker::Tracker bboxMessage; + + // Read the existing tracker message. + fstream input(inputFilePath, ios::in | ios::binary); + + // Check if it was able to read the protobuf data + if (!bboxMessage.ParseFromIstream(&input)) + { + cerr << "Failed to parse protobuf message." << endl; + return false; + } + + this->clear(); + + // Iterate over all frames of the saved message + for (size_t i = 0; i < bboxMessage.frame_size(); i++) + { + // Get data of the i-th frame + const pb_tracker::Frame &pbFrameData = bboxMessage.frame(i); + + // Get frame number + size_t frame_number = pbFrameData.id(); + + // Get bounding box data from current frame + const pb_tracker::Frame::Box &box = pbFrameData.bounding_box(); + + float width = box.x2() - box.x1(); + float height = box.y2() - box.y1(); + float cx = box.x1() + width/2; + float cy = box.y1() + height/2; + float angle = 0.0; + + + if ( (cx >= 0.0) && (cy >= 0.0) && (width >= 0.0) && (height >= 0.0) ) + { + // The bounding-box properties are valid, so add it to the BoxVec map + this->AddBox(frame_number, cx, cy, width, height, angle); + } + } + + // Show the time stamp from the last update in tracker data file + if (bboxMessage.has_last_updated()) + { + cout << " Loaded Data. Saved Time Stamp: " << TimeUtil::ToString(bboxMessage.last_updated()) << endl; + } + + // Delete all global objects allocated by libprotobuf. + google::protobuf::ShutdownProtobufLibrary(); + + return true; } // Clear the BoxVec map void TrackedObjectBBox::clear() { - BoxVec.clear(); + BoxVec.clear(); } // Generate JSON string of this object std::string TrackedObjectBBox::Json() const { - // Return formatted string - return JsonValue().toStyledString(); + // Return formatted string + return JsonValue().toStyledString(); } // Generate Json::Value for this object Json::Value TrackedObjectBBox::JsonValue() const { - // Create root json object - Json::Value root; - - // Object's properties - root["box_id"] = Id(); - 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(); - root["delta_y"] = delta_y.JsonValue(); - root["scale_x"] = scale_x.JsonValue(); - root["scale_y"] = scale_y.JsonValue(); - 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(); - root["stroke_alpha"] = stroke_alpha.JsonValue(); - - // return JsonValue - return root; + // Create root json object + Json::Value root; + + // Object's properties + root["box_id"] = Id(); + 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(); + root["delta_y"] = delta_y.JsonValue(); + root["scale_x"] = scale_x.JsonValue(); + root["scale_y"] = scale_y.JsonValue(); + 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(); + root["stroke_alpha"] = stroke_alpha.JsonValue(); + + // return JsonValue + return root; } // Load JSON string into this object void TrackedObjectBBox::SetJson(const std::string value) { - // Parse JSON string into JSON objects - try - { - const Json::Value root = openshot::stringToJson(value); - // Set all values that match - SetJsonValue(root); - } - catch (const std::exception &e) - { - // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); - } - return; + // Parse JSON string into JSON objects + try + { + const Json::Value root = openshot::stringToJson(value); + // Set all values that match + SetJsonValue(root); + } + catch (const std::exception &e) + { + // Error parsing JSON (or missing keys) + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); + } + return; } // Load Json::Value into this object void TrackedObjectBBox::SetJsonValue(const Json::Value root) { - // Set the Id by the given JSON object - if (!root["box_id"].isNull() && root["box_id"].asString() != "None") - Id(root["box_id"].asString()); - - // Set the BaseFps by the given JSON object - if (!root["BaseFPS"].isNull() && root["BaseFPS"].isObject()) - { - if (!root["BaseFPS"]["num"].isNull()) - BaseFps.num = (int)root["BaseFPS"]["num"].asInt(); - if (!root["BaseFPS"]["den"].isNull()) - BaseFps.den = (int)root["BaseFPS"]["den"].asInt(); - } - - // Set the TimeScale by the given JSON object - if (!root["TimeScale"].isNull()) - { - double scale = (double)root["TimeScale"].asDouble(); - this->ScalePoints(scale); - } - - // Set the protobuf data path by the given JSON object - if (!root["protobuf_data_path"].isNull()) - protobufDataPath = root["protobuf_data_path"].asString(); - - // Set the id of the child clip - // Does not allow to link to the parent clip - if (!root["child_clip_id"].isNull() && root["box_id"].asString() != "None"){ - Clip* parentClip = (Clip *) ParentClip(); - - if(parentClip && (root["child_clip_id"].asString() != parentClip->Id())){ - 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"]); - if (!root["delta_y"].isNull()) + // Set the Id by the given JSON object + if (!root["box_id"].isNull() && root["box_id"].asString() != "None") + Id(root["box_id"].asString()); + + // Set the BaseFps by the given JSON object + if (!root["BaseFPS"].isNull() && root["BaseFPS"].isObject()) + { + if (!root["BaseFPS"]["num"].isNull()) + BaseFps.num = (int)root["BaseFPS"]["num"].asInt(); + if (!root["BaseFPS"]["den"].isNull()) + BaseFps.den = (int)root["BaseFPS"]["den"].asInt(); + } + + // Set the TimeScale by the given JSON object + if (!root["TimeScale"].isNull()) + { + double scale = (double)root["TimeScale"].asDouble(); + this->ScalePoints(scale); + } + + // Set the protobuf data path by the given JSON object + if (!root["protobuf_data_path"].isNull()) + protobufDataPath = root["protobuf_data_path"].asString(); + + // Set the id of the child clip + // Does not allow to link to the parent clip + if (!root["child_clip_id"].isNull() && root["box_id"].asString() != "None"){ + Clip* parentClip = (Clip *) ParentClip(); + + if(parentClip && (root["child_clip_id"].asString() != parentClip->Id())){ + 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"]); + if (!root["delta_y"].isNull()) delta_y.SetJsonValue(root["delta_y"]); - if (!root["scale_x"].isNull()) - scale_x.SetJsonValue(root["scale_x"]); - if (!root["scale_y"].isNull()) - scale_y.SetJsonValue(root["scale_y"]); - if (!root["rotation"].isNull()) - rotation.SetJsonValue(root["rotation"]); - if (!root["visible"].isNull()) - visible.SetJsonValue(root["visible"]); - if (!root["draw_box"].isNull()) + if (!root["scale_x"].isNull()) + scale_x.SetJsonValue(root["scale_x"]); + if (!root["scale_y"].isNull()) + scale_y.SetJsonValue(root["scale_y"]); + if (!root["rotation"].isNull()) + rotation.SetJsonValue(root["rotation"]); + if (!root["visible"].isNull()) + visible.SetJsonValue(root["visible"]); + if (!root["draw_box"].isNull()) draw_box.SetJsonValue(root["draw_box"]); - if (!root["stroke"].isNull()) + if (!root["stroke"].isNull()) stroke.SetJsonValue(root["stroke"]); - if (!root["background_alpha"].isNull()) + if (!root["background_alpha"].isNull()) background_alpha.SetJsonValue(root["background_alpha"]); - if (!root["background_corner"].isNull()) + if (!root["background_corner"].isNull()) background_corner.SetJsonValue(root["background_corner"]); - if (!root["background"].isNull()) + if (!root["background"].isNull()) background.SetJsonValue(root["background"]); - if (!root["stroke_width"].isNull()) + if (!root["stroke_width"].isNull()) stroke_width.SetJsonValue(root["stroke_width"]); - if (!root["stroke_alpha"].isNull()) + if (!root["stroke_alpha"].isNull()) stroke_alpha.SetJsonValue(root["stroke_alpha"]); - return; + return; } // Get all properties for a specific frame (perfect for a UI to display the current state // of all properties at any time) Json::Value TrackedObjectBBox::PropertiesJSON(int64_t requested_frame) const { - Json::Value root; + Json::Value root; - BBox box = GetBox(requested_frame); + BBox box = GetBox(requested_frame); - // 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 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 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 + // 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); root["x2"] = add_property_json("X2", box.cx+(box.width/2), "float", "", NULL, 0.0, 1.0, false, requested_frame); @@ -459,26 +459,26 @@ Json::Value TrackedObjectBBox::PropertiesJSON(int64_t requested_frame) const 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); + 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"] = 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["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); - - 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); + + 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["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); + + 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; @@ -525,59 +525,59 @@ Json::Value TrackedObjectBBox::add_property_json(std::string name, float value, // Return a map that contains the bounding box properties and it's keyframes indexed by their names std::map TrackedObjectBBox::GetBoxValues(int64_t frame_number) const { - // Create the map - std::map boxValues; + // Create the map + std::map boxValues; - // Get bounding box of the current frame - BBox box = GetBox(frame_number); + // Get bounding box of the current frame + BBox box = GetBox(frame_number); - // Save the bounding box properties - boxValues["cx"] = box.cx; - boxValues["cy"] = box.cy; - boxValues["w"] = box.width; - boxValues["h"] = box.height; - boxValues["ang"] = box.angle; + // Save the bounding box properties + boxValues["cx"] = box.cx; + boxValues["cy"] = box.cy; + boxValues["w"] = box.width; + boxValues["h"] = box.height; + boxValues["ang"] = box.angle; - // Save the keyframes values - boxValues["sx"] = this->scale_x.GetValue(frame_number); - boxValues["sy"] = this->scale_y.GetValue(frame_number); - boxValues["dx"] = this->delta_x.GetValue(frame_number); - boxValues["dy"] = this->delta_y.GetValue(frame_number); - boxValues["r"] = this->rotation.GetValue(frame_number); + // Save the keyframes values + boxValues["sx"] = this->scale_x.GetValue(frame_number); + boxValues["sy"] = this->scale_y.GetValue(frame_number); + boxValues["dx"] = this->delta_x.GetValue(frame_number); + boxValues["dy"] = this->delta_y.GetValue(frame_number); + boxValues["r"] = this->rotation.GetValue(frame_number); - - return boxValues; + + return boxValues; } // Return a map that contains the properties of this object's parent clip std::map TrackedObjectBBox::GetParentClipProperties(int64_t frame_number) const { - - // Get the parent clip of this object as a Clip pointer - Clip* parentClip = (Clip *) ParentClip(); - - // Calculate parentClip's frame number - long parentClip_start_position = round( parentClip->Position() * parentClip->info.fps.ToDouble() ) + 1; - long parentClip_start_frame = ( parentClip->Start() * parentClip->info.fps.ToDouble() ) + 1; - float parentClip_frame_number = round(frame_number - parentClip_start_position) + parentClip_start_frame; - - // Get parentClip's Keyframes - float parentClip_location_x = parentClip->location_x.GetValue(parentClip_frame_number); - float parentClip_location_y = parentClip->location_y.GetValue(parentClip_frame_number); - float parentClip_scale_x = parentClip->scale_x.GetValue(parentClip_frame_number); - float parentClip_scale_y = parentClip->scale_y.GetValue(parentClip_frame_number); - float parentClip_rotation = parentClip->rotation.GetValue(parentClip_frame_number); - - // Initialize the parent clip properties map - std::map parentClipProperties; - - // Set the map properties - parentClipProperties["frame_number"] = parentClip_frame_number; - parentClipProperties["timeline_frame_number"] = frame_number; - parentClipProperties["location_x"] = parentClip_location_x; - parentClipProperties["location_y"] = parentClip_location_y; - parentClipProperties["scale_x"] = parentClip_scale_x; - parentClipProperties["scale_y"] = parentClip_scale_y; - parentClipProperties["rotation"] = parentClip_rotation; - - return parentClipProperties; + + // Get the parent clip of this object as a Clip pointer + Clip* parentClip = (Clip *) ParentClip(); + + // Calculate parentClip's frame number + long parentClip_start_position = round( parentClip->Position() * parentClip->info.fps.ToDouble() ) + 1; + long parentClip_start_frame = ( parentClip->Start() * parentClip->info.fps.ToDouble() ) + 1; + float parentClip_frame_number = round(frame_number - parentClip_start_position) + parentClip_start_frame; + + // Get parentClip's Keyframes + float parentClip_location_x = parentClip->location_x.GetValue(parentClip_frame_number); + float parentClip_location_y = parentClip->location_y.GetValue(parentClip_frame_number); + float parentClip_scale_x = parentClip->scale_x.GetValue(parentClip_frame_number); + float parentClip_scale_y = parentClip->scale_y.GetValue(parentClip_frame_number); + float parentClip_rotation = parentClip->rotation.GetValue(parentClip_frame_number); + + // Initialize the parent clip properties map + std::map parentClipProperties; + + // Set the map properties + parentClipProperties["frame_number"] = parentClip_frame_number; + parentClipProperties["timeline_frame_number"] = frame_number; + parentClipProperties["location_x"] = parentClip_location_x; + parentClipProperties["location_y"] = parentClip_location_y; + parentClipProperties["scale_x"] = parentClip_scale_x; + parentClipProperties["scale_y"] = parentClip_scale_y; + parentClipProperties["rotation"] = parentClip_rotation; + + return parentClipProperties; } \ No newline at end of file diff --git a/src/TrackedObjectBBox.h b/src/TrackedObjectBBox.h index e50f3cf8b..bf66c388d 100644 --- a/src/TrackedObjectBBox.h +++ b/src/TrackedObjectBBox.h @@ -52,197 +52,197 @@ using google::protobuf::util::TimeUtil; namespace openshot { - /** - * @brief This struct holds the information of a bounding-box. - * - * A bounding-box is a rectangular shape that enclosures an - * object or a desired set of pixels in a digital image. - * - * The bounding-box structure holds five floating-point properties: - * the x and y coordinates of the rectangle's center point (cx, cy), - * the rectangle's width, height and rotation. - */ - struct BBox - { - float cx = -1; ///< x-coordinate of the bounding box center - float cy = -1; ///< y-coordinate of the bounding box center - float width = -1; ///< bounding box width - float height = -1; ///< bounding box height - float angle = -1; ///< bounding box rotation angle [degrees] - - /// Blank constructor - BBox() {} - - /// Default constructor, which takes the bounding box top-left corner coordinates, width and height. - /// @param _cx X-coordinate of the bounding box center - /// @param _cy Y-coordinate of the bounding box center - /// @param _width Bounding box width - /// @param _height Bounding box height - /// @param _angle Bounding box rotation angle [degrees] - BBox(float _cx, float _cy, float _width, float _height, float _angle) - { - cx = _cx; - cy = _cy; - width = _width; - height = _height; - angle = _angle; - } - - - /// Generate JSON string of this object - std::string Json() const - { - return JsonValue().toStyledString(); - } - - /// Generate Json::Value for this object - Json::Value JsonValue() const - { - Json::Value root; - root["cx"] = cx; - root["cy"] = cy; - root["width"] = width; - root["height"] = height; - root["angle"] = angle; - - return root; - } - - /// Load JSON string into this object - void SetJson(const std::string value) - { - // Parse JSON string into JSON objects - try - { - const Json::Value root = openshot::stringToJson(value); - // Set all values that match - SetJsonValue(root); - } - catch (const std::exception &e) - { - // Error parsing JSON (or missing keys) - throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); - } - } - - /// Load Json::Value into this object - void SetJsonValue(const Json::Value root) - { - - // Set data from Json (if key is found) - if (!root["cx"].isNull()) - cx = root["cx"].asDouble(); - if (!root["cy"].isNull()) - cy = root["cy"].asDouble(); - if (!root["width"].isNull()) - width = root["width"].asDouble(); - if (!root["height"].isNull()) - height = root["height"].asDouble(); - if (!root["angle"].isNull()) - angle = root["angle"].asDouble(); - } - }; - - /** - * @brief This class contains the properties of a tracked object - * and functions to manipulate it. - * - * The bounding-box displacement in X and Y directions, it's width, - * height and rotation variation over the frames are set as - * openshot::Keyframe objects. - * - * The bounding-box information over the clip's frames are - * saved into a protobuf file and loaded into an - * object of this class. - */ - class TrackedObjectBBox : public TrackedObjectBase - { - private: - Fraction BaseFps; - double TimeScale; - - public: - std::map BoxVec; ///< Index the bounding-box by time of each frame - Keyframe delta_x; ///< X-direction displacement Keyframe - Keyframe delta_y; ///< Y-direction displacement Keyframe - 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 - Keyframe stroke_alpha; ///< Stroke box opacity - 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 - TrackedObjectBBox(); - TrackedObjectBBox(int Red, int Green, int Blue, int Alfa); - - /// Add a BBox to the BoxVec map - void AddBox(int64_t _frame_num, float _cx, float _cy, float _width, float _height, float _angle) override; - - /// Update object's BaseFps - void SetBaseFPS(Fraction fps); - - /// Return the object's BaseFps - Fraction GetBaseFPS(); - - /// Update the TimeScale member variable - void ScalePoints(double scale) override; - - /// Check if there is a bounding-box in the given frame - 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 override; - - /// Get the size of BoxVec map - int64_t GetLength() const; - - /// Remove a bounding-box from the BoxVec map - void RemoveBox(int64_t frame_number); - - /// Return a bounding-box from BoxVec with it's properties adjusted by the Keyframes - BBox GetBox(int64_t frame_number); - /// Const-cast of the GetBox function, so that it can be called inside other cont function - BBox GetBox(int64_t frame_number) const - { - return const_cast(this)->GetBox(frame_number); - } - - /// Load the bounding-boxes information from the protobuf file - bool LoadBoxData(std::string inputFilePath); - - /// Get the time of the given frame - 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); - - /// Clear the BoxVec map - void clear(); - - /// Get and Set JSON methods - std::string Json() const override; ///< Generate JSON string of this object - Json::Value JsonValue() const override; ///< Generate Json::Value for this object - void SetJson(const std::string value) override; ///< Load JSON string into this object - void SetJsonValue(const Json::Value root) override; ///< Load Json::Value into this object - - /// Get all properties for a specific frame (perfect for a UI to display the current state + /** + * @brief This struct holds the information of a bounding-box. + * + * A bounding-box is a rectangular shape that enclosures an + * object or a desired set of pixels in a digital image. + * + * The bounding-box structure holds five floating-point properties: + * the x and y coordinates of the rectangle's center point (cx, cy), + * the rectangle's width, height and rotation. + */ + struct BBox + { + float cx = -1; ///< x-coordinate of the bounding box center + float cy = -1; ///< y-coordinate of the bounding box center + float width = -1; ///< bounding box width + float height = -1; ///< bounding box height + float angle = -1; ///< bounding box rotation angle [degrees] + + /// Blank constructor + BBox() {} + + /// Default constructor, which takes the bounding box top-left corner coordinates, width and height. + /// @param _cx X-coordinate of the bounding box center + /// @param _cy Y-coordinate of the bounding box center + /// @param _width Bounding box width + /// @param _height Bounding box height + /// @param _angle Bounding box rotation angle [degrees] + BBox(float _cx, float _cy, float _width, float _height, float _angle) + { + cx = _cx; + cy = _cy; + width = _width; + height = _height; + angle = _angle; + } + + + /// Generate JSON string of this object + std::string Json() const + { + return JsonValue().toStyledString(); + } + + /// Generate Json::Value for this object + Json::Value JsonValue() const + { + Json::Value root; + root["cx"] = cx; + root["cy"] = cy; + root["width"] = width; + root["height"] = height; + root["angle"] = angle; + + return root; + } + + /// Load JSON string into this object + void SetJson(const std::string value) + { + // Parse JSON string into JSON objects + try + { + const Json::Value root = openshot::stringToJson(value); + // Set all values that match + SetJsonValue(root); + } + catch (const std::exception &e) + { + // Error parsing JSON (or missing keys) + throw InvalidJSON("JSON is invalid (missing keys or invalid data types)"); + } + } + + /// Load Json::Value into this object + void SetJsonValue(const Json::Value root) + { + + // Set data from Json (if key is found) + if (!root["cx"].isNull()) + cx = root["cx"].asDouble(); + if (!root["cy"].isNull()) + cy = root["cy"].asDouble(); + if (!root["width"].isNull()) + width = root["width"].asDouble(); + if (!root["height"].isNull()) + height = root["height"].asDouble(); + if (!root["angle"].isNull()) + angle = root["angle"].asDouble(); + } + }; + + /** + * @brief This class contains the properties of a tracked object + * and functions to manipulate it. + * + * The bounding-box displacement in X and Y directions, it's width, + * height and rotation variation over the frames are set as + * openshot::Keyframe objects. + * + * The bounding-box information over the clip's frames are + * saved into a protobuf file and loaded into an + * object of this class. + */ + class TrackedObjectBBox : public TrackedObjectBase + { + private: + Fraction BaseFps; + double TimeScale; + + public: + std::map BoxVec; ///< Index the bounding-box by time of each frame + Keyframe delta_x; ///< X-direction displacement Keyframe + Keyframe delta_y; ///< Y-direction displacement Keyframe + 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 + Keyframe stroke_alpha; ///< Stroke box opacity + 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 + TrackedObjectBBox(); + TrackedObjectBBox(int Red, int Green, int Blue, int Alfa); + + /// Add a BBox to the BoxVec map + void AddBox(int64_t _frame_num, float _cx, float _cy, float _width, float _height, float _angle) override; + + /// Update object's BaseFps + void SetBaseFPS(Fraction fps); + + /// Return the object's BaseFps + Fraction GetBaseFPS(); + + /// Update the TimeScale member variable + void ScalePoints(double scale) override; + + /// Check if there is a bounding-box in the given frame + 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 override; + + /// Get the size of BoxVec map + int64_t GetLength() const; + + /// Remove a bounding-box from the BoxVec map + void RemoveBox(int64_t frame_number); + + /// Return a bounding-box from BoxVec with it's properties adjusted by the Keyframes + BBox GetBox(int64_t frame_number); + /// Const-cast of the GetBox function, so that it can be called inside other cont function + BBox GetBox(int64_t frame_number) const + { + return const_cast(this)->GetBox(frame_number); + } + + /// Load the bounding-boxes information from the protobuf file + bool LoadBoxData(std::string inputFilePath); + + /// Get the time of the given frame + 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); + + /// Clear the BoxVec map + void clear(); + + /// Get and Set JSON methods + std::string Json() const override; ///< Generate JSON string of this object + Json::Value JsonValue() const override; ///< Generate Json::Value for this object + void SetJson(const std::string value) override; ///< Load JSON string into this object + void SetJsonValue(const Json::Value root) override; ///< Load Json::Value into this object + + /// Get all properties for a specific frame (perfect for a UI to display the current state /// of all properties at any time) - Json::Value PropertiesJSON(int64_t requested_frame) const override; + Json::Value PropertiesJSON(int64_t requested_frame) const override; - // Generate JSON for a property - 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 + 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; - /// Return a map that contains the bounding box properties and it's keyframes indexed by their names - std::map GetBoxValues(int64_t frame_number) const override; - /// Return a map that contains the properties of this object's parent clip - std::map GetParentClipProperties(int64_t frame_number) const override; - - }; + /// Return a map that contains the bounding box properties and it's keyframes indexed by their names + std::map GetBoxValues(int64_t frame_number) const override; + /// Return a map that contains the properties of this object's parent clip + std::map GetParentClipProperties(int64_t frame_number) const override; + + }; } // namespace openshot #endif \ No newline at end of file diff --git a/src/TrackedObjectBase.h b/src/TrackedObjectBase.h index af74e45e6..371b056fc 100644 --- a/src/TrackedObjectBase.h +++ b/src/TrackedObjectBase.h @@ -47,36 +47,36 @@ namespace openshot { - /** + /** * @brief This abstract class is the base class of all Tracked Objects. * * A Tracked Object is an object or a desired set of pixels in a digital image * which properties (such as position, width and height) can be detected and * predicted along the frames of a clip. */ - class TrackedObjectBase { + class TrackedObjectBase { protected: std::string id; std::string childClipId; ClipBase* parentClip; - public: + public: Keyframe visible; Keyframe draw_box; - /// Default constructor - TrackedObjectBase(); + /// Default constructor + TrackedObjectBase(); /// Constructor which takes an object ID TrackedObjectBase(std::string _id); - /// Get the id of this object + /// Get the id of this object std::string Id() const { return id; } /// Set the id of this object void Id(std::string _id) { id = _id; } - /// Get and set the parentClip of this object + /// 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 @@ -84,23 +84,23 @@ namespace openshot { void ChildClipId(std::string _childClipId) { childClipId = _childClipId; }; /// Check if there is data for the exact frame number - virtual bool ExactlyContains(int64_t frame_number) const { return {}; }; + virtual bool ExactlyContains(int64_t frame_number) const { return {}; }; - /// Scale an object's property - virtual void ScalePoints(double scale) { return; }; + /// Scale an object's property + virtual void ScalePoints(double scale) { return; }; /// Return the main properties of a TrackedObjectBBox instance - such as position, size and rotation virtual std::map GetBoxValues(int64_t frame_number) const { std::map ret; return ret; }; - /// Return the main properties of the tracked object's parent clip - such as position, size and rotation - virtual std::map GetParentClipProperties(int64_t frame_number) const { std::map ret; return ret; } + /// Return the main properties of the tracked object's parent clip - such as position, size and rotation + virtual std::map GetParentClipProperties(int64_t frame_number) const { std::map ret; return ret; } /// Add a bounding box to the tracked object's BoxVec map virtual void AddBox(int64_t _frame_num, float _cx, float _cy, float _width, float _height, float _angle) { return; }; /// Get and Set JSON methods - virtual std::string Json() const = 0; ///< Generate JSON string of this object - virtual Json::Value JsonValue() const = 0; ///< Generate Json::Value for this object - virtual void SetJson(const std::string value) = 0; ///< Load JSON string into this object - virtual void SetJsonValue(const Json::Value root) = 0; ///< Load Json::Value into this object + virtual std::string Json() const = 0; ///< Generate JSON string of this object + virtual Json::Value JsonValue() const = 0; ///< Generate Json::Value for this object + virtual void SetJson(const std::string value) = 0; ///< Load JSON string into this object + virtual void SetJsonValue(const Json::Value root) = 0; ///< Load Json::Value into this object /// Get all properties for a specific frame (perfect for a UI to display the current state /// of all properties at any time) diff --git a/src/effects/ObjectDetection.cpp b/src/effects/ObjectDetection.cpp index dbb00522c..9c947e911 100644 --- a/src/effects/ObjectDetection.cpp +++ b/src/effects/ObjectDetection.cpp @@ -39,495 +39,495 @@ using namespace openshot; /// Blank constructor, useful when using Json to load the effect properties ObjectDetection::ObjectDetection(std::string clipObDetectDataPath) { - // Init effect properties - init_effect_details(); + // Init effect properties + init_effect_details(); - // Tries to load the tracker data from protobuf - LoadObjDetectdData(clipObDetectDataPath); + // Tries to load the tracker data from protobuf + LoadObjDetectdData(clipObDetectDataPath); - // Initialize the selected object index as the first object index - selectedObjectIndex = trackedObjects.begin()->first; + // Initialize the selected object index as the first object index + selectedObjectIndex = trackedObjects.begin()->first; } // Default constructor ObjectDetection::ObjectDetection() { - // Init effect properties - init_effect_details(); + // Init effect properties + init_effect_details(); - // Initialize the selected object index as the first object index - selectedObjectIndex = trackedObjects.begin()->first; + // Initialize the selected object index as the first object index + selectedObjectIndex = trackedObjects.begin()->first; } // Init effect settings void ObjectDetection::init_effect_details() { - /// Initialize the values of the EffectInfo struct. - InitEffectInfo(); - - /// Set the effect info - info.class_name = "Object Detector"; - info.name = "Object Detector"; - info.description = "Detect objects through the video."; - info.has_audio = false; - info.has_video = true; - info.has_tracked_object = true; + /// Initialize the values of the EffectInfo struct. + InitEffectInfo(); + + /// Set the effect info + info.class_name = "Object Detector"; + info.name = "Object Detector"; + info.description = "Detect objects through the video."; + info.has_audio = false; + info.has_video = true; + info.has_tracked_object = true; } // This method is required for all derived classes of EffectBase, and returns a // modified openshot::Frame object std::shared_ptr ObjectDetection::GetFrame(std::shared_ptr frame, int64_t frame_number) { - // Get the frame's image - cv::Mat cv_image = frame->GetImageCV(); - - // Check if frame isn't NULL - if(cv_image.empty()){ - return frame; - } - - // Check if track data exists for the requested frame - if (detectionsData.find(frame_number) != detectionsData.end()) { - float fw = cv_image.size().width; - float fh = cv_image.size().height; - - DetectionData detections = detectionsData[frame_number]; - for(int i = 0; i 0 && - std::find(display_classes.begin(), display_classes.end(), classNames[detections.classIds.at(i)]) == display_classes.end()){ - continue; - } - - // Get the object id - int objectId = detections.objectIds.at(i); - - // Search for the object in the trackedObjects map - auto trackedObject_it = trackedObjects.find(objectId); - - // Cast the object as TrackedObjectBBox - std::shared_ptr trackedObject = std::static_pointer_cast(trackedObject_it->second); - - // Check if the tracked object has data for this frame - if (trackedObject->Contains(frame_number) && - trackedObject->visible.GetValue(frame_number) == 1) - { - // Get the bounding-box of given frame - BBox trackedBox = trackedObject->GetBox(frame_number); - - std::vector stroke_rgba = trackedObject->stroke.GetColorRGBA(frame_number); - int stroke_width = trackedObject->stroke_width.GetValue(frame_number); - float stroke_alpha = trackedObject->stroke_alpha.GetValue(frame_number); - std::vector bg_rgba = trackedObject->background.GetColorRGBA(frame_number); - float bg_alpha = trackedObject->background_alpha.GetValue(frame_number); - - // Create a rotated rectangle object that holds the bounding box - // cv::RotatedRect box ( cv::Point2f( (int)(trackedBox.cx*fw), (int)(trackedBox.cy*fh) ), - // cv::Size2f( (int)(trackedBox.width*fw), (int)(trackedBox.height*fh) ), - // (int) (trackedBox.angle) ); - - // DrawRectangleRGBA(cv_image, box, bg_rgba, bg_alpha, 1, true); - // DrawRectangleRGBA(cv_image, box, stroke_rgba, stroke_alpha, stroke_width, false); - - cv::Rect2d box( - (int)( (trackedBox.cx-trackedBox.width/2)*fw), - (int)( (trackedBox.cy-trackedBox.height/2)*fh), - (int)( trackedBox.width*fw), - (int)( trackedBox.height*fh) - ); - drawPred(detections.classIds.at(i), detections.confidences.at(i), - box, cv_image, detections.objectIds.at(i), bg_rgba, bg_alpha, 1, true); - drawPred(detections.classIds.at(i), detections.confidences.at(i), - box, cv_image, detections.objectIds.at(i), stroke_rgba, stroke_alpha, stroke_width, false); - } - } - } - - // Update Qt image with new Opencv frame - frame->SetImageCV(cv_image); - - return frame; + // Get the frame's image + cv::Mat cv_image = frame->GetImageCV(); + + // Check if frame isn't NULL + if(cv_image.empty()){ + return frame; + } + + // Check if track data exists for the requested frame + if (detectionsData.find(frame_number) != detectionsData.end()) { + float fw = cv_image.size().width; + float fh = cv_image.size().height; + + DetectionData detections = detectionsData[frame_number]; + for(int i = 0; i 0 && + std::find(display_classes.begin(), display_classes.end(), classNames[detections.classIds.at(i)]) == display_classes.end()){ + continue; + } + + // Get the object id + int objectId = detections.objectIds.at(i); + + // Search for the object in the trackedObjects map + auto trackedObject_it = trackedObjects.find(objectId); + + // Cast the object as TrackedObjectBBox + std::shared_ptr trackedObject = std::static_pointer_cast(trackedObject_it->second); + + // Check if the tracked object has data for this frame + if (trackedObject->Contains(frame_number) && + trackedObject->visible.GetValue(frame_number) == 1) + { + // Get the bounding-box of given frame + BBox trackedBox = trackedObject->GetBox(frame_number); + + std::vector stroke_rgba = trackedObject->stroke.GetColorRGBA(frame_number); + int stroke_width = trackedObject->stroke_width.GetValue(frame_number); + float stroke_alpha = trackedObject->stroke_alpha.GetValue(frame_number); + std::vector bg_rgba = trackedObject->background.GetColorRGBA(frame_number); + float bg_alpha = trackedObject->background_alpha.GetValue(frame_number); + + // Create a rotated rectangle object that holds the bounding box + // cv::RotatedRect box ( cv::Point2f( (int)(trackedBox.cx*fw), (int)(trackedBox.cy*fh) ), + // cv::Size2f( (int)(trackedBox.width*fw), (int)(trackedBox.height*fh) ), + // (int) (trackedBox.angle) ); + + // DrawRectangleRGBA(cv_image, box, bg_rgba, bg_alpha, 1, true); + // DrawRectangleRGBA(cv_image, box, stroke_rgba, stroke_alpha, stroke_width, false); + + cv::Rect2d box( + (int)( (trackedBox.cx-trackedBox.width/2)*fw), + (int)( (trackedBox.cy-trackedBox.height/2)*fh), + (int)( trackedBox.width*fw), + (int)( trackedBox.height*fh) + ); + drawPred(detections.classIds.at(i), detections.confidences.at(i), + box, cv_image, detections.objectIds.at(i), bg_rgba, bg_alpha, 1, true); + drawPred(detections.classIds.at(i), detections.confidences.at(i), + box, cv_image, detections.objectIds.at(i), stroke_rgba, stroke_alpha, stroke_width, false); + } + } + } + + // Update Qt image with new Opencv frame + frame->SetImageCV(cv_image); + + return frame; } void ObjectDetection::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); - } + 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); + } } void ObjectDetection::drawPred(int classId, float conf, cv::Rect2d box, cv::Mat& frame, int objectNumber, std::vector color, - float alpha, int thickness, bool is_background) + float alpha, int thickness, bool is_background) { - if(is_background){ - cv::Mat overlayFrame; - frame.copyTo(overlayFrame); - - //Draw a rectangle displaying the bounding box - cv::rectangle(overlayFrame, box, cv::Scalar(color[2],color[1],color[0]), cv::FILLED); - - // add opacity - cv::addWeighted(overlayFrame, 1-alpha, frame, alpha, 0, frame); - } - else{ - cv::Mat overlayFrame; - frame.copyTo(overlayFrame); - - //Draw a rectangle displaying the bounding box - cv::rectangle(overlayFrame, box, cv::Scalar(color[2],color[1],color[0]), thickness); - - //Get the label for the class name and its confidence - std::string label = cv::format("%.2f", conf); - if (!classNames.empty()) - { - CV_Assert(classId < (int)classNames.size()); - label = classNames[classId] + ":" + label; - } - - //Display the label at the top of the bounding box - int baseLine; - cv::Size labelSize = cv::getTextSize(label, cv::FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine); - - double left = box.x; - double top = std::max((int)box.y, labelSize.height); - - cv::rectangle(overlayFrame, cv::Point(left, top - round(1.025*labelSize.height)), cv::Point(left + round(1.025*labelSize.width), top + baseLine), - cv::Scalar(color[2],color[1],color[0]), cv::FILLED); - putText(overlayFrame, label, cv::Point(left+1, top), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0,0,0),1); - - // add opacity - cv::addWeighted(overlayFrame, 1-alpha, frame, alpha, 0, frame); - } + if(is_background){ + cv::Mat overlayFrame; + frame.copyTo(overlayFrame); + + //Draw a rectangle displaying the bounding box + cv::rectangle(overlayFrame, box, cv::Scalar(color[2],color[1],color[0]), cv::FILLED); + + // add opacity + cv::addWeighted(overlayFrame, 1-alpha, frame, alpha, 0, frame); + } + else{ + cv::Mat overlayFrame; + frame.copyTo(overlayFrame); + + //Draw a rectangle displaying the bounding box + cv::rectangle(overlayFrame, box, cv::Scalar(color[2],color[1],color[0]), thickness); + + //Get the label for the class name and its confidence + std::string label = cv::format("%.2f", conf); + if (!classNames.empty()) + { + CV_Assert(classId < (int)classNames.size()); + label = classNames[classId] + ":" + label; + } + + //Display the label at the top of the bounding box + int baseLine; + cv::Size labelSize = cv::getTextSize(label, cv::FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine); + + double left = box.x; + double top = std::max((int)box.y, labelSize.height); + + cv::rectangle(overlayFrame, cv::Point(left, top - round(1.025*labelSize.height)), cv::Point(left + round(1.025*labelSize.width), top + baseLine), + cv::Scalar(color[2],color[1],color[0]), cv::FILLED); + putText(overlayFrame, label, cv::Point(left+1, top), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0,0,0),1); + + // add opacity + cv::addWeighted(overlayFrame, 1-alpha, frame, alpha, 0, frame); + } } // Load protobuf data file bool ObjectDetection::LoadObjDetectdData(std::string inputFilePath){ - // Create tracker message - pb_objdetect::ObjDetect objMessage; - - - // Read the existing tracker message. - fstream input(inputFilePath, ios::in | ios::binary); - if (!objMessage.ParseFromIstream(&input)) { - cerr << "Failed to parse protobuf message." << endl; - return false; - } - - - // Make sure classNames, detectionsData and trackedObjects are empty - classNames.clear(); - detectionsData.clear(); - trackedObjects.clear(); - - // Seed to generate same random numbers - std::srand(1); - // Get all classes names and assign a color to them - for(int i = 0; i < objMessage.classnames_size(); i++) - { - classNames.push_back(objMessage.classnames(i)); - classesColor.push_back(cv::Scalar(std::rand()%205 + 50, std::rand()%205 + 50, std::rand()%205 + 50)); - } - - // Iterate over all frames of the saved message - for (size_t i = 0; i < objMessage.frame_size(); i++) - { - // Create protobuf message reader - const pb_objdetect::Frame& pbFrameData = objMessage.frame(i); - - // Get frame Id - size_t id = pbFrameData.id(); - - // Load bounding box data - const google::protobuf::RepeatedPtrField &pBox = pbFrameData.bounding_box(); - - // Construct data vectors related to detections in the current frame - std::vector classIds; - std::vector confidences; - std::vector> boxes; - std::vector objectIds; - - // Iterate through the detected objects - for(int i = 0; i < pbFrameData.bounding_box_size(); i++) - { - // Get bounding box coordinates - float x = pBox.Get(i).x(); - float y = pBox.Get(i).y(); - float w = pBox.Get(i).w(); - float h = pBox.Get(i).h(); - // Get class Id (which will be assign to a class name) - int classId = pBox.Get(i).classid(); - // Get prediction confidence - float confidence = pBox.Get(i).confidence(); - - // Get the object Id - int objectId = pBox.Get(i).objectid(); - - // Search for the object id on trackedObjects map - auto trackedObject = trackedObjects.find(objectId); - // Check if object already exists on the map - if (trackedObject != trackedObjects.end()) - { - // Add a new BBox to it - trackedObject->second->AddBox(id, x+(w/2), y+(h/2), w, h, 0.0); - } - else - { - // There is no tracked object with that id, so insert a new one - TrackedObjectBBox trackedObj((int)classesColor[classId](0), (int)classesColor[classId](1), (int)classesColor[classId](2), (int)0); - trackedObj.AddBox(id, x+(w/2), y+(h/2), w, h, 0.0); - std::shared_ptr trackedObjPtr = std::make_shared(trackedObj); - trackedObjects.insert({objectId, trackedObjPtr}); - } - - // Create OpenCV rectangle with the bouding box info - cv::Rect_ box(x, y, w, h); - - // Push back data into vectors - boxes.push_back(box); - classIds.push_back(classId); - confidences.push_back(confidence); - objectIds.push_back(objectId); - } - - // Assign data to object detector map - detectionsData[id] = DetectionData(classIds, confidences, boxes, id, objectIds); - } - - // Delete all global objects allocated by libprotobuf. - google::protobuf::ShutdownProtobufLibrary(); - - return true; + // Create tracker message + pb_objdetect::ObjDetect objMessage; + + + // Read the existing tracker message. + fstream input(inputFilePath, ios::in | ios::binary); + if (!objMessage.ParseFromIstream(&input)) { + cerr << "Failed to parse protobuf message." << endl; + return false; + } + + + // Make sure classNames, detectionsData and trackedObjects are empty + classNames.clear(); + detectionsData.clear(); + trackedObjects.clear(); + + // Seed to generate same random numbers + std::srand(1); + // Get all classes names and assign a color to them + for(int i = 0; i < objMessage.classnames_size(); i++) + { + classNames.push_back(objMessage.classnames(i)); + classesColor.push_back(cv::Scalar(std::rand()%205 + 50, std::rand()%205 + 50, std::rand()%205 + 50)); + } + + // Iterate over all frames of the saved message + for (size_t i = 0; i < objMessage.frame_size(); i++) + { + // Create protobuf message reader + const pb_objdetect::Frame& pbFrameData = objMessage.frame(i); + + // Get frame Id + size_t id = pbFrameData.id(); + + // Load bounding box data + const google::protobuf::RepeatedPtrField &pBox = pbFrameData.bounding_box(); + + // Construct data vectors related to detections in the current frame + std::vector classIds; + std::vector confidences; + std::vector> boxes; + std::vector objectIds; + + // Iterate through the detected objects + for(int i = 0; i < pbFrameData.bounding_box_size(); i++) + { + // Get bounding box coordinates + float x = pBox.Get(i).x(); + float y = pBox.Get(i).y(); + float w = pBox.Get(i).w(); + float h = pBox.Get(i).h(); + // Get class Id (which will be assign to a class name) + int classId = pBox.Get(i).classid(); + // Get prediction confidence + float confidence = pBox.Get(i).confidence(); + + // Get the object Id + int objectId = pBox.Get(i).objectid(); + + // Search for the object id on trackedObjects map + auto trackedObject = trackedObjects.find(objectId); + // Check if object already exists on the map + if (trackedObject != trackedObjects.end()) + { + // Add a new BBox to it + trackedObject->second->AddBox(id, x+(w/2), y+(h/2), w, h, 0.0); + } + else + { + // There is no tracked object with that id, so insert a new one + TrackedObjectBBox trackedObj((int)classesColor[classId](0), (int)classesColor[classId](1), (int)classesColor[classId](2), (int)0); + trackedObj.AddBox(id, x+(w/2), y+(h/2), w, h, 0.0); + std::shared_ptr trackedObjPtr = std::make_shared(trackedObj); + trackedObjects.insert({objectId, trackedObjPtr}); + } + + // Create OpenCV rectangle with the bouding box info + cv::Rect_ box(x, y, w, h); + + // Push back data into vectors + boxes.push_back(box); + classIds.push_back(classId); + confidences.push_back(confidence); + objectIds.push_back(objectId); + } + + // Assign data to object detector map + detectionsData[id] = DetectionData(classIds, confidences, boxes, id, objectIds); + } + + // Delete all global objects allocated by libprotobuf. + google::protobuf::ShutdownProtobufLibrary(); + + return true; } // Get tracker info for the desired frame DetectionData ObjectDetection::GetTrackedData(size_t frameId){ - // Check if the tracker info for the requested frame exists - if ( detectionsData.find(frameId) == detectionsData.end() ) { - return DetectionData(); - } else { - return detectionsData[frameId]; - } + // Check if the tracker info for the requested frame exists + if ( detectionsData.find(frameId) == detectionsData.end() ) { + return DetectionData(); + } else { + return detectionsData[frameId]; + } } // Get the indexes and IDs of all visible objects in the given frame std::string ObjectDetection::GetVisibleObjects(int64_t frame_number) const{ - - // Initialize the JSON objects - Json::Value root; - root["visible_objects_index"] = Json::Value(Json::arrayValue); - root["visible_objects_id"] = Json::Value(Json::arrayValue); - - // Check if track data exists for the requested frame - if (detectionsData.find(frame_number) == detectionsData.end()){ - return root.toStyledString(); - } - DetectionData detections = detectionsData.at(frame_number); - - // Iterate through the tracked objects - for(int i = 0; i 0 && - std::find(display_classes.begin(), display_classes.end(), classNames[detections.classIds.at(i)]) == display_classes.end()){ - continue; - } - - int objectId = detections.objectIds.at(i); - // Search for the object in the trackedObjects map - auto trackedObject = trackedObjects.find(objectId); - - // Get the tracked object JSON properties for this frame - Json::Value trackedObjectJSON = trackedObject->second->PropertiesJSON(frame_number); - - if (trackedObjectJSON["visible"]["value"].asBool() && - trackedObject->second->ExactlyContains(frame_number)){ - // Save the object's index and ID if it's visible in this frame - root["visible_objects_index"].append(trackedObject->first); - root["visible_objects_id"].append(trackedObject->second->Id()); - } - } - - return root.toStyledString(); + + // Initialize the JSON objects + Json::Value root; + root["visible_objects_index"] = Json::Value(Json::arrayValue); + root["visible_objects_id"] = Json::Value(Json::arrayValue); + + // Check if track data exists for the requested frame + if (detectionsData.find(frame_number) == detectionsData.end()){ + return root.toStyledString(); + } + DetectionData detections = detectionsData.at(frame_number); + + // Iterate through the tracked objects + for(int i = 0; i 0 && + std::find(display_classes.begin(), display_classes.end(), classNames[detections.classIds.at(i)]) == display_classes.end()){ + continue; + } + + int objectId = detections.objectIds.at(i); + // Search for the object in the trackedObjects map + auto trackedObject = trackedObjects.find(objectId); + + // Get the tracked object JSON properties for this frame + Json::Value trackedObjectJSON = trackedObject->second->PropertiesJSON(frame_number); + + if (trackedObjectJSON["visible"]["value"].asBool() && + trackedObject->second->ExactlyContains(frame_number)){ + // Save the object's index and ID if it's visible in this frame + root["visible_objects_index"].append(trackedObject->first); + root["visible_objects_id"].append(trackedObject->second->Id()); + } + } + + return root.toStyledString(); } // Generate JSON string of this object std::string ObjectDetection::Json() const { - // Return formatted string - return JsonValue().toStyledString(); + // Return formatted string + return JsonValue().toStyledString(); } // Generate Json::Value for this object Json::Value ObjectDetection::JsonValue() const { - // Create root json object - Json::Value root = EffectBase::JsonValue(); // get parent properties - root["type"] = info.class_name; - root["protobuf_data_path"] = protobuf_data_path; - root["selected_object_index"] = selectedObjectIndex; - root["confidence_threshold"] = confidence_threshold; - - // Add tracked object's IDs to root - root["objects_id"] = Json::Value(Json::arrayValue); - for (auto const& trackedObject : trackedObjects){ - Json::Value trackedObjectJSON = trackedObject.second->JsonValue(); - root["objects_id"].append(trackedObject.second->Id()); - } - - // Add the selected object Json to root - if(trackedObjects.count(selectedObjectIndex) != 0){ - auto selectedObject = trackedObjects.at(selectedObjectIndex); - if (selectedObject){ - Json::Value selectedObjectJSON = selectedObject->JsonValue(); - for (auto const& key : selectedObjectJSON.getMemberNames()) - root[key] = selectedObjectJSON[key]; - } - } - - // return JsonValue - return root; + // Create root json object + Json::Value root = EffectBase::JsonValue(); // get parent properties + root["type"] = info.class_name; + root["protobuf_data_path"] = protobuf_data_path; + root["selected_object_index"] = selectedObjectIndex; + root["confidence_threshold"] = confidence_threshold; + + // Add tracked object's IDs to root + root["objects_id"] = Json::Value(Json::arrayValue); + for (auto const& trackedObject : trackedObjects){ + Json::Value trackedObjectJSON = trackedObject.second->JsonValue(); + root["objects_id"].append(trackedObject.second->Id()); + } + + // Add the selected object Json to root + if(trackedObjects.count(selectedObjectIndex) != 0){ + auto selectedObject = trackedObjects.at(selectedObjectIndex); + if (selectedObject){ + Json::Value selectedObjectJSON = selectedObject->JsonValue(); + for (auto const& key : selectedObjectJSON.getMemberNames()) + root[key] = selectedObjectJSON[key]; + } + } + + // return JsonValue + return root; } // Load JSON string into this object void ObjectDetection::SetJson(const std::string value) { - // Parse JSON string into JSON objects - try - { - std::cout<<"entrou no objectDetection SetJson \n"<SetJsonValue(trackedObjectJSON); - } - } - - // Set the selected object's properties - if(trackedObjects.count(selectedObjectIndex) != 0){ - auto selectedObject = trackedObjects.at(selectedObjectIndex); - if (selectedObject) - selectedObject->SetJsonValue(root); - } + std::cout<<"entrou no objectDetection SetJasonValue \n"<SetJsonValue(trackedObjectJSON); + } + } + + // Set the selected object's properties + if(trackedObjects.count(selectedObjectIndex) != 0){ + auto selectedObject = trackedObjects.at(selectedObjectIndex); + if (selectedObject) + selectedObject->SetJsonValue(root); + } } // Get all properties for a specific frame std::string ObjectDetection::PropertiesJSON(int64_t requested_frame) const { - // Generate JSON properties list - Json::Value root; - - // Add the selected object Json to root - if(trackedObjects.count(selectedObjectIndex) != 0){ - auto selectedObject = trackedObjects.at(selectedObjectIndex); - if (selectedObject) - root = selectedObject->PropertiesJSON(requested_frame); - } - - root["selected_object_index"] = add_property_json("Selected Object", selectedObjectIndex, "int", "", NULL, 0, 200, false, requested_frame); - root["id"] = add_property_json("ID", 0.0, "string", Id(), NULL, -1, -1, true, requested_frame); - root["position"] = add_property_json("Position", Position(), "float", "", NULL, 0, 1000 * 60 * 30, false, requested_frame); - root["layer"] = add_property_json("Track", Layer(), "int", "", NULL, 0, 20, false, requested_frame); - root["start"] = add_property_json("Start", Start(), "float", "", NULL, 0, 1000 * 60 * 30, false, requested_frame); - root["end"] = add_property_json("End", End(), "float", "", NULL, 0, 1000 * 60 * 30, false, requested_frame); - root["duration"] = add_property_json("Duration", Duration(), "float", "", NULL, 0, 1000 * 60 * 30, true, requested_frame); - root["confidence_threshold"] = add_property_json("Confidence Theshold", confidence_threshold, "float", "", NULL, 0, 1, false, requested_frame); - root["class_filter"] = add_property_json("Class Filter", 0.0, "string", class_filter, NULL, -1, -1, false, requested_frame); - // Return formatted string - return root.toStyledString(); + // Generate JSON properties list + Json::Value root; + + // Add the selected object Json to root + if(trackedObjects.count(selectedObjectIndex) != 0){ + auto selectedObject = trackedObjects.at(selectedObjectIndex); + if (selectedObject) + root = selectedObject->PropertiesJSON(requested_frame); + } + + root["selected_object_index"] = add_property_json("Selected Object", selectedObjectIndex, "int", "", NULL, 0, 200, false, requested_frame); + root["id"] = add_property_json("ID", 0.0, "string", Id(), NULL, -1, -1, true, requested_frame); + root["position"] = add_property_json("Position", Position(), "float", "", NULL, 0, 1000 * 60 * 30, false, requested_frame); + root["layer"] = add_property_json("Track", Layer(), "int", "", NULL, 0, 20, false, requested_frame); + root["start"] = add_property_json("Start", Start(), "float", "", NULL, 0, 1000 * 60 * 30, false, requested_frame); + root["end"] = add_property_json("End", End(), "float", "", NULL, 0, 1000 * 60 * 30, false, requested_frame); + root["duration"] = add_property_json("Duration", Duration(), "float", "", NULL, 0, 1000 * 60 * 30, true, requested_frame); + root["confidence_threshold"] = add_property_json("Confidence Theshold", confidence_threshold, "float", "", NULL, 0, 1, false, requested_frame); + root["class_filter"] = add_property_json("Class Filter", 0.0, "string", class_filter, NULL, -1, -1, false, requested_frame); + // Return formatted string + return root.toStyledString(); } From a7cefa4bd29cae458a86640ef4381254d31d0c03 Mon Sep 17 00:00:00 2001 From: Brenno Date: Mon, 12 Apr 2021 21:22:58 -0300 Subject: [PATCH 62/84] Removed namespaces, iostream library and added TrackedObject test --- src/TimelineBase.h | 1 - src/effects/Tracker.h | 1 - tests/KeyFrame.cpp | 29 ++++++++++++++++++++++++++--- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/TimelineBase.h b/src/TimelineBase.h index 7bcd8f9a9..39dd3a41f 100644 --- a/src/TimelineBase.h +++ b/src/TimelineBase.h @@ -30,7 +30,6 @@ #ifndef OPENSHOT_TIMELINE_BASE_H #define OPENSHOT_TIMELINE_BASE_H -#include namespace openshot { /** diff --git a/src/effects/Tracker.h b/src/effects/Tracker.h index 2faafcb27..0ccf589c5 100644 --- a/src/effects/Tracker.h +++ b/src/effects/Tracker.h @@ -44,7 +44,6 @@ #include "../TrackedObjectBBox.h" #include "../Clip.h" -using namespace std; namespace openshot { /** diff --git a/tests/KeyFrame.cpp b/tests/KeyFrame.cpp index f476faafa..3e0b381c4 100644 --- a/tests/KeyFrame.cpp +++ b/tests/KeyFrame.cpp @@ -516,9 +516,32 @@ TEST_CASE( "Point_Vector_Constructor", "[libopenshot][keyframe]" ) TEST_CASE( "TrackedObjectBBox init", "[libopenshot][keyframe]" ) { - TrackedObjectBBox kfb; - // XXX: This really needs to perform some sort of _test_ here, - // like confirming some default values in the new object. + TrackedObjectBBox kfb(62,143,0,212); + + CHECK(kfb.delta_x.GetInt(1) == 0); + CHECK(kfb.delta_y.GetInt(1) == 0); + + CHECK(kfb.scale_x.GetInt(1) == 1); + CHECK(kfb.scale_y.GetInt(1) == 1); + + CHECK(kfb.rotation.GetInt(1) == 0); + + CHECK(kfb.stroke_width.GetInt(1) == 2); + CHECK(kfb.stroke_alpha.GetInt(1) == 0); + + CHECK(kfb.background_alpha .GetInt(1)== 1); + CHECK(kfb.background_corner.GetInt(1) == 0); + + CHECK(kfb.stroke.red.GetInt(1) == 62); + CHECK(kfb.stroke.green.GetInt(1) == 143); + CHECK(kfb.stroke.blue.GetInt(1) == 0); + CHECK(kfb.stroke.alpha.GetInt(1) == 212); + + CHECK(kfb.background.red.GetInt(1) == 0); + CHECK(kfb.background.green.GetInt(1) == 0); + CHECK(kfb.background.blue.GetInt(1) == 255); + CHECK(kfb.background.alpha.GetInt(1) == 0); + } TEST_CASE( "TrackedObjectBBox AddBox and RemoveBox", "[libopenshot][keyframe]" ) From 2cf2c55f9b835eb4bbc033e3c57cdaf911c34fd8 Mon Sep 17 00:00:00 2001 From: Brenno Date: Mon, 12 Apr 2021 21:32:27 -0300 Subject: [PATCH 63/84] Changed None to empty string, corrected dynamic pointers --- src/Clip.cpp | 10 +++++----- src/EffectBase.cpp | 4 ++-- src/KeyFrame.cpp | 7 +++---- src/TrackedObjectBBox.cpp | 4 ++-- src/TrackedObjectBase.cpp | 8 ++++---- src/effects/Tracker.cpp | 2 +- tests/KeyFrame.cpp | 10 ++++++---- tests/KeyFrame_Tests.cpp | 2 +- 8 files changed, 24 insertions(+), 23 deletions(-) diff --git a/src/Clip.cpp b/src/Clip.cpp index e94b7d0c3..0d4068cf7 100644 --- a/src/Clip.cpp +++ b/src/Clip.cpp @@ -749,7 +749,7 @@ std::string Clip::PropertiesJSON(int64_t requested_frame) const { if (!parentObjectId.empty()) { root["parentObjectId"] = add_property_json("Parent", 0.0, "string", parentObjectId, NULL, -1, -1, false, requested_frame); } else { - root["parentObjectId"] = add_property_json("Parent", 0.0, "string", "None", NULL, -1, -1, false, requested_frame); + root["parentObjectId"] = add_property_json("Parent", 0.0, "string", "", NULL, -1, -1, false, requested_frame); } // Add gravity choices (dropdown style) root["gravity"]["choices"].append(add_property_choice_json("Top Left", GRAVITY_TOP_LEFT, gravity)); @@ -766,16 +766,16 @@ std::string Clip::PropertiesJSON(int64_t requested_frame) const { root["scale"]["choices"].append(add_property_choice_json("Crop", SCALE_CROP, scale)); root["scale"]["choices"].append(add_property_choice_json("Best Fit", SCALE_FIT, scale)); root["scale"]["choices"].append(add_property_choice_json("Stretch", SCALE_STRETCH, scale)); - root["scale"]["choices"].append(add_property_choice_json("None", SCALE_NONE, scale)); + root["scale"]["choices"].append(add_property_choice_json("", SCALE_NONE, scale)); // Add frame number display choices (dropdown style) - root["display"]["choices"].append(add_property_choice_json("None", FRAME_DISPLAY_NONE, display)); + root["display"]["choices"].append(add_property_choice_json("", FRAME_DISPLAY_NONE, display)); root["display"]["choices"].append(add_property_choice_json("Clip", FRAME_DISPLAY_CLIP, display)); root["display"]["choices"].append(add_property_choice_json("Timeline", FRAME_DISPLAY_TIMELINE, display)); root["display"]["choices"].append(add_property_choice_json("Both", FRAME_DISPLAY_BOTH, display)); // Add volume mixing choices (dropdown style) - root["mixing"]["choices"].append(add_property_choice_json("None", VOLUME_MIX_NONE, mixing)); + root["mixing"]["choices"].append(add_property_choice_json("", VOLUME_MIX_NONE, mixing)); root["mixing"]["choices"].append(add_property_choice_json("Average", VOLUME_MIX_AVERAGE, mixing)); root["mixing"]["choices"].append(add_property_choice_json("Reduce", VOLUME_MIX_REDUCE, mixing)); @@ -962,7 +962,7 @@ void Clip::SetJsonValue(const Json::Value root) { // Set data from Json (if key is found) if (!root["parentObjectId"].isNull()){ parentObjectId = root["parentObjectId"].asString(); - if (parentObjectId.size() > 0 && parentObjectId != "None"){ + if (parentObjectId.size() > 0 && parentObjectId != ""){ AttachToObject(parentObjectId); } else{ parentTrackedObject = nullptr; diff --git a/src/EffectBase.cpp b/src/EffectBase.cpp index 8f453ca50..97e1ef5ee 100644 --- a/src/EffectBase.cpp +++ b/src/EffectBase.cpp @@ -52,7 +52,7 @@ void EffectBase::InitEffectInfo() info.has_tracked_object = false; info.name = ""; info.description = ""; - info.parent_effect_id = "None"; + info.parent_effect_id = ""; } // Display file information @@ -160,7 +160,7 @@ void EffectBase::SetJsonValue(Json::Value root) { if (!root["parent_effect_id"].isNull()){ info.parent_effect_id = root["parent_effect_id"].asString(); - if (info.parent_effect_id.size() > 0 && info.parent_effect_id != "None" && parentEffect == NULL) + if (info.parent_effect_id.size() > 0 && info.parent_effect_id != "" && parentEffect == NULL) SetParentEffect(info.parent_effect_id); else parentEffect = NULL; diff --git a/src/KeyFrame.cpp b/src/KeyFrame.cpp index 421a562ef..048ef9313 100644 --- a/src/KeyFrame.cpp +++ b/src/KeyFrame.cpp @@ -34,9 +34,9 @@ #include #include #include -#include // For assert() -#include // For std::cout -#include // For std::setprecision +#include // For assert() +#include // For std::cout +#include // For std::setprecision using namespace std; using namespace openshot; @@ -92,7 +92,6 @@ namespace openshot{ t_step /= 2; } while (true); } - // Interpolate two points using the right Point's interpolation method double InterpolateBetween(Point const & left, Point const & right, double target, double allowed_error) { assert(left.co.X < target); diff --git a/src/TrackedObjectBBox.cpp b/src/TrackedObjectBBox.cpp index 899829323..447efaf2f 100644 --- a/src/TrackedObjectBBox.cpp +++ b/src/TrackedObjectBBox.cpp @@ -370,7 +370,7 @@ void TrackedObjectBBox::SetJsonValue(const Json::Value root) { // Set the Id by the given JSON object - if (!root["box_id"].isNull() && root["box_id"].asString() != "None") + if (!root["box_id"].isNull() && root["box_id"].asString() != "") Id(root["box_id"].asString()); // Set the BaseFps by the given JSON object @@ -395,7 +395,7 @@ void TrackedObjectBBox::SetJsonValue(const Json::Value root) // Set the id of the child clip // Does not allow to link to the parent clip - if (!root["child_clip_id"].isNull() && root["box_id"].asString() != "None"){ + if (!root["child_clip_id"].isNull() && root["box_id"].asString() != ""){ Clip* parentClip = (Clip *) ParentClip(); if(parentClip && (root["child_clip_id"].asString() != parentClip->Id())){ diff --git a/src/TrackedObjectBase.cpp b/src/TrackedObjectBase.cpp index acdc9e399..631e0a651 100644 --- a/src/TrackedObjectBase.cpp +++ b/src/TrackedObjectBase.cpp @@ -39,16 +39,16 @@ namespace openshot // Blank constructor TrackedObjectBase::TrackedObjectBase() : visible(1.0), draw_box(1) { - // Initializes the id as "None" - id = "None"; - childClipId = "None"; + // Initializes the id as "" + id = ""; + childClipId = ""; } // Default constructor TrackedObjectBase::TrackedObjectBase(std::string _id) : visible(1.0) { Id(_id); - childClipId = "None"; + childClipId = ""; } Json::Value TrackedObjectBase::add_property_choice_json(std::string name, int value, int selected_value) const diff --git a/src/effects/Tracker.cpp b/src/effects/Tracker.cpp index 52dc90796..c4373d667 100644 --- a/src/effects/Tracker.cpp +++ b/src/effects/Tracker.cpp @@ -132,7 +132,7 @@ std::shared_ptr Tracker::GetFrame(std::shared_ptr frame, int64_t f } // Get the image of the Tracked Object' child clip - if (trackedData->ChildClipId() != "None"){ + if (trackedData->ChildClipId() != ""){ // Cast the parent timeline of this effect Timeline* parentTimeline = (Timeline *) ParentTimeline(); if (parentTimeline){ diff --git a/tests/KeyFrame.cpp b/tests/KeyFrame.cpp index 3e0b381c4..a75e5a952 100644 --- a/tests/KeyFrame.cpp +++ b/tests/KeyFrame.cpp @@ -693,8 +693,9 @@ TEST_CASE( "AttachToObject", "[libopenshot][keyframe]" ) auto trackedDataJson = trackedData->JsonValue(); // Get and cast the trakcedObject - auto trackedObject_base = t.GetTrackedObject("None"); - std::shared_ptr trackedObject = std::static_pointer_cast(trackedObject_base); + auto trackedObject_base = t.GetTrackedObject(""); + auto trackedObject = std::make_shared(); + trackedObject = std::dynamic_pointer_cast(trackedObject_base); CHECK(trackedObject == trackedData); // Set trackedObject Json Value @@ -705,7 +706,8 @@ TEST_CASE( "AttachToObject", "[libopenshot][keyframe]" ) childClip.Open(); childClip.AttachToObject(tracked_id); - std::shared_ptr trackedTest = std::static_pointer_cast(childClip.GetAttachedObject()); + auto trackedTest = std::make_shared(); + trackedTest = std::dynamic_pointer_cast(childClip.GetAttachedObject()); CHECK(trackedData->scale_x.GetValue(1) == trackedTest->scale_x.GetValue(1)); @@ -719,7 +721,7 @@ TEST_CASE( "GetBoxValues", "[libopenshot][keyframe]" ) TrackedObjectBBox trackedDataObject; trackedDataObject.AddBox(1, 10.0, 10.0, 20.0, 20.0, 30.0); - std::shared_ptr trackedData = std::make_shared(trackedDataObject); + auto trackedData = std::make_shared(trackedDataObject); auto boxValues = trackedData->GetBoxValues(1); diff --git a/tests/KeyFrame_Tests.cpp b/tests/KeyFrame_Tests.cpp index 29c774be6..33d0f7ae4 100644 --- a/tests/KeyFrame_Tests.cpp +++ b/tests/KeyFrame_Tests.cpp @@ -670,7 +670,7 @@ TEST(Attach_test){ auto trackedDataJson = trackedData->JsonValue(); // Get and cast the trakcedObject - auto trackedObject_base = t.GetTrackedObject("None"); + auto trackedObject_base = t.GetTrackedObject(""); std::shared_ptr trackedObject = std::static_pointer_cast(trackedObject_base); CHECK_EQUAL(trackedData, trackedObject); From ed72fc82282cff4fb2aa5b57d277f34b79d73d0b Mon Sep 17 00:00:00 2001 From: Brenno Date: Mon, 12 Apr 2021 22:20:44 -0300 Subject: [PATCH 64/84] Added option to hide bounding box text in ObjectDetector effect. Fixed tab formatting --- src/effects/ObjectDetection.cpp | 862 ++++++++++++++++---------------- src/effects/ObjectDetection.h | 46 +- 2 files changed, 460 insertions(+), 448 deletions(-) diff --git a/src/effects/ObjectDetection.cpp b/src/effects/ObjectDetection.cpp index 9c947e911..a85d807aa 100644 --- a/src/effects/ObjectDetection.cpp +++ b/src/effects/ObjectDetection.cpp @@ -39,495 +39,505 @@ using namespace openshot; /// Blank constructor, useful when using Json to load the effect properties ObjectDetection::ObjectDetection(std::string clipObDetectDataPath) { - // Init effect properties - init_effect_details(); + // Init effect properties + init_effect_details(); - // Tries to load the tracker data from protobuf - LoadObjDetectdData(clipObDetectDataPath); + // Tries to load the tracker data from protobuf + LoadObjDetectdData(clipObDetectDataPath); - // Initialize the selected object index as the first object index - selectedObjectIndex = trackedObjects.begin()->first; + // Initialize the selected object index as the first object index + selectedObjectIndex = trackedObjects.begin()->first; } // Default constructor ObjectDetection::ObjectDetection() { - // Init effect properties - init_effect_details(); + // Init effect properties + init_effect_details(); - // Initialize the selected object index as the first object index - selectedObjectIndex = trackedObjects.begin()->first; + // Initialize the selected object index as the first object index + selectedObjectIndex = trackedObjects.begin()->first; } // Init effect settings void ObjectDetection::init_effect_details() { - /// Initialize the values of the EffectInfo struct. - InitEffectInfo(); - - /// Set the effect info - info.class_name = "Object Detector"; - info.name = "Object Detector"; - info.description = "Detect objects through the video."; - info.has_audio = false; - info.has_video = true; - info.has_tracked_object = true; + /// Initialize the values of the EffectInfo struct. + InitEffectInfo(); + + /// Set the effect info + info.class_name = "Object Detector"; + info.name = "Object Detector"; + info.description = "Detect objects through the video."; + info.has_audio = false; + info.has_video = true; + info.has_tracked_object = true; } // This method is required for all derived classes of EffectBase, and returns a // modified openshot::Frame object std::shared_ptr ObjectDetection::GetFrame(std::shared_ptr frame, int64_t frame_number) { - // Get the frame's image - cv::Mat cv_image = frame->GetImageCV(); - - // Check if frame isn't NULL - if(cv_image.empty()){ - return frame; - } - - // Check if track data exists for the requested frame - if (detectionsData.find(frame_number) != detectionsData.end()) { - float fw = cv_image.size().width; - float fh = cv_image.size().height; - - DetectionData detections = detectionsData[frame_number]; - for(int i = 0; i 0 && - std::find(display_classes.begin(), display_classes.end(), classNames[detections.classIds.at(i)]) == display_classes.end()){ - continue; - } - - // Get the object id - int objectId = detections.objectIds.at(i); - - // Search for the object in the trackedObjects map - auto trackedObject_it = trackedObjects.find(objectId); - - // Cast the object as TrackedObjectBBox - std::shared_ptr trackedObject = std::static_pointer_cast(trackedObject_it->second); - - // Check if the tracked object has data for this frame - if (trackedObject->Contains(frame_number) && - trackedObject->visible.GetValue(frame_number) == 1) - { - // Get the bounding-box of given frame - BBox trackedBox = trackedObject->GetBox(frame_number); - - std::vector stroke_rgba = trackedObject->stroke.GetColorRGBA(frame_number); - int stroke_width = trackedObject->stroke_width.GetValue(frame_number); - float stroke_alpha = trackedObject->stroke_alpha.GetValue(frame_number); - std::vector bg_rgba = trackedObject->background.GetColorRGBA(frame_number); - float bg_alpha = trackedObject->background_alpha.GetValue(frame_number); - - // Create a rotated rectangle object that holds the bounding box - // cv::RotatedRect box ( cv::Point2f( (int)(trackedBox.cx*fw), (int)(trackedBox.cy*fh) ), - // cv::Size2f( (int)(trackedBox.width*fw), (int)(trackedBox.height*fh) ), - // (int) (trackedBox.angle) ); - - // DrawRectangleRGBA(cv_image, box, bg_rgba, bg_alpha, 1, true); - // DrawRectangleRGBA(cv_image, box, stroke_rgba, stroke_alpha, stroke_width, false); - - cv::Rect2d box( - (int)( (trackedBox.cx-trackedBox.width/2)*fw), - (int)( (trackedBox.cy-trackedBox.height/2)*fh), - (int)( trackedBox.width*fw), - (int)( trackedBox.height*fh) - ); - drawPred(detections.classIds.at(i), detections.confidences.at(i), - box, cv_image, detections.objectIds.at(i), bg_rgba, bg_alpha, 1, true); - drawPred(detections.classIds.at(i), detections.confidences.at(i), - box, cv_image, detections.objectIds.at(i), stroke_rgba, stroke_alpha, stroke_width, false); - } - } - } - - // Update Qt image with new Opencv frame - frame->SetImageCV(cv_image); - - return frame; + // Get the frame's image + cv::Mat cv_image = frame->GetImageCV(); + + // Check if frame isn't NULL + if(cv_image.empty()){ + return frame; + } + + // Check if track data exists for the requested frame + if (detectionsData.find(frame_number) != detectionsData.end()) { + float fw = cv_image.size().width; + float fh = cv_image.size().height; + + DetectionData detections = detectionsData[frame_number]; + for(int i = 0; i 0 && + std::find(display_classes.begin(), display_classes.end(), classNames[detections.classIds.at(i)]) == display_classes.end()){ + continue; + } + + // Get the object id + int objectId = detections.objectIds.at(i); + + // Search for the object in the trackedObjects map + auto trackedObject_it = trackedObjects.find(objectId); + + // Cast the object as TrackedObjectBBox + std::shared_ptr trackedObject = std::static_pointer_cast(trackedObject_it->second); + + // Check if the tracked object has data for this frame + if (trackedObject->Contains(frame_number) && + trackedObject->visible.GetValue(frame_number) == 1) + { + // Get the bounding-box of given frame + BBox trackedBox = trackedObject->GetBox(frame_number); + bool draw_text = !display_box_text.GetValue(frame_number); + std::vector stroke_rgba = trackedObject->stroke.GetColorRGBA(frame_number); + int stroke_width = trackedObject->stroke_width.GetValue(frame_number); + float stroke_alpha = trackedObject->stroke_alpha.GetValue(frame_number); + std::vector bg_rgba = trackedObject->background.GetColorRGBA(frame_number); + float bg_alpha = trackedObject->background_alpha.GetValue(frame_number); + + // Create a rotated rectangle object that holds the bounding box + // cv::RotatedRect box ( cv::Point2f( (int)(trackedBox.cx*fw), (int)(trackedBox.cy*fh) ), + // cv::Size2f( (int)(trackedBox.width*fw), (int)(trackedBox.height*fh) ), + // (int) (trackedBox.angle) ); + + // DrawRectangleRGBA(cv_image, box, bg_rgba, bg_alpha, 1, true); + // DrawRectangleRGBA(cv_image, box, stroke_rgba, stroke_alpha, stroke_width, false); + + cv::Rect2d box( + (int)( (trackedBox.cx-trackedBox.width/2)*fw), + (int)( (trackedBox.cy-trackedBox.height/2)*fh), + (int)( trackedBox.width*fw), + (int)( trackedBox.height*fh) + ); + drawPred(detections.classIds.at(i), detections.confidences.at(i), + box, cv_image, detections.objectIds.at(i), bg_rgba, bg_alpha, 1, true, draw_text); + drawPred(detections.classIds.at(i), detections.confidences.at(i), + box, cv_image, detections.objectIds.at(i), stroke_rgba, stroke_alpha, stroke_width, false, draw_text); + } + } + } + + // Update Qt image with new Opencv frame + frame->SetImageCV(cv_image); + + return frame; } void ObjectDetection::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); - } + 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); + } } void ObjectDetection::drawPred(int classId, float conf, cv::Rect2d box, cv::Mat& frame, int objectNumber, std::vector color, - float alpha, int thickness, bool is_background) + float alpha, int thickness, bool is_background, bool display_text) { - if(is_background){ - cv::Mat overlayFrame; - frame.copyTo(overlayFrame); - - //Draw a rectangle displaying the bounding box - cv::rectangle(overlayFrame, box, cv::Scalar(color[2],color[1],color[0]), cv::FILLED); - - // add opacity - cv::addWeighted(overlayFrame, 1-alpha, frame, alpha, 0, frame); - } - else{ - cv::Mat overlayFrame; - frame.copyTo(overlayFrame); - - //Draw a rectangle displaying the bounding box - cv::rectangle(overlayFrame, box, cv::Scalar(color[2],color[1],color[0]), thickness); - - //Get the label for the class name and its confidence - std::string label = cv::format("%.2f", conf); - if (!classNames.empty()) - { - CV_Assert(classId < (int)classNames.size()); - label = classNames[classId] + ":" + label; - } - - //Display the label at the top of the bounding box - int baseLine; - cv::Size labelSize = cv::getTextSize(label, cv::FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine); - - double left = box.x; - double top = std::max((int)box.y, labelSize.height); - - cv::rectangle(overlayFrame, cv::Point(left, top - round(1.025*labelSize.height)), cv::Point(left + round(1.025*labelSize.width), top + baseLine), - cv::Scalar(color[2],color[1],color[0]), cv::FILLED); - putText(overlayFrame, label, cv::Point(left+1, top), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0,0,0),1); - - // add opacity - cv::addWeighted(overlayFrame, 1-alpha, frame, alpha, 0, frame); - } + if(is_background){ + cv::Mat overlayFrame; + frame.copyTo(overlayFrame); + + //Draw a rectangle displaying the bounding box + cv::rectangle(overlayFrame, box, cv::Scalar(color[2],color[1],color[0]), cv::FILLED); + + // add opacity + cv::addWeighted(overlayFrame, 1-alpha, frame, alpha, 0, frame); + } + else{ + cv::Mat overlayFrame; + frame.copyTo(overlayFrame); + + //Draw a rectangle displaying the bounding box + cv::rectangle(overlayFrame, box, cv::Scalar(color[2],color[1],color[0]), thickness); + + if(display_text){ + //Get the label for the class name and its confidence + std::string label = cv::format("%.2f", conf); + if (!classNames.empty()) + { + CV_Assert(classId < (int)classNames.size()); + label = classNames[classId] + ":" + label; + } + + //Display the label at the top of the bounding box + int baseLine; + cv::Size labelSize = cv::getTextSize(label, cv::FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine); + + double left = box.x; + double top = std::max((int)box.y, labelSize.height); + + cv::rectangle(overlayFrame, cv::Point(left, top - round(1.025*labelSize.height)), cv::Point(left + round(1.025*labelSize.width), top + baseLine), + cv::Scalar(color[2],color[1],color[0]), cv::FILLED); + putText(overlayFrame, label, cv::Point(left+1, top), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0,0,0),1); + } + // add opacity + cv::addWeighted(overlayFrame, 1-alpha, frame, alpha, 0, frame); + } } // Load protobuf data file bool ObjectDetection::LoadObjDetectdData(std::string inputFilePath){ - // Create tracker message - pb_objdetect::ObjDetect objMessage; - - - // Read the existing tracker message. - fstream input(inputFilePath, ios::in | ios::binary); - if (!objMessage.ParseFromIstream(&input)) { - cerr << "Failed to parse protobuf message." << endl; - return false; - } - - - // Make sure classNames, detectionsData and trackedObjects are empty - classNames.clear(); - detectionsData.clear(); - trackedObjects.clear(); - - // Seed to generate same random numbers - std::srand(1); - // Get all classes names and assign a color to them - for(int i = 0; i < objMessage.classnames_size(); i++) - { - classNames.push_back(objMessage.classnames(i)); - classesColor.push_back(cv::Scalar(std::rand()%205 + 50, std::rand()%205 + 50, std::rand()%205 + 50)); - } - - // Iterate over all frames of the saved message - for (size_t i = 0; i < objMessage.frame_size(); i++) - { - // Create protobuf message reader - const pb_objdetect::Frame& pbFrameData = objMessage.frame(i); - - // Get frame Id - size_t id = pbFrameData.id(); - - // Load bounding box data - const google::protobuf::RepeatedPtrField &pBox = pbFrameData.bounding_box(); - - // Construct data vectors related to detections in the current frame - std::vector classIds; - std::vector confidences; - std::vector> boxes; - std::vector objectIds; - - // Iterate through the detected objects - for(int i = 0; i < pbFrameData.bounding_box_size(); i++) - { - // Get bounding box coordinates - float x = pBox.Get(i).x(); - float y = pBox.Get(i).y(); - float w = pBox.Get(i).w(); - float h = pBox.Get(i).h(); - // Get class Id (which will be assign to a class name) - int classId = pBox.Get(i).classid(); - // Get prediction confidence - float confidence = pBox.Get(i).confidence(); - - // Get the object Id - int objectId = pBox.Get(i).objectid(); - - // Search for the object id on trackedObjects map - auto trackedObject = trackedObjects.find(objectId); - // Check if object already exists on the map - if (trackedObject != trackedObjects.end()) - { - // Add a new BBox to it - trackedObject->second->AddBox(id, x+(w/2), y+(h/2), w, h, 0.0); - } - else - { - // There is no tracked object with that id, so insert a new one - TrackedObjectBBox trackedObj((int)classesColor[classId](0), (int)classesColor[classId](1), (int)classesColor[classId](2), (int)0); - trackedObj.AddBox(id, x+(w/2), y+(h/2), w, h, 0.0); - std::shared_ptr trackedObjPtr = std::make_shared(trackedObj); - trackedObjects.insert({objectId, trackedObjPtr}); - } - - // Create OpenCV rectangle with the bouding box info - cv::Rect_ box(x, y, w, h); - - // Push back data into vectors - boxes.push_back(box); - classIds.push_back(classId); - confidences.push_back(confidence); - objectIds.push_back(objectId); - } - - // Assign data to object detector map - detectionsData[id] = DetectionData(classIds, confidences, boxes, id, objectIds); - } - - // Delete all global objects allocated by libprotobuf. - google::protobuf::ShutdownProtobufLibrary(); - - return true; + // Create tracker message + pb_objdetect::ObjDetect objMessage; + + + // Read the existing tracker message. + fstream input(inputFilePath, ios::in | ios::binary); + if (!objMessage.ParseFromIstream(&input)) { + cerr << "Failed to parse protobuf message." << endl; + return false; + } + + + // Make sure classNames, detectionsData and trackedObjects are empty + classNames.clear(); + detectionsData.clear(); + trackedObjects.clear(); + + // Seed to generate same random numbers + std::srand(1); + // Get all classes names and assign a color to them + for(int i = 0; i < objMessage.classnames_size(); i++) + { + classNames.push_back(objMessage.classnames(i)); + classesColor.push_back(cv::Scalar(std::rand()%205 + 50, std::rand()%205 + 50, std::rand()%205 + 50)); + } + + // Iterate over all frames of the saved message + for (size_t i = 0; i < objMessage.frame_size(); i++) + { + // Create protobuf message reader + const pb_objdetect::Frame& pbFrameData = objMessage.frame(i); + + // Get frame Id + size_t id = pbFrameData.id(); + + // Load bounding box data + const google::protobuf::RepeatedPtrField &pBox = pbFrameData.bounding_box(); + + // Construct data vectors related to detections in the current frame + std::vector classIds; + std::vector confidences; + std::vector> boxes; + std::vector objectIds; + + // Iterate through the detected objects + for(int i = 0; i < pbFrameData.bounding_box_size(); i++) + { + // Get bounding box coordinates + float x = pBox.Get(i).x(); + float y = pBox.Get(i).y(); + float w = pBox.Get(i).w(); + float h = pBox.Get(i).h(); + // Get class Id (which will be assign to a class name) + int classId = pBox.Get(i).classid(); + // Get prediction confidence + float confidence = pBox.Get(i).confidence(); + + // Get the object Id + int objectId = pBox.Get(i).objectid(); + + // Search for the object id on trackedObjects map + auto trackedObject = trackedObjects.find(objectId); + // Check if object already exists on the map + if (trackedObject != trackedObjects.end()) + { + // Add a new BBox to it + trackedObject->second->AddBox(id, x+(w/2), y+(h/2), w, h, 0.0); + } + else + { + // There is no tracked object with that id, so insert a new one + TrackedObjectBBox trackedObj((int)classesColor[classId](0), (int)classesColor[classId](1), (int)classesColor[classId](2), (int)0); + trackedObj.AddBox(id, x+(w/2), y+(h/2), w, h, 0.0); + std::shared_ptr trackedObjPtr = std::make_shared(trackedObj); + trackedObjects.insert({objectId, trackedObjPtr}); + } + + // Create OpenCV rectangle with the bouding box info + cv::Rect_ box(x, y, w, h); + + // Push back data into vectors + boxes.push_back(box); + classIds.push_back(classId); + confidences.push_back(confidence); + objectIds.push_back(objectId); + } + + // Assign data to object detector map + detectionsData[id] = DetectionData(classIds, confidences, boxes, id, objectIds); + } + + // Delete all global objects allocated by libprotobuf. + google::protobuf::ShutdownProtobufLibrary(); + + return true; } // Get tracker info for the desired frame DetectionData ObjectDetection::GetTrackedData(size_t frameId){ - // Check if the tracker info for the requested frame exists - if ( detectionsData.find(frameId) == detectionsData.end() ) { - return DetectionData(); - } else { - return detectionsData[frameId]; - } + // Check if the tracker info for the requested frame exists + if ( detectionsData.find(frameId) == detectionsData.end() ) { + return DetectionData(); + } else { + return detectionsData[frameId]; + } } // Get the indexes and IDs of all visible objects in the given frame std::string ObjectDetection::GetVisibleObjects(int64_t frame_number) const{ - - // Initialize the JSON objects - Json::Value root; - root["visible_objects_index"] = Json::Value(Json::arrayValue); - root["visible_objects_id"] = Json::Value(Json::arrayValue); - - // Check if track data exists for the requested frame - if (detectionsData.find(frame_number) == detectionsData.end()){ - return root.toStyledString(); - } - DetectionData detections = detectionsData.at(frame_number); - - // Iterate through the tracked objects - for(int i = 0; i 0 && - std::find(display_classes.begin(), display_classes.end(), classNames[detections.classIds.at(i)]) == display_classes.end()){ - continue; - } - - int objectId = detections.objectIds.at(i); - // Search for the object in the trackedObjects map - auto trackedObject = trackedObjects.find(objectId); - - // Get the tracked object JSON properties for this frame - Json::Value trackedObjectJSON = trackedObject->second->PropertiesJSON(frame_number); - - if (trackedObjectJSON["visible"]["value"].asBool() && - trackedObject->second->ExactlyContains(frame_number)){ - // Save the object's index and ID if it's visible in this frame - root["visible_objects_index"].append(trackedObject->first); - root["visible_objects_id"].append(trackedObject->second->Id()); - } - } - - return root.toStyledString(); + + // Initialize the JSON objects + Json::Value root; + root["visible_objects_index"] = Json::Value(Json::arrayValue); + root["visible_objects_id"] = Json::Value(Json::arrayValue); + + // Check if track data exists for the requested frame + if (detectionsData.find(frame_number) == detectionsData.end()){ + return root.toStyledString(); + } + DetectionData detections = detectionsData.at(frame_number); + + // Iterate through the tracked objects + for(int i = 0; i 0 && + std::find(display_classes.begin(), display_classes.end(), classNames[detections.classIds.at(i)]) == display_classes.end()){ + continue; + } + + int objectId = detections.objectIds.at(i); + // Search for the object in the trackedObjects map + auto trackedObject = trackedObjects.find(objectId); + + // Get the tracked object JSON properties for this frame + Json::Value trackedObjectJSON = trackedObject->second->PropertiesJSON(frame_number); + + if (trackedObjectJSON["visible"]["value"].asBool() && + trackedObject->second->ExactlyContains(frame_number)){ + // Save the object's index and ID if it's visible in this frame + root["visible_objects_index"].append(trackedObject->first); + root["visible_objects_id"].append(trackedObject->second->Id()); + } + } + + return root.toStyledString(); } // Generate JSON string of this object std::string ObjectDetection::Json() const { - // Return formatted string - return JsonValue().toStyledString(); + // Return formatted string + return JsonValue().toStyledString(); } // Generate Json::Value for this object Json::Value ObjectDetection::JsonValue() const { - // Create root json object - Json::Value root = EffectBase::JsonValue(); // get parent properties - root["type"] = info.class_name; - root["protobuf_data_path"] = protobuf_data_path; - root["selected_object_index"] = selectedObjectIndex; - root["confidence_threshold"] = confidence_threshold; - - // Add tracked object's IDs to root - root["objects_id"] = Json::Value(Json::arrayValue); - for (auto const& trackedObject : trackedObjects){ - Json::Value trackedObjectJSON = trackedObject.second->JsonValue(); - root["objects_id"].append(trackedObject.second->Id()); - } - - // Add the selected object Json to root - if(trackedObjects.count(selectedObjectIndex) != 0){ - auto selectedObject = trackedObjects.at(selectedObjectIndex); - if (selectedObject){ - Json::Value selectedObjectJSON = selectedObject->JsonValue(); - for (auto const& key : selectedObjectJSON.getMemberNames()) - root[key] = selectedObjectJSON[key]; - } - } - - // return JsonValue - return root; + // Create root json object + Json::Value root = EffectBase::JsonValue(); // get parent properties + root["type"] = info.class_name; + root["protobuf_data_path"] = protobuf_data_path; + root["selected_object_index"] = selectedObjectIndex; + root["confidence_threshold"] = confidence_threshold; + root["display_box_text"] = display_box_text.JsonValue(); + + // Add tracked object's IDs to root + root["objects_id"] = Json::Value(Json::arrayValue); + for (auto const& trackedObject : trackedObjects){ + Json::Value trackedObjectJSON = trackedObject.second->JsonValue(); + root["objects_id"].append(trackedObject.second->Id()); + } + + // Add the selected object Json to root + if(trackedObjects.count(selectedObjectIndex) != 0){ + auto selectedObject = trackedObjects.at(selectedObjectIndex); + if (selectedObject){ + Json::Value selectedObjectJSON = selectedObject->JsonValue(); + for (auto const& key : selectedObjectJSON.getMemberNames()) + root[key] = selectedObjectJSON[key]; + } + } + + // return JsonValue + return root; } // Load JSON string into this object void ObjectDetection::SetJson(const std::string value) { - // Parse JSON string into JSON objects - try - { - std::cout<<"entrou no objectDetection SetJson \n"<SetJsonValue(trackedObjectJSON); - } - } - - // Set the selected object's properties - if(trackedObjects.count(selectedObjectIndex) != 0){ - auto selectedObject = trackedObjects.at(selectedObjectIndex); - if (selectedObject) - selectedObject->SetJsonValue(root); - } + std::cout<<"entrou no objectDetection SetJasonValue \n"<SetJsonValue(trackedObjectJSON); + } + } + + // Set the selected object's properties + if(trackedObjects.count(selectedObjectIndex) != 0){ + auto selectedObject = trackedObjects.at(selectedObjectIndex); + if (selectedObject) + selectedObject->SetJsonValue(root); + } } // Get all properties for a specific frame std::string ObjectDetection::PropertiesJSON(int64_t requested_frame) const { - // Generate JSON properties list - Json::Value root; - - // Add the selected object Json to root - if(trackedObjects.count(selectedObjectIndex) != 0){ - auto selectedObject = trackedObjects.at(selectedObjectIndex); - if (selectedObject) - root = selectedObject->PropertiesJSON(requested_frame); - } - - root["selected_object_index"] = add_property_json("Selected Object", selectedObjectIndex, "int", "", NULL, 0, 200, false, requested_frame); - root["id"] = add_property_json("ID", 0.0, "string", Id(), NULL, -1, -1, true, requested_frame); - root["position"] = add_property_json("Position", Position(), "float", "", NULL, 0, 1000 * 60 * 30, false, requested_frame); - root["layer"] = add_property_json("Track", Layer(), "int", "", NULL, 0, 20, false, requested_frame); - root["start"] = add_property_json("Start", Start(), "float", "", NULL, 0, 1000 * 60 * 30, false, requested_frame); - root["end"] = add_property_json("End", End(), "float", "", NULL, 0, 1000 * 60 * 30, false, requested_frame); - root["duration"] = add_property_json("Duration", Duration(), "float", "", NULL, 0, 1000 * 60 * 30, true, requested_frame); - root["confidence_threshold"] = add_property_json("Confidence Theshold", confidence_threshold, "float", "", NULL, 0, 1, false, requested_frame); - root["class_filter"] = add_property_json("Class Filter", 0.0, "string", class_filter, NULL, -1, -1, false, requested_frame); - // Return formatted string - return root.toStyledString(); + // Generate JSON properties list + Json::Value root; + + // Add the selected object Json to root + if(trackedObjects.count(selectedObjectIndex) != 0){ + auto selectedObject = trackedObjects.at(selectedObjectIndex); + if (selectedObject) + root = selectedObject->PropertiesJSON(requested_frame); + } + + root["selected_object_index"] = add_property_json("Selected Object", selectedObjectIndex, "int", "", NULL, 0, 200, false, requested_frame); + root["id"] = add_property_json("ID", 0.0, "string", Id(), NULL, -1, -1, true, requested_frame); + root["position"] = add_property_json("Position", Position(), "float", "", NULL, 0, 1000 * 60 * 30, false, requested_frame); + root["layer"] = add_property_json("Track", Layer(), "int", "", NULL, 0, 20, false, requested_frame); + root["start"] = add_property_json("Start", Start(), "float", "", NULL, 0, 1000 * 60 * 30, false, requested_frame); + root["end"] = add_property_json("End", End(), "float", "", NULL, 0, 1000 * 60 * 30, false, requested_frame); + root["duration"] = add_property_json("Duration", Duration(), "float", "", NULL, 0, 1000 * 60 * 30, true, requested_frame); + root["confidence_threshold"] = add_property_json("Confidence Theshold", confidence_threshold, "float", "", NULL, 0, 1, false, requested_frame); + root["class_filter"] = add_property_json("Class Filter", 0.0, "string", class_filter, NULL, -1, -1, false, requested_frame); + + root["display_box_text"] = add_property_json("Draw Box Text", display_box_text.GetValue(requested_frame), "int", "", &display_box_text, 0, 1.0, false, requested_frame); + root["display_box_text"]["choices"].append(add_property_choice_json("Off", 1, display_box_text.GetValue(requested_frame))); + root["display_box_text"]["choices"].append(add_property_choice_json("On", 0, display_box_text.GetValue(requested_frame))); + + // Return formatted string + return root.toStyledString(); } diff --git a/src/effects/ObjectDetection.h b/src/effects/ObjectDetection.h index fee9382bb..bf7782301 100644 --- a/src/effects/ObjectDetection.h +++ b/src/effects/ObjectDetection.h @@ -46,23 +46,23 @@ struct DetectionData{ DetectionData(){} DetectionData( - std::vector _classIds, - std::vector _confidences, - std::vector> _boxes, - size_t _frameId, - std::vector _objectIds) - { + std::vector _classIds, + std::vector _confidences, + std::vector> _boxes, + size_t _frameId, + std::vector _objectIds) + { classIds = _classIds; confidences = _confidences; boxes = _boxes; frameId = _frameId; - objectIds = _objectIds; + objectIds = _objectIds; } size_t frameId; std::vector classIds; std::vector confidences; std::vector> boxes; - std::vector objectIds; + std::vector objectIds; }; namespace openshot @@ -78,20 +78,22 @@ namespace openshot std::vector classNames; std::vector classesColor; - - /// Minimum confidence value to display the detected objects - float confidence_threshold = 0.5; - /// Contain the user selected classes for visualization - std::vector display_classes; - std::string class_filter; - - /// Init effect settings - void init_effect_details(); - /// Draw bounding box with class and score text - void drawPred(int classId, float conf, cv::Rect2d box, cv::Mat& frame, int objectNumber, std::vector color, float alpha, - int thickness, bool is_background); - /// Draw rotated rectangle with alpha channel - void DrawRectangleRGBA(cv::Mat &frame_image, cv::RotatedRect box, std::vector color, float alpha, int thickness, bool is_background); + + /// Draw class name and confidence score on top of the bounding box + Keyframe display_box_text; + /// Minimum confidence value to display the detected objects + float confidence_threshold = 0.5; + /// Contain the user selected classes for visualization + std::vector display_classes; + std::string class_filter; + + /// Init effect settings + void init_effect_details(); + /// Draw bounding box with class and score text + void drawPred(int classId, float conf, cv::Rect2d box, cv::Mat& frame, int objectNumber, std::vector color, float alpha, + int thickness, bool is_background, bool draw_text); + /// Draw rotated rectangle with alpha channel + void DrawRectangleRGBA(cv::Mat &frame_image, cv::RotatedRect box, std::vector color, float alpha, int thickness, bool is_background); public: From 77aa418353440856de2bade89f48c9ef083a2b70 Mon Sep 17 00:00:00 2001 From: Brenno Date: Thu, 15 Apr 2021 21:52:02 -0300 Subject: [PATCH 65/84] Fixed FPS ToInt() conversion and changed initial frame number to 1 --- src/CVObjectDetection.cpp | 6 +++--- src/CVStabilization.cpp | 10 +++++----- src/CVTracker.cpp | 14 +++++++------- tests/CVObjectDetection.cpp | 4 ++-- tests/CVStabilizer.cpp | 4 ++-- tests/CVTracker.cpp | 10 +++++----- 6 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/CVObjectDetection.cpp b/src/CVObjectDetection.cpp index 53533cbff..3fddb93f7 100644 --- a/src/CVObjectDetection.cpp +++ b/src/CVObjectDetection.cpp @@ -78,10 +78,10 @@ void CVObjectDetection::detectObjectsClip(openshot::Clip &video, size_t _start, setProcessingDevice(); size_t frame_number; - if(!process_interval || end == 0 || end-start == 0){ + if(!process_interval || end <= 1 || end-start == 0){ // Get total number of frames in video - start = video.Start() * video.Reader()->info.fps.ToInt(); - end = video.End() * video.Reader()->info.fps.ToInt(); + start = (int)(video.Start() * video.Reader()->info.fps.ToFloat()) + 1; + end = (int)(video.End() * video.Reader()->info.fps.ToFloat()) + 1; } for (frame_number = start; frame_number <= end; frame_number++) diff --git a/src/CVStabilization.cpp b/src/CVStabilization.cpp index 3076ada8b..75eff5363 100644 --- a/src/CVStabilization.cpp +++ b/src/CVStabilization.cpp @@ -39,8 +39,8 @@ using google::protobuf::util::TimeUtil; CVStabilization::CVStabilization(std::string processInfoJson, ProcessingController &processingController) : processingController(&processingController){ SetJson(processInfoJson); - start = 0; - end = 0; + start = 1; + end = 1; } // Process clip and store necessary stabilization data @@ -60,10 +60,10 @@ void CVStabilization::stabilizeClip(openshot::Clip& video, size_t _start, size_t cv::Size readerDims(video.Reader()->info.width, video.Reader()->info.height); size_t frame_number; - if(!process_interval || end == 0 || end-start == 0){ + if(!process_interval || end <= 1 || end-start == 0){ // Get total number of frames in video - start = video.Start() * video.Reader()->info.fps.ToInt(); - end = video.End() * video.Reader()->info.fps.ToInt(); + start = (int)(video.Start() * video.Reader()->info.fps.ToFloat()) + 1; + end = (int)(video.End() * video.Reader()->info.fps.ToFloat()) + 1; } // Extract and track opticalflow features for each frame diff --git a/src/CVTracker.cpp b/src/CVTracker.cpp index ee29894ae..f300c2d73 100644 --- a/src/CVTracker.cpp +++ b/src/CVTracker.cpp @@ -40,8 +40,8 @@ using google::protobuf::util::TimeUtil; CVTracker::CVTracker(std::string processInfoJson, ProcessingController &processingController) : processingController(&processingController), json_interval(false){ SetJson(processInfoJson); - start = 0; - end = 0; + start = 1; + end = 1; } // Set desirable tracker method @@ -73,15 +73,15 @@ void CVTracker::trackClip(openshot::Clip& video, size_t _start, size_t _end, boo if(!json_interval){ start = _start; end = _end; - if(!process_interval || end <= 0 || end-start == 0){ + if(!process_interval || end <= 1 || end-start == 0){ // Get total number of frames in video - start = video.Start() * video.Reader()->info.fps.ToInt(); - end = video.End() * video.Reader()->info.fps.ToInt(); + start = (int)(video.Start() * video.Reader()->info.fps.ToFloat()) + 1; + end = (int)(video.End() * video.Reader()->info.fps.ToFloat()) + 1; } } else{ - start = start + video.Start() * video.Reader()->info.fps.ToInt(); - end = video.End() * video.Reader()->info.fps.ToInt(); + start = (int)(start + video.Start() * video.Reader()->info.fps.ToFloat()) + 1; + end = (int)(video.End() * video.Reader()->info.fps.ToFloat()) + 1; } if(error){ diff --git a/tests/CVObjectDetection.cpp b/tests/CVObjectDetection.cpp index ce948074d..688581c57 100644 --- a/tests/CVObjectDetection.cpp +++ b/tests/CVObjectDetection.cpp @@ -62,7 +62,7 @@ TEST_CASE( "DetectObject_Video", "[libopenshot][opencv][objectdetection]" ) //TODO remove hardcoded path CVObjectDetection objectDetector(effectInfo, processingController); - objectDetector.detectObjectsClip(c1, 0, 20, true); + objectDetector.detectObjectsClip(c1, 1, 20, true); CVDetectionData dd = objectDetector.GetDetectionData(20); @@ -97,7 +97,7 @@ TEST_CASE( "SaveLoad_Protobuf", "[libopenshot][opencv][objectdetection]" ) //TODO remove hardcoded path CVObjectDetection objectDetector_1(effectInfo ,processingController); - objectDetector_1.detectObjectsClip(c1, 0, 20, true); + objectDetector_1.detectObjectsClip(c1, 1, 20, true); CVDetectionData dd_1 = objectDetector_1.GetDetectionData(20); diff --git a/tests/CVStabilizer.cpp b/tests/CVStabilizer.cpp index ed3e5403c..61b9f6266 100644 --- a/tests/CVStabilizer.cpp +++ b/tests/CVStabilizer.cpp @@ -62,7 +62,7 @@ TEST_CASE( "Stabilize_Video", "[libopenshot][opencv][stabilizer]" ) CVStabilization stabilizer(json_data, stabilizer_pc); // Stabilize clip for frames 0-21 - stabilizer.stabilizeClip(c1, 0, 21, true); + stabilizer.stabilizeClip(c1, 1, 21, true); // Get stabilized data TransformParam tp = stabilizer.GetTransformParamData(20); @@ -106,7 +106,7 @@ TEST_CASE( "SaveLoad_Protobuf", "[libopenshot][opencv][stabilizer]" ) CVStabilization stabilizer_1(json_data, stabilizer_pc); // Stabilize clip for frames 0-20 - stabilizer_1.stabilizeClip(c1, 0, 20+1, true); + stabilizer_1.stabilizeClip(c1, 1, 20+1, true); // Get stabilized data TransformParam tp_1 = stabilizer_1.GetTransformParamData(20); diff --git a/tests/CVTracker.cpp b/tests/CVTracker.cpp index 9548fc380..2bc878889 100644 --- a/tests/CVTracker.cpp +++ b/tests/CVTracker.cpp @@ -56,14 +56,14 @@ TEST_CASE( "Track_Video", "[libopenshot][opencv][tracker]" ) { "protobuf_data_path": "kcf_tracker.data", "tracker-type": "KCF", - "region": {"x": 294, "y": 102, "width": 180, "height": 166, "first-frame": 0} + "region": {"x": 294, "y": 102, "width": 180, "height": 166, "first-frame": 1} } )proto"; // Create tracker CVTracker kcfTracker(json_data, tracker_pc); // Track clip for frames 0-20 - kcfTracker.trackClip(c1, 0, 20, true); + kcfTracker.trackClip(c1, 1, 20, true); // Get tracked data FrameData fd = kcfTracker.GetTrackedData(20); float x = fd.x1; @@ -94,7 +94,7 @@ TEST_CASE( "SaveLoad_Protobuf", "[libopenshot][opencv][tracker]" ) { "protobuf_data_path": "kcf_tracker.data", "tracker-type": "KCF", - "region": {"x": 294, "y": 102, "width": 180, "height": 166, "first-frame": 0} + "region": {"x": 294, "y": 102, "width": 180, "height": 166, "first-frame": 1} } )proto"; @@ -102,7 +102,7 @@ TEST_CASE( "SaveLoad_Protobuf", "[libopenshot][opencv][tracker]" ) CVTracker kcfTracker_1(json_data, tracker_pc); // Track clip for frames 0-20 - kcfTracker_1.trackClip(c1, 0, 20, true); + kcfTracker_1.trackClip(c1, 1, 20, true); // Get tracked data FrameData fd_1 = kcfTracker_1.GetTrackedData(20); @@ -119,7 +119,7 @@ TEST_CASE( "SaveLoad_Protobuf", "[libopenshot][opencv][tracker]" ) { "protobuf_data_path": "kcf_tracker.data", "tracker_type": "", - "region": {"x": -1, "y": -1, "width": -1, "height": -1, "first-frame": 0} + "region": {"x": -1, "y": -1, "width": -1, "height": -1, "first-frame": 1} } )proto"; // Create second tracker From 2c9d2f2a32609ee456ff20ea1d8016a8723f4e3c Mon Sep 17 00:00:00 2001 From: Brenno Date: Thu, 15 Apr 2021 22:05:35 -0300 Subject: [PATCH 66/84] OpenCV is again an optional dependency --- src/CMakeLists.txt | 2 +- src/Clip.cpp | 4 ++-- src/OpenShot.h | 2 +- src/Timeline.cpp | 2 ++ src/Timeline.h | 4 ++++ tests/KeyFrame.cpp | 6 +++++- tests/KeyFrame_Tests.cpp | 7 +++++-- 7 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ced0bd1a4..76022764b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -87,7 +87,6 @@ set(OPENSHOT_SOURCES Json.cpp KeyFrame.cpp TrackedObjectBase.cpp - TrackedObjectBBox.cpp OpenShotVersion.cpp ZmqLogger.cpp PlayerBase.cpp @@ -107,6 +106,7 @@ set(OPENSHOT_CV_SOURCES CVStabilization.cpp ClipProcessingJobs.cpp CVObjectDetection.cpp + TrackedObjectBBox.cpp effects/Stabilizer.cpp effects/Tracker.cpp effects/ObjectDetection.cpp diff --git a/src/Clip.cpp b/src/Clip.cpp index 0d4068cf7..4c0e9876a 100644 --- a/src/Clip.cpp +++ b/src/Clip.cpp @@ -40,7 +40,6 @@ #include "ChunkReader.h" #include "DummyReader.h" #include "Timeline.h" -#include "effects/Tracker.h" using namespace openshot; @@ -1158,6 +1157,7 @@ void Clip::AddEffect(EffectBase* effect) if (parentTimeline) effect->ParentTimeline(parentTimeline); + #ifdef USE_OPENCV // Add Tracked Object to Timeline if (effect->info.has_tracked_object){ @@ -1178,9 +1178,9 @@ void Clip::AddEffect(EffectBase* effect) // Add the Tracked Object to the timeline parentTimeline->AddTrackedObject(trackedObjectBBox); } - } } + #endif // Clear cache cache.Clear(); diff --git a/src/OpenShot.h b/src/OpenShot.h index 5903ae433..f6c80c42c 100644 --- a/src/OpenShot.h +++ b/src/OpenShot.h @@ -132,7 +132,6 @@ #include "TextReader.h" #endif #include "KeyFrame.h" -#include "TrackedObjectBBox.h" #include "PlayerBase.h" #include "Point.h" #include "Profiles.h" @@ -147,6 +146,7 @@ #include "CVStabilization.h" #include "CVTracker.h" #include "CVObjectDetection.h" + #include "TrackedObjectBBox.h" #endif #endif diff --git a/src/Timeline.cpp b/src/Timeline.cpp index 291944106..51c90840d 100644 --- a/src/Timeline.cpp +++ b/src/Timeline.cpp @@ -293,6 +293,7 @@ std::list Timeline::GetTrackedObjectsIds() const{ return trackedObjects_ids; } +#ifdef USE_OPENCV // Return the trackedObject's properties as a JSON string std::string Timeline::GetTrackedObjectValues(std::string id, int64_t frame_number) const { @@ -349,6 +350,7 @@ std::string Timeline::GetTrackedObjectValues(std::string id, int64_t frame_numbe return trackedObjectJson.toStyledString(); } +#endif // Add an openshot::Clip to the timeline void Timeline::AddClip(Clip* clip) diff --git a/src/Timeline.h b/src/Timeline.h index 236e1352a..630f93c84 100644 --- a/src/Timeline.h +++ b/src/Timeline.h @@ -48,7 +48,9 @@ #include "Fraction.h" #include "Frame.h" #include "KeyFrame.h" +#ifdef USE_OPENCV #include "TrackedObjectBBox.h" +#endif #include "TrackedObjectBase.h" @@ -254,7 +256,9 @@ namespace openshot { /// Return the ID's of the tracked objects as a list of strings std::list GetTrackedObjectsIds() const; /// Return the trackedObject's properties as a JSON string + #ifdef USE_OPENCV std::string GetTrackedObjectValues(std::string id, int64_t frame_number) const; + #endif /// @brief Add an openshot::Clip to the timeline /// @param clip Add an openshot::Clip to the timeline. A clip can contain any type of Reader. diff --git a/tests/KeyFrame.cpp b/tests/KeyFrame.cpp index a75e5a952..3b32a86a3 100644 --- a/tests/KeyFrame.cpp +++ b/tests/KeyFrame.cpp @@ -34,13 +34,15 @@ #include #include "KeyFrame.h" -#include "TrackedObjectBBox.h" #include "Exceptions.h" #include "Coordinate.h" #include "Fraction.h" #include "Clip.h" #include "Timeline.h" +#ifdef USE_OPENCV #include "effects/Tracker.h" +#include "TrackedObjectBBox.h" +#endif #include "Point.h" using namespace openshot; @@ -514,6 +516,7 @@ TEST_CASE( "Point_Vector_Constructor", "[libopenshot][keyframe]" ) CHECK(k1.GetValue(10) == Approx(30.0f).margin(0.0001)); } +#ifdef USE_OPENCV TEST_CASE( "TrackedObjectBBox init", "[libopenshot][keyframe]" ) { TrackedObjectBBox kfb(62,143,0,212); @@ -731,3 +734,4 @@ TEST_CASE( "GetBoxValues", "[libopenshot][keyframe]" ) CHECK(boxValues["h"] == 20.0); CHECK(boxValues["ang"] == 30.0); } +#endif \ No newline at end of file diff --git a/tests/KeyFrame_Tests.cpp b/tests/KeyFrame_Tests.cpp index 33d0f7ae4..14864cadb 100644 --- a/tests/KeyFrame_Tests.cpp +++ b/tests/KeyFrame_Tests.cpp @@ -35,7 +35,9 @@ // Prevent name clashes with juce::UnitTest #define DONT_SET_USING_JUCE_NAMESPACE 1 #include "KeyFrame.h" +#ifdef USE_OPENCV #include "TrackedObjectBBox.h" +#endif #include "Exceptions.h" #include "Coordinate.h" #include "Fraction.h" @@ -519,7 +521,7 @@ TEST(Point_Vector_Constructor) }; // SUITE - +#ifdef USE_OPENCV TEST(TrackedObjectBBox_init_test) { TrackedObjectBBox kfb; @@ -704,4 +706,5 @@ TEST(GetBoxValues_test){ CHECK_EQUAL(20.0, boxValues["w"]); CHECK_EQUAL(20.0, boxValues["h"]); CHECK_EQUAL(30.0, boxValues["ang"]); -} \ No newline at end of file +} +#endif \ No newline at end of file From c6aae47d500c816d12d8eb621479524c5ffcd5fb Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Thu, 15 Apr 2021 19:53:57 -0400 Subject: [PATCH 67/84] Don't use OpenShot.h in ExampleHtml.cpp When `#include`-ing the whole mess, building the file was leading to what looked like out-of-memory errors. Replacing the monolithic header with just the necessary ones cleared it up. --- examples/ExampleHtml.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/ExampleHtml.cpp b/examples/ExampleHtml.cpp index 928a05fe8..852543ae0 100644 --- a/examples/ExampleHtml.cpp +++ b/examples/ExampleHtml.cpp @@ -35,7 +35,10 @@ #include #include -#include "OpenShot.h" +#include "QtHtmlReader.h" +#include "FFmpegWriter.h" +#include "Fraction.h" +#include "Enums.h" // for GRAVITY_BOTTOM_RIGHT #include "CrashHandler.h" using namespace openshot; From d73da93fb5d3f8184e7f53b16f827beedba71b34 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Sun, 18 Apr 2021 00:32:03 -0400 Subject: [PATCH 68/84] Don't use OpenShot.h in OpenCV example --- examples/Example_opencv.cpp | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/examples/Example_opencv.cpp b/examples/Example_opencv.cpp index 6b605a840..92576b3cb 100644 --- a/examples/Example_opencv.cpp +++ b/examples/Example_opencv.cpp @@ -31,12 +31,15 @@ #include #include #include -#include "../../src/CVTracker.h" -#include "../../src/CVStabilization.h" -#include "../../src/CVObjectDetection.h" +#include "CVTracker.h" +#include "CVStabilization.h" +#include "CVObjectDetection.h" -#include "../../src/OpenShot.h" -#include "../../src/CrashHandler.h" +#include "Clip.h" +#include "EffectBase.h" +#include "EffectInfo.h" +#include "Frame.h" +#include "CrashHandler.h" using namespace openshot; using namespace std; @@ -60,7 +63,7 @@ void displayClip(openshot::Clip &r9){ // Opencv display window cv::namedWindow("Display Image", cv::WINDOW_NORMAL ); - + // Get video lenght int videoLenght = r9.Reader()->info.video_length; @@ -223,7 +226,7 @@ string jsonFormat(string key, string value, string type){ // Return JSON string for the tracker effect string trackerJson(cv::Rect2d r, bool onlyProtoPath){ - // Define path to save tracked data + // Define path to save tracked data string protobufDataPath = "kcf_tracker.data"; // Set the tracker string tracker = "KCF"; @@ -232,14 +235,14 @@ string trackerJson(cv::Rect2d r, bool onlyProtoPath){ string protobuf_data_path = jsonFormat("protobuf_data_path", protobufDataPath); string trackerType = jsonFormat("tracker-type", tracker); string bboxCoords = jsonFormat( - "region", - "{" + jsonFormat("x", to_string(r.x), "int") + - "," + jsonFormat("y", to_string(r.y), "int") + + "region", + "{" + jsonFormat("x", to_string(r.x), "int") + + "," + jsonFormat("y", to_string(r.y), "int") + "," + jsonFormat("width", to_string(r.width), "int") + - "," + jsonFormat("height", to_string(r.height), "int") + + "," + jsonFormat("height", to_string(r.height), "int") + "," + jsonFormat("first-frame", to_string(0), "int") + "}", - "rstring"); + "rstring"); // Return only the the protobuf path in JSON format if(onlyProtoPath) @@ -252,7 +255,7 @@ string trackerJson(cv::Rect2d r, bool onlyProtoPath){ // Return JSON string for the stabilizer effect string stabilizerJson(bool onlyProtoPath){ - // Define path to save stabilized data + // Define path to save stabilized data string protobufDataPath = "example_stabilizer.data"; // Set smoothing window value string smoothingWindow = "30"; @@ -271,13 +274,13 @@ string stabilizerJson(bool onlyProtoPath){ string objectDetectionJson(bool onlyProtoPath){ - // Define path to save object detection data + // Define path to save object detection data string protobufDataPath = "example_object_detection.data"; // Define processing device string processingDevice = "GPU"; // Set path to model configuration file string modelConfiguration = "yolov3.cfg"; - // Set path to model weights + // Set path to model weights string modelWeights = "yolov3.weights"; // Set path to class names file string classesFile = "obj.names"; From 5f853a34308f7846d68463528ba972d98dcebd7c Mon Sep 17 00:00:00 2001 From: Brenno Date: Sun, 18 Apr 2021 19:28:28 -0300 Subject: [PATCH 69/84] Fixed attaching a clip to Tracker and ObjectDetection Some problems still persists - Saved projects are not loading properly - There is an aspect ratio issue when attaching an emoji to the ObjectDetection --- src/EffectBase.cpp | 12 +++---- src/TrackedObjectBBox.cpp | 5 ++- src/effects/ObjectDetection.cpp | 60 ++++++++++++++++++++++++++------- src/effects/ObjectDetection.h | 3 -- src/effects/Tracker.cpp | 5 ++- 5 files changed, 58 insertions(+), 27 deletions(-) diff --git a/src/EffectBase.cpp b/src/EffectBase.cpp index 97e1ef5ee..e22283fe7 100644 --- a/src/EffectBase.cpp +++ b/src/EffectBase.cpp @@ -135,13 +135,11 @@ void EffectBase::SetJsonValue(Json::Value root) { // TODO: Fix recursive call for Object Detection // // Loop through the effects and check if we have a child effect linked to this effect - // for (auto const& effect : effects){ - // // Set the properties of all effects which parentEffect points to this - // if ((effect->info.parent_effect_id == this->Id()) && (effect->Id() != this->Id())) - // std::cout<<"passou3 \n"; - - // effect->SetJsonValue(root); - // } + for (auto const& effect : effects){ + // Set the properties of all effects which parentEffect points to this + if ((effect->info.parent_effect_id == this->Id()) && (effect->Id() != this->Id())) + effect->SetJsonValue(root); + } } // Set this effect properties with the parent effect properties (except the id and parent_effect_id) diff --git a/src/TrackedObjectBBox.cpp b/src/TrackedObjectBBox.cpp index 447efaf2f..dbf6efb97 100644 --- a/src/TrackedObjectBBox.cpp +++ b/src/TrackedObjectBBox.cpp @@ -394,10 +394,9 @@ void TrackedObjectBBox::SetJsonValue(const Json::Value root) protobufDataPath = root["protobuf_data_path"].asString(); // Set the id of the child clip - // Does not allow to link to the parent clip - if (!root["child_clip_id"].isNull() && root["box_id"].asString() != ""){ + if (!root["child_clip_id"].isNull() && root["child_clip_id"].asString() != ""){ Clip* parentClip = (Clip *) ParentClip(); - + if(parentClip && (root["child_clip_id"].asString() != parentClip->Id())){ ChildClipId(root["child_clip_id"].asString()); } diff --git a/src/effects/ObjectDetection.cpp b/src/effects/ObjectDetection.cpp index a85d807aa..ae1ab3c3e 100644 --- a/src/effects/ObjectDetection.cpp +++ b/src/effects/ObjectDetection.cpp @@ -31,7 +31,11 @@ #include "effects/ObjectDetection.h" #include "effects/Tracker.h" #include "Exceptions.h" +#include "Timeline.h" +#include +#include +#include using namespace std; using namespace openshot; @@ -86,6 +90,11 @@ std::shared_ptr ObjectDetection::GetFrame(std::shared_ptr frame, i return frame; } + // Initialize the Qt rectangle that will hold the positions of the bounding-box + std::vector boxRects; + // Initialize the image of the TrackedObject child clip + std::vector> childClipImages; + // Check if track data exists for the requested frame if (detectionsData.find(frame_number) != detectionsData.end()) { float fw = cv_image.size().width; @@ -144,6 +153,30 @@ std::shared_ptr ObjectDetection::GetFrame(std::shared_ptr frame, i box, cv_image, detections.objectIds.at(i), bg_rgba, bg_alpha, 1, true, draw_text); drawPred(detections.classIds.at(i), detections.confidences.at(i), box, cv_image, detections.objectIds.at(i), stroke_rgba, stroke_alpha, stroke_width, false, draw_text); + + + // Get the Detected Object's child clip + if (trackedObject->ChildClipId() != ""){ + // Cast the parent timeline of this effect + Timeline* parentTimeline = (Timeline *) ParentTimeline(); + if (parentTimeline){ + // Get the Tracked Object's child clip + Clip* childClip = parentTimeline->GetClip(trackedObject->ChildClipId()); + if (childClip){ + // Get the image of the child clip for this frame + std::shared_ptr childClipFrame = childClip->GetFrame(frame_number); + childClipImages.push_back(childClipFrame->GetImage()); + + // Set the Qt rectangle with the bounding-box properties + QRectF boxRect; + boxRect.setRect((int)((trackedBox.cx-trackedBox.width/2)*fw), + (int)((trackedBox.cy - trackedBox.height/2)*fh), + (int)(trackedBox.width*fw), + (int)(trackedBox.height*fh)); + boxRects.push_back(boxRect); + } + } + } } } } @@ -151,6 +184,20 @@ std::shared_ptr ObjectDetection::GetFrame(std::shared_ptr frame, i // Update Qt image with new Opencv frame frame->SetImageCV(cv_image); + // Set the bounding-box image with the Tracked Object's child clip image + if(boxRects.size() > 0){ + // Get the frame image + QImage frameImage = *(frame->GetImage()); + for(int i; i < boxRects.size();i++){ + // Set a Qt painter to the frame image + QPainter painter(&frameImage); + // Draw the child clip image inside the bounding-box + painter.drawImage(boxRects[i], *childClipImages[i], 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; } @@ -254,7 +301,6 @@ bool ObjectDetection::LoadObjDetectdData(std::string inputFilePath){ return false; } - // Make sure classNames, detectionsData and trackedObjects are empty classNames.clear(); detectionsData.clear(); @@ -340,18 +386,6 @@ bool ObjectDetection::LoadObjDetectdData(std::string inputFilePath){ return true; } -// Get tracker info for the desired frame -DetectionData ObjectDetection::GetTrackedData(size_t frameId){ - - // Check if the tracker info for the requested frame exists - if ( detectionsData.find(frameId) == detectionsData.end() ) { - return DetectionData(); - } else { - return detectionsData[frameId]; - } - -} - // Get the indexes and IDs of all visible objects in the given frame std::string ObjectDetection::GetVisibleObjects(int64_t frame_number) const{ diff --git a/src/effects/ObjectDetection.h b/src/effects/ObjectDetection.h index bf7782301..3866bd2f1 100644 --- a/src/effects/ObjectDetection.h +++ b/src/effects/ObjectDetection.h @@ -121,9 +121,6 @@ namespace openshot /// Load protobuf data file bool LoadObjDetectdData(std::string inputFilePath); - /// Get tracker info for the desired frame - DetectionData GetTrackedData(size_t frameId); - /// Get the indexes and IDs of all visible objects in the given frame std::string GetVisibleObjects(int64_t frame_number) const override; diff --git a/src/effects/Tracker.cpp b/src/effects/Tracker.cpp index c4373d667..2e72c6d17 100644 --- a/src/effects/Tracker.cpp +++ b/src/effects/Tracker.cpp @@ -144,7 +144,10 @@ std::shared_ptr Tracker::GetFrame(std::shared_ptr frame, int64_t f 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) ); + boxRect.setRect((int)((fd.cx-fd.width/2)*fw), + (int)((fd.cy - fd.height/2)*fh), + (int)(fd.width*fw), + (int)(fd.height*fh) ); } } } From f491d585fcd1a3fab54131a20b6f821a8b38cd0a Mon Sep 17 00:00:00 2001 From: Brenno Date: Tue, 20 Apr 2021 23:07:23 -0300 Subject: [PATCH 70/84] Added author and added licence in ClipProcessingJobs --- src/CVObjectDetection.cpp | 1 + src/CVObjectDetection.h | 1 + src/CVStabilization.cpp | 1 + src/CVStabilization.h | 1 + src/CVTracker.cpp | 1 + src/CVTracker.h | 1 + src/ClipProcessingJobs.cpp | 31 +++++++++++++++++++++++++++++++ src/ClipProcessingJobs.h | 3 ++- src/ProcessingController.h | 1 + src/TrackedObjectBBox.cpp | 1 + src/TrackedObjectBBox.h | 1 + src/TrackedObjectBase.cpp | 1 + src/TrackedObjectBase.h | 1 + src/effects/ObjectDetection.cpp | 1 + src/effects/ObjectDetection.h | 1 + src/effects/Stabilizer.cpp | 1 + src/effects/Stabilizer.h | 1 + src/effects/Tracker.cpp | 1 + src/effects/Tracker.h | 1 + tests/CVObjectDetection.cpp | 1 + tests/CVStabilizer.cpp | 1 + tests/CVTracker.cpp | 1 + 22 files changed, 53 insertions(+), 1 deletion(-) diff --git a/src/CVObjectDetection.cpp b/src/CVObjectDetection.cpp index 3fddb93f7..bab072770 100644 --- a/src/CVObjectDetection.cpp +++ b/src/CVObjectDetection.cpp @@ -2,6 +2,7 @@ * @file * @brief Source file for CVObjectDetection class * @author Jonathan Thomas + * @author Brenno Caldato * * @ref License */ diff --git a/src/CVObjectDetection.h b/src/CVObjectDetection.h index ba62be956..326fc7ce0 100644 --- a/src/CVObjectDetection.h +++ b/src/CVObjectDetection.h @@ -2,6 +2,7 @@ * @file * @brief Header file for CVObjectDetection class * @author Jonathan Thomas + * @author Brenno Caldato * * @ref License */ diff --git a/src/CVStabilization.cpp b/src/CVStabilization.cpp index 75eff5363..fd50f0162 100644 --- a/src/CVStabilization.cpp +++ b/src/CVStabilization.cpp @@ -2,6 +2,7 @@ * @file * @brief Source file for CVStabilization class * @author Jonathan Thomas + * @author Brenno Caldato * * @ref License */ diff --git a/src/CVStabilization.h b/src/CVStabilization.h index 96cbf7125..4dd04ca96 100644 --- a/src/CVStabilization.h +++ b/src/CVStabilization.h @@ -2,6 +2,7 @@ * @file * @brief Header file for CVStabilization class * @author Jonathan Thomas + * @author Brenno Caldato * * @ref License */ diff --git a/src/CVTracker.cpp b/src/CVTracker.cpp index f300c2d73..3b24a14b7 100644 --- a/src/CVTracker.cpp +++ b/src/CVTracker.cpp @@ -2,6 +2,7 @@ * @file * @brief Track an object selected by the user * @author Jonathan Thomas + * @author Brenno Caldato * * @ref License */ diff --git a/src/CVTracker.h b/src/CVTracker.h index 4ac28df53..51df4e767 100644 --- a/src/CVTracker.h +++ b/src/CVTracker.h @@ -2,6 +2,7 @@ * @file * @brief Track an object selected by the user * @author Jonathan Thomas + * @author Brenno Caldato * * @ref License */ diff --git a/src/ClipProcessingJobs.cpp b/src/ClipProcessingJobs.cpp index fb64fd78b..8e0b9d083 100644 --- a/src/ClipProcessingJobs.cpp +++ b/src/ClipProcessingJobs.cpp @@ -1,3 +1,34 @@ +/** + * @file + * @brief Source file for ClipProcessingJobs class + * @author Jonathan Thomas + * @author Brenno Caldato + * + * @ref License + */ + +/* LICENSE + * + * Copyright (c) 2008-2019 OpenShot Studios, LLC + * . This file is part of + * OpenShot Library (libopenshot), an open-source project dedicated to + * delivering high quality video editing and animation solutions to the + * world. For more information visit . + * + * OpenShot Library (libopenshot) is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * OpenShot Library (libopenshot) is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with OpenShot Library. If not, see . + */ + #include "ClipProcessingJobs.h" // Constructor responsible to choose processing type and apply to clip diff --git a/src/ClipProcessingJobs.h b/src/ClipProcessingJobs.h index 2a34d46e4..ffa6b4a4d 100644 --- a/src/ClipProcessingJobs.h +++ b/src/ClipProcessingJobs.h @@ -1,7 +1,8 @@ /** * @file - * @brief Header for the ClipProcessingJobs class + * @brief Header for ClipProcessingJobs class * @author Jonathan Thomas + * @author Brenno Caldato * * @ref License */ diff --git a/src/ProcessingController.h b/src/ProcessingController.h index 98c77888b..24d501e39 100644 --- a/src/ProcessingController.h +++ b/src/ProcessingController.h @@ -2,6 +2,7 @@ * @file * @brief This is a message class for thread safe comunication between ClipProcessingJobs and OpenCV classes * @author Jonathan Thomas + * @author Brenno Caldato * * @ref License */ diff --git a/src/TrackedObjectBBox.cpp b/src/TrackedObjectBBox.cpp index dbf6efb97..71642f6a8 100644 --- a/src/TrackedObjectBBox.cpp +++ b/src/TrackedObjectBBox.cpp @@ -2,6 +2,7 @@ * @file * @brief Source file for the TrackedObjectBBox class * @author Jonathan Thomas + * @author Brenno Caldato * * @ref License */ diff --git a/src/TrackedObjectBBox.h b/src/TrackedObjectBBox.h index bf66c388d..ae951e220 100644 --- a/src/TrackedObjectBBox.h +++ b/src/TrackedObjectBBox.h @@ -2,6 +2,7 @@ * @file * @brief Header file for the TrackedObjectBBox class * @author Jonathan Thomas + * @author Brenno Caldato * * @ref License */ diff --git a/src/TrackedObjectBase.cpp b/src/TrackedObjectBase.cpp index 631e0a651..f065b10a9 100644 --- a/src/TrackedObjectBase.cpp +++ b/src/TrackedObjectBase.cpp @@ -2,6 +2,7 @@ * @file * @brief Source file for the TrackedObjectBase class * @author Jonathan Thomas + * @author Brenno Caldato * * @ref License */ diff --git a/src/TrackedObjectBase.h b/src/TrackedObjectBase.h index 371b056fc..86278e637 100644 --- a/src/TrackedObjectBase.h +++ b/src/TrackedObjectBase.h @@ -2,6 +2,7 @@ * @file * @brief Header file for the TrackedObjectBase class * @author Jonathan Thomas + * @author Brenno Caldato * * @ref License */ diff --git a/src/effects/ObjectDetection.cpp b/src/effects/ObjectDetection.cpp index ae1ab3c3e..a59406015 100644 --- a/src/effects/ObjectDetection.cpp +++ b/src/effects/ObjectDetection.cpp @@ -2,6 +2,7 @@ * @file * @brief Source file for Object Detection effect class * @author Jonathan Thomas + * @author Brenno Caldato * * @ref License */ diff --git a/src/effects/ObjectDetection.h b/src/effects/ObjectDetection.h index 3866bd2f1..50e393080 100644 --- a/src/effects/ObjectDetection.h +++ b/src/effects/ObjectDetection.h @@ -2,6 +2,7 @@ * @file * @brief Header file for Object Detection effect class * @author Jonathan Thomas + * @author Brenno Caldato * * @ref License */ diff --git a/src/effects/Stabilizer.cpp b/src/effects/Stabilizer.cpp index e7fb3c029..6d1666ab4 100644 --- a/src/effects/Stabilizer.cpp +++ b/src/effects/Stabilizer.cpp @@ -2,6 +2,7 @@ * @file * @brief Source file for Stabilizer effect class * @author Jonathan Thomas + * @author Brenno Caldato * * @ref License */ diff --git a/src/effects/Stabilizer.h b/src/effects/Stabilizer.h index 73e8090ad..1291fb73f 100644 --- a/src/effects/Stabilizer.h +++ b/src/effects/Stabilizer.h @@ -2,6 +2,7 @@ * @file * @brief Header file for Stabilizer effect class * @author Jonathan Thomas + * @author Brenno Caldato * * @ref License */ diff --git a/src/effects/Tracker.cpp b/src/effects/Tracker.cpp index 2e72c6d17..ae2dbafd0 100644 --- a/src/effects/Tracker.cpp +++ b/src/effects/Tracker.cpp @@ -2,6 +2,7 @@ * @file * @brief Source file for Tracker effect class * @author Jonathan Thomas + * @author Brenno Caldato * * @ref License */ diff --git a/src/effects/Tracker.h b/src/effects/Tracker.h index 0ccf589c5..f7db6e2ec 100644 --- a/src/effects/Tracker.h +++ b/src/effects/Tracker.h @@ -2,6 +2,7 @@ * @file * @brief Header file for Tracker effect class * @author Jonathan Thomas + * @author Brenno Caldato * * @ref License */ diff --git a/tests/CVObjectDetection.cpp b/tests/CVObjectDetection.cpp index 688581c57..350f1b984 100644 --- a/tests/CVObjectDetection.cpp +++ b/tests/CVObjectDetection.cpp @@ -2,6 +2,7 @@ * @file * @brief Unit tests for CVObjectDetection * @author Jonathan Thomas + * @author Brenno Caldato * * @ref License */ diff --git a/tests/CVStabilizer.cpp b/tests/CVStabilizer.cpp index 61b9f6266..15782a574 100644 --- a/tests/CVStabilizer.cpp +++ b/tests/CVStabilizer.cpp @@ -2,6 +2,7 @@ * @file * @brief Unit tests for CVStabilizer * @author Jonathan Thomas + * @author Brenno Caldato * * @ref License */ diff --git a/tests/CVTracker.cpp b/tests/CVTracker.cpp index 2bc878889..5106a2d94 100644 --- a/tests/CVTracker.cpp +++ b/tests/CVTracker.cpp @@ -2,6 +2,7 @@ * @file * @brief Unit tests for CVTracker * @author Jonathan Thomas + * @author Brenno Caldato * * @ref License */ From 0b8481f335fa4eb507cafdc850776de414c4ed5d Mon Sep 17 00:00:00 2001 From: Brenno Date: Tue, 20 Apr 2021 23:09:07 -0300 Subject: [PATCH 71/84] Fixed aspect ratio and off-center displacement when attaching a clip to a tracked object --- src/effects/ObjectDetection.cpp | 2 ++ src/effects/Tracker.cpp | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/effects/ObjectDetection.cpp b/src/effects/ObjectDetection.cpp index a59406015..de91c7a71 100644 --- a/src/effects/ObjectDetection.cpp +++ b/src/effects/ObjectDetection.cpp @@ -164,6 +164,8 @@ std::shared_ptr ObjectDetection::GetFrame(std::shared_ptr frame, i // Get the Tracked Object's child clip Clip* childClip = parentTimeline->GetClip(trackedObject->ChildClipId()); if (childClip){ + std::shared_ptr f(new Frame(1, frame->GetWidth(), frame->GetHeight(), "#00000000")); + std::shared_ptr childClipFrame = childClip->GetFrame(f, frame_number); // Get the image of the child clip for this frame std::shared_ptr childClipFrame = childClip->GetFrame(frame_number); childClipImages.push_back(childClipFrame->GetImage()); diff --git a/src/effects/Tracker.cpp b/src/effects/Tracker.cpp index ae2dbafd0..d04d7e30d 100644 --- a/src/effects/Tracker.cpp +++ b/src/effects/Tracker.cpp @@ -141,7 +141,8 @@ std::shared_ptr Tracker::GetFrame(std::shared_ptr frame, int64_t f 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); + std::shared_ptr f(new Frame(1, frame->GetWidth(), frame->GetHeight(), "#00000000")); + std::shared_ptr childClipFrame = childClip->GetFrame(f, frame_number); childClipImage = childClipFrame->GetImage(); // Set the Qt rectangle with the bounding-box properties From f412cae5c6c4ba3ef8264358229dd255c756addc Mon Sep 17 00:00:00 2001 From: Brenno Date: Wed, 21 Apr 2021 13:46:10 -0300 Subject: [PATCH 72/84] small fix --- src/effects/ObjectDetection.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/effects/ObjectDetection.cpp b/src/effects/ObjectDetection.cpp index de91c7a71..9204a9510 100644 --- a/src/effects/ObjectDetection.cpp +++ b/src/effects/ObjectDetection.cpp @@ -165,9 +165,8 @@ std::shared_ptr ObjectDetection::GetFrame(std::shared_ptr frame, i Clip* childClip = parentTimeline->GetClip(trackedObject->ChildClipId()); if (childClip){ std::shared_ptr f(new Frame(1, frame->GetWidth(), frame->GetHeight(), "#00000000")); - std::shared_ptr childClipFrame = childClip->GetFrame(f, frame_number); // Get the image of the child clip for this frame - std::shared_ptr childClipFrame = childClip->GetFrame(frame_number); + std::shared_ptr childClipFrame = childClip->GetFrame(f, frame_number); childClipImages.push_back(childClipFrame->GetImage()); // Set the Qt rectangle with the bounding-box properties From 7a9d196d8cc3859fc2b05ba27946f992eecc8a4d Mon Sep 17 00:00:00 2001 From: Brenno Date: Mon, 26 Apr 2021 11:49:21 -0300 Subject: [PATCH 73/84] Fixed missing parent clip in TrackedObjectBoundingbox --- src/effects/ObjectDetection.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/effects/ObjectDetection.cpp b/src/effects/ObjectDetection.cpp index 9204a9510..19ef8ac97 100644 --- a/src/effects/ObjectDetection.cpp +++ b/src/effects/ObjectDetection.cpp @@ -364,7 +364,11 @@ bool ObjectDetection::LoadObjDetectdData(std::string inputFilePath){ // There is no tracked object with that id, so insert a new one TrackedObjectBBox trackedObj((int)classesColor[classId](0), (int)classesColor[classId](1), (int)classesColor[classId](2), (int)0); trackedObj.AddBox(id, x+(w/2), y+(h/2), w, h, 0.0); + std::shared_ptr trackedObjPtr = std::make_shared(trackedObj); + ClipBase* parentClip = this->ParentClip(); + trackedObjPtr->ParentClip(parentClip); + trackedObjects.insert({objectId, trackedObjPtr}); } From c6ce5b0e16e3f4246d00411465ad2cccda67e71a Mon Sep 17 00:00:00 2001 From: Brenno Date: Sat, 8 May 2021 20:24:39 -0300 Subject: [PATCH 74/84] Key "objects" in Json hold a dict of tracked objects --- src/TrackedObjectBBox.cpp | 8 +------ src/effects/ObjectDetection.cpp | 40 ++++++++++++++++++++------------- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/src/TrackedObjectBBox.cpp b/src/TrackedObjectBBox.cpp index 71642f6a8..cc8be1872 100644 --- a/src/TrackedObjectBBox.cpp +++ b/src/TrackedObjectBBox.cpp @@ -382,25 +382,19 @@ void TrackedObjectBBox::SetJsonValue(const Json::Value root) if (!root["BaseFPS"]["den"].isNull()) BaseFps.den = (int)root["BaseFPS"]["den"].asInt(); } - // Set the TimeScale by the given JSON object if (!root["TimeScale"].isNull()) { double scale = (double)root["TimeScale"].asDouble(); this->ScalePoints(scale); } - // Set the protobuf data path by the given JSON object if (!root["protobuf_data_path"].isNull()) protobufDataPath = root["protobuf_data_path"].asString(); - // Set the id of the child clip if (!root["child_clip_id"].isNull() && root["child_clip_id"].asString() != ""){ Clip* parentClip = (Clip *) ParentClip(); - - if(parentClip && (root["child_clip_id"].asString() != parentClip->Id())){ - ChildClipId(root["child_clip_id"].asString()); - } + ChildClipId(root["child_clip_id"].asString()); } // Set the Keyframes by the given JSON object diff --git a/src/effects/ObjectDetection.cpp b/src/effects/ObjectDetection.cpp index 19ef8ac97..6141ba550 100644 --- a/src/effects/ObjectDetection.cpp +++ b/src/effects/ObjectDetection.cpp @@ -369,6 +369,9 @@ bool ObjectDetection::LoadObjDetectdData(std::string inputFilePath){ ClipBase* parentClip = this->ParentClip(); trackedObjPtr->ParentClip(parentClip); + // Create a temp ID. This ID is necessary to initialize the object_id Json list + // this Id will be replaced by the one created in the UI + trackedObjPtr->Id(std::to_string(objectId)); trackedObjects.insert({objectId, trackedObjPtr}); } @@ -456,11 +459,13 @@ Json::Value ObjectDetection::JsonValue() const { root["display_box_text"] = display_box_text.JsonValue(); // Add tracked object's IDs to root - root["objects_id"] = Json::Value(Json::arrayValue); + Json::Value objects; for (auto const& trackedObject : trackedObjects){ Json::Value trackedObjectJSON = trackedObject.second->JsonValue(); - root["objects_id"].append(trackedObject.second->Id()); + // add object json + objects[trackedObject.second->Id()] = trackedObjectJSON; } + root["objects"] = objects; // Add the selected object Json to root if(trackedObjects.count(selectedObjectIndex) != 0){ @@ -482,7 +487,6 @@ void ObjectDetection::SetJson(const std::string value) { // Parse JSON string into JSON objects try { - std::cout<<"entrou no objectDetection SetJson \n"<SetJsonValue(root["objects"][obj_id]); + } + } + } + // Set the tracked object's ids if (!root["objects_id"].isNull()){ for (auto const& trackedObject : trackedObjects){ @@ -542,13 +553,6 @@ void ObjectDetection::SetJsonValue(const Json::Value root) { trackedObject.second->SetJsonValue(trackedObjectJSON); } } - - // Set the selected object's properties - if(trackedObjects.count(selectedObjectIndex) != 0){ - auto selectedObject = trackedObjects.at(selectedObjectIndex); - if (selectedObject) - selectedObject->SetJsonValue(root); - } } // Get all properties for a specific frame @@ -557,12 +561,16 @@ std::string ObjectDetection::PropertiesJSON(int64_t requested_frame) const { // Generate JSON properties list Json::Value root; - // Add the selected object Json to root + Json::Value objects; if(trackedObjects.count(selectedObjectIndex) != 0){ auto selectedObject = trackedObjects.at(selectedObjectIndex); - if (selectedObject) - root = selectedObject->PropertiesJSON(requested_frame); + if (selectedObject){ + Json::Value trackedObjectJSON = selectedObject->PropertiesJSON(requested_frame); + // add object json + objects[selectedObject->Id()] = trackedObjectJSON; + } } + root["objects"] = objects; root["selected_object_index"] = add_property_json("Selected Object", selectedObjectIndex, "int", "", NULL, 0, 200, false, requested_frame); root["id"] = add_property_json("ID", 0.0, "string", Id(), NULL, -1, -1, true, requested_frame); From 7eb23a9f1965341f9ac0358b42bdbc91c95b1a09 Mon Sep 17 00:00:00 2001 From: Brenno Date: Tue, 11 May 2021 11:34:30 -0300 Subject: [PATCH 75/84] Removed unnecessary Json tags --- src/effects/ObjectDetection.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/effects/ObjectDetection.cpp b/src/effects/ObjectDetection.cpp index 6141ba550..61b21c45d 100644 --- a/src/effects/ObjectDetection.cpp +++ b/src/effects/ObjectDetection.cpp @@ -467,16 +467,6 @@ Json::Value ObjectDetection::JsonValue() const { } root["objects"] = objects; - // Add the selected object Json to root - if(trackedObjects.count(selectedObjectIndex) != 0){ - auto selectedObject = trackedObjects.at(selectedObjectIndex); - if (selectedObject){ - Json::Value selectedObjectJSON = selectedObject->JsonValue(); - for (auto const& key : selectedObjectJSON.getMemberNames()) - root[key] = selectedObjectJSON[key]; - } - } - // return JsonValue return root; } From e45b81bd7bdf40ada605f81a8be08f64bc7742b6 Mon Sep 17 00:00:00 2001 From: Brenno Date: Tue, 11 May 2021 12:12:35 -0300 Subject: [PATCH 76/84] Updated Json communication of Tracker effect --- src/effects/ObjectDetection.cpp | 2 +- src/effects/Tracker.cpp | 50 +++++++++++++++++++++------------ 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/src/effects/ObjectDetection.cpp b/src/effects/ObjectDetection.cpp index 61b21c45d..30505cfb5 100644 --- a/src/effects/ObjectDetection.cpp +++ b/src/effects/ObjectDetection.cpp @@ -498,7 +498,7 @@ void ObjectDetection::SetJsonValue(const Json::Value root) { protobuf_data_path = root["protobuf_data_path"].asString(); if(!LoadObjDetectdData(protobuf_data_path)){ - throw InvalidFile("Invalid protobuf data path"); + throw InvalidFile("Invalid protobuf data path", ""); protobuf_data_path = ""; } } diff --git a/src/effects/Tracker.cpp b/src/effects/Tracker.cpp index d04d7e30d..a5aa511dd 100644 --- a/src/effects/Tracker.cpp +++ b/src/effects/Tracker.cpp @@ -54,6 +54,7 @@ Tracker::Tracker(std::string clipTrackerDataPath) trackedData->LoadBoxData(clipTrackerDataPath); ClipBase* parentClip = this->ParentClip(); trackedData->ParentClip(parentClip); + trackedData->Id(std::to_string(0)); // Insert TrackedObject with index 0 to the trackedObjects map trackedObjects.insert({0, trackedData}); } @@ -68,6 +69,7 @@ Tracker::Tracker() trackedData = std::make_shared(trackedDataObject); ClipBase* parentClip = this->ParentClip(); trackedData->ParentClip(parentClip); + trackedData->Id(std::to_string(0)); // Insert TrackedObject with index 0 to the trackedObjects map trackedObjects.insert({0, trackedData}); } @@ -260,17 +262,15 @@ Json::Value Tracker::JsonValue() const { root["BaseFPS"]["num"] = BaseFPS.num; root["BaseFPS"]["den"] = BaseFPS.den; root["TimeScale"] = this->TimeScale; - root["objects_id"] = Json::Value(Json::arrayValue); // Add trackedObjects IDs to JSON - for (auto const& trackedObject : trackedObjects){ - // Get the trackedObject JSON - Json::Value trackedObjectJSON = trackedObject.second->JsonValue(); - root["objects_id"].append(trackedObject.second->Id()); - // Save the trackedObject JSON on root - for (auto const& key : trackedObjectJSON.getMemberNames()) - root[key] = trackedObjectJSON[key]; - } + Json::Value objects; + for (auto const& trackedObject : trackedObjects){ + Json::Value trackedObjectJSON = trackedObject.second->JsonValue(); + // add object json + objects[trackedObject.second->Id()] = trackedObjectJSON; + } + root["objects"] = objects; // return JsonValue return root; @@ -329,18 +329,27 @@ void Tracker::SetJsonValue(const Json::Value root) { } } - // Set the tracked object's properties - for (auto const& trackedObject : trackedObjects){ - Json::Value trackedObjectJSON = root; - if (!root["objects_id"].isNull()) - trackedObjectJSON["box_id"] = root["objects_id"][trackedObject.first].asString(); - trackedObject.second->SetJsonValue(trackedObjectJSON); + if (!root["objects"].isNull()){ + for (auto const& trackedObject : trackedObjects){ + std::string obj_id = std::to_string(trackedObject.first); + if(!root["objects"][obj_id].isNull()){ + trackedObject.second->SetJsonValue(root["objects"][obj_id]); + } + } } + + // Set the tracked object's ids + if (!root["objects_id"].isNull()){ + for (auto const& trackedObject : trackedObjects){ + Json::Value trackedObjectJSON; + trackedObjectJSON["box_id"] = root["objects_id"][trackedObject.first].asString(); + trackedObject.second->SetJsonValue(trackedObjectJSON); + } + } return; } - // Get all properties for a specific frame std::string Tracker::PropertiesJSON(int64_t requested_frame) const { @@ -348,8 +357,13 @@ std::string Tracker::PropertiesJSON(int64_t requested_frame) const { Json::Value root; // Add trackedObject properties to JSON - for (auto const& trackedObject : trackedObjects) - root = trackedObject.second->PropertiesJSON(requested_frame); + Json::Value objects; + for (auto const& trackedObject : trackedObjects){ + Json::Value trackedObjectJSON = trackedObject.second->PropertiesJSON(requested_frame); + // add object json + objects[trackedObject.second->Id()] = trackedObjectJSON; + } + root["objects"] = objects; // Append effect's properties root["id"] = add_property_json("ID", 0.0, "string", Id(), NULL, -1, -1, true, requested_frame); From 4362c5fd1589e560dbbea10103031a17298d981c Mon Sep 17 00:00:00 2001 From: Brenno Date: Mon, 17 May 2021 11:38:24 -0300 Subject: [PATCH 77/84] Included AVresample outside if statement Small reversion on @ferdync changes because the if statement is not working on my setup --- src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 00870d3a3..c14e84b73 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -290,7 +290,7 @@ mark_as_advanced(QT_VERSION_STR) # Find FFmpeg libraries (used for video encoding / decoding) find_package(FFmpeg REQUIRED COMPONENTS avcodec avformat avutil swscale) -set(all_comps avcodec avformat avutil swscale) +set(all_comps avcodec avformat avutil swscale avresample) if(TARGET FFmpeg::swresample) list(APPEND all_comps swresample) else() From 2e8ff3b9825f013ea3536d4c19eacf3bc5cab606 Mon Sep 17 00:00:00 2001 From: Brenno Date: Mon, 17 May 2021 11:38:45 -0300 Subject: [PATCH 78/84] Added TrackedObjectBBox to python bindings --- bindings/python/openshot.i | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bindings/python/openshot.i b/bindings/python/openshot.i index 764333aa6..2bb21b20b 100644 --- a/bindings/python/openshot.i +++ b/bindings/python/openshot.i @@ -120,6 +120,7 @@ #include "effects/Stabilizer.h" #include "effects/Tracker.h" #include "effects/ObjectDetection.h" + #include "TrackedObjectBBox.h" %} #endif @@ -291,6 +292,7 @@ #ifdef USE_OPENCV %include "ClipProcessingJobs.h" + %include "TrackedObjectBBox.h" #endif #ifdef USE_IMAGEMAGICK From d9e4f0450e0a524512453fd05a58315d63cd002a Mon Sep 17 00:00:00 2001 From: Brenno Date: Mon, 17 May 2021 12:03:18 -0300 Subject: [PATCH 79/84] Disabling Examples_opencv because it needs a deep refactor --- examples/CMakeLists.txt | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index e3c694090..bde744d7e 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -65,13 +65,13 @@ if (BLACKMAGIC_FOUND) endif() ############### OPENCV EXAMPLE ################ -if (DEFINED CACHE{HAVE_OPENCV}) - # Create test executable - add_executable(openshot-example-opencv - Example_opencv.cpp) - - target_compile_definitions(openshot-example-opencv PRIVATE - -DTEST_MEDIA_PATH="${TEST_MEDIA_PATH}" ) - # Link test executable to the new library - target_link_libraries(openshot-example-opencv openshot) -endif() +#if (DEFINED CACHE{HAVE_OPENCV}) +# # Create test executable +# add_executable(openshot-example-opencv +# Example_opencv.cpp) +# +# target_compile_definitions(openshot-example-opencv PRIVATE +# -DTEST_MEDIA_PATH="${TEST_MEDIA_PATH}" ) +# # Link test executable to the new library +# target_link_libraries(openshot-example-opencv openshot) +#endif() From 36c72224cf1a7feb725868d151f131188c81be38 Mon Sep 17 00:00:00 2001 From: Brenno Date: Wed, 19 May 2021 10:45:15 -0300 Subject: [PATCH 80/84] Fixed Json in Tracker Tests --- tests/CVTracker.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/CVTracker.cpp b/tests/CVTracker.cpp index 5106a2d94..85611a0b9 100644 --- a/tests/CVTracker.cpp +++ b/tests/CVTracker.cpp @@ -57,7 +57,7 @@ TEST_CASE( "Track_Video", "[libopenshot][opencv][tracker]" ) { "protobuf_data_path": "kcf_tracker.data", "tracker-type": "KCF", - "region": {"x": 294, "y": 102, "width": 180, "height": 166, "first-frame": 1} + "region": {"normalized_x": 0.459375, "normalized_y": 0.28333, "normalized_width": 0.28125, "normalized_height": 0.461111, "first-frame": 1} } )proto"; // Create tracker @@ -73,9 +73,9 @@ TEST_CASE( "Track_Video", "[libopenshot][opencv][tracker]" ) float height = fd.y2 - y; // Compare if tracked data is equal to pre-tested ones - CHECK((int)(x * 640) == 259); - CHECK((int)(y * 360) == 131); - CHECK((int)(width * 640) == 180); + CHECK((int)(x * 640) == 256); + CHECK((int)(y * 360) == 134); + CHECK((int)(width * 640) == 179); CHECK((int)(height * 360) == 166); } From f51af2e91759556c06acad31d9a7fc61193170fe Mon Sep 17 00:00:00 2001 From: Brenno Date: Wed, 19 May 2021 11:21:08 -0300 Subject: [PATCH 81/84] More permissive range interval for Tracker test --- tests/CVTracker.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/CVTracker.cpp b/tests/CVTracker.cpp index 85611a0b9..bb4470654 100644 --- a/tests/CVTracker.cpp +++ b/tests/CVTracker.cpp @@ -67,16 +67,16 @@ TEST_CASE( "Track_Video", "[libopenshot][opencv][tracker]" ) kcfTracker.trackClip(c1, 1, 20, true); // Get tracked data FrameData fd = kcfTracker.GetTrackedData(20); - float x = fd.x1; - float y = fd.y1; - float width = fd.x2 - x; - float height = fd.y2 - y; + int x = (float)fd.x1 * 640; + int y = (float)fd.y1 * 360; + int width = ((float)fd.x2*640) - x; + int height = ((float)fd.y2*360) - y; // Compare if tracked data is equal to pre-tested ones - CHECK((int)(x * 640) == 256); - CHECK((int)(y * 360) == 134); - CHECK((int)(width * 640) == 179); - CHECK((int)(height * 360) == 166); + CHECK(x >= 255); CHECK(x <= 257); + CHECK(y >= 133); CHECK(y <= 135); + CHECK(width >= 179); CHECK(width <= 181); + CHECK(height >= 165); CHECK(height <= 168); } From e2b51da44227366b9f7460f31d5105b1d440a1d9 Mon Sep 17 00:00:00 2001 From: Brenno Date: Wed, 19 May 2021 11:45:09 -0300 Subject: [PATCH 82/84] Fixed missing detection in the first frame --- src/CVObjectDetection.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CVObjectDetection.cpp b/src/CVObjectDetection.cpp index bab072770..ac0ca1014 100644 --- a/src/CVObjectDetection.cpp +++ b/src/CVObjectDetection.cpp @@ -81,8 +81,8 @@ void CVObjectDetection::detectObjectsClip(openshot::Clip &video, size_t _start, size_t frame_number; if(!process_interval || end <= 1 || end-start == 0){ // Get total number of frames in video - start = (int)(video.Start() * video.Reader()->info.fps.ToFloat()) + 1; - end = (int)(video.End() * video.Reader()->info.fps.ToFloat()) + 1; + start = (int)(video.Start() * video.Reader()->info.fps.ToFloat()); + end = (int)(video.End() * video.Reader()->info.fps.ToFloat()); } for (frame_number = start; frame_number <= end; frame_number++) From ae0a6357168465ee8d280233631719763cb66b08 Mon Sep 17 00:00:00 2001 From: Brenno Date: Mon, 24 May 2021 11:32:34 -0300 Subject: [PATCH 83/84] removed assert from interpolation --- src/KeyFrame.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/KeyFrame.cpp b/src/KeyFrame.cpp index 048ef9313..4107f2def 100644 --- a/src/KeyFrame.cpp +++ b/src/KeyFrame.cpp @@ -94,8 +94,14 @@ namespace openshot{ } // Interpolate two points using the right Point's interpolation method double InterpolateBetween(Point const & left, Point const & right, double target, double allowed_error) { - assert(left.co.X < target); - assert(target <= right.co.X); + // check if target is outside of the extremities poits + // This can occur when moving fast the play head + if(left.co.X > target){ + return left.co.Y; + } + if(target > right.co.X){ + return right.co.Y; + } switch (right.interpolation) { case CONSTANT: return left.co.Y; case LINEAR: return InterpolateLinearCurve(left, right, target); From 27eb0e6e23b4c27ea28cebaee68325245efac2ca Mon Sep 17 00:00:00 2001 From: Brenno Date: Mon, 24 May 2021 11:45:39 -0300 Subject: [PATCH 84/84] Fixed Keyframe Test --- tests/KeyFrame.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/KeyFrame.cpp b/tests/KeyFrame.cpp index ad5036524..599c973f8 100644 --- a/tests/KeyFrame.cpp +++ b/tests/KeyFrame.cpp @@ -695,8 +695,9 @@ TEST_CASE( "AttachToObject", "[libopenshot][keyframe]" ) // Tracked Data JSON auto trackedDataJson = trackedData->JsonValue(); - // Get and cast the trakcedObject - auto trackedObject_base = t.GetTrackedObject(""); + // Get and cast the trakcedObjec + std::list ids = t.GetTrackedObjectsIds(); + auto trackedObject_base = t.GetTrackedObject(ids.front()); auto trackedObject = std::make_shared(); trackedObject = std::dynamic_pointer_cast(trackedObject_base); CHECK(trackedObject == trackedData);