Skip to content

Commit

Permalink
Added support to show the transform handler for the selected object
Browse files Browse the repository at this point in the history
When using the ObjectDetection effect, it's now possible to select one detected object and update it's properties through it's transform handler.
  • Loading branch information
BrennoCaldato committed Jan 27, 2021
1 parent ce2c4e0 commit 4a28654
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 53 deletions.
46 changes: 31 additions & 15 deletions src/Timeline.cpp
Expand Up @@ -290,7 +290,8 @@ std::list<std::string> 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;
Expand All @@ -304,19 +305,34 @@ std::string Timeline::GetTrackedObjectValues(std::string id) const {
std::shared_ptr<TrackedObjectBBox> trackedObject = std::static_pointer_cast<TrackedObjectBBox>(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 {
Expand All @@ -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();
Expand Down
4 changes: 2 additions & 2 deletions src/Timeline.h
Expand Up @@ -250,8 +250,8 @@ namespace openshot {
std::shared_ptr<openshot::TrackedObjectBase> GetTrackedObject(std::string id) const;
/// Return the ID's of the tracked objects as a list of strings
std::list<std::string> 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.
Expand Down
102 changes: 66 additions & 36 deletions src/effects/ObjectDetection.cpp
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand All @@ -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);
Expand Down
3 changes: 3 additions & 0 deletions src/effects/ObjectDetection.h
Expand Up @@ -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);

Expand Down

0 comments on commit 4a28654

Please sign in to comment.