diff --git a/src/Timeline.cpp b/src/Timeline.cpp index dd2c1702..47b52bdf 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; + 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["r"] = r; + 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 e9b201b0..b17d164e 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 62107013..a9ee0411 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 - 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"]; - } - } + // 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["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 64df91c3..39f7f33c 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);