Files
libopenshot/src/TrackedObjectBBox.h
Frank Dana 59138ea3e4 Adopt license management via Reuse project/tool (#711)
* reuse-managed license/copyright headers

reuse is a tool for compliance with the REUSE recommendations. See
<https://reuse.software/> for more information, and
<https://reuse.readthedocs.io/> for the online documentation.

* Set jsoncpp license
* Add MIT license for Decklink sources
* Explicitly license examples/
  - Add headers to source files
  - Change blanket licensing in .reuse/dep5 to only cover binary media
  - Import CC-BY-3.0 license and assign to sintel_trailer
2021-10-16 01:26:26 -04:00

221 lines
7.0 KiB
C++

/**
* @file
* @brief Header file for the TrackedObjectBBox class
* @author Jonathan Thomas <jonathan@openshot.org>
* @author Brenno Caldato <brenno.caldato@outlook.com>
*
* @ref License
*/
// Copyright (c) 2008-2019 OpenShot Studios, LLC
//
// SPDX-License-Identifier: LGPL-3.0-or-later
#ifndef OPENSHOT_TRACKEDOBJECTBBOX_H
#define OPENSHOT_TRACKEDOBJECTBBOX_H
#include "TrackedObjectBase.h"
#include "Color.h"
#include "Exceptions.h"
#include "Fraction.h"
#include "Json.h"
#include "KeyFrame.h"
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<double, BBox> 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<TrackedObjectBBox *>(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;
// 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<std::string, float> GetBoxValues(int64_t frame_number) const override;
/// Return a map that contains the properties of this object's parent clip
std::map<std::string, float> GetParentClipProperties(int64_t frame_number) const override;
};
} // namespace openshot
#endif