Small refactor to assign Clip and Effect ids in base class

This commit is contained in:
Jonathan Thomas
2025-08-11 14:52:24 -05:00
parent 6cea273b77
commit e43f87552d
4 changed files with 98 additions and 51 deletions

View File

@@ -16,8 +16,8 @@
#include <memory>
#include "CacheMemory.h"
#include "Frame.h"
#include "Point.h"
#include "KeyFrame.h"
#include "IdGenerator.h"
#include "Json.h"
#include "TimelineBase.h"
@@ -48,6 +48,7 @@ namespace openshot {
public:
/// Constructor for the base clip
ClipBase() :
id(IdGenerator::Generate()),
position(0.0),
layer(0),
start(0.0),

36
src/IdGenerator.h Normal file
View File

@@ -0,0 +1,36 @@
/*
* @file
* @brief Header file for generating random identifier strings
*/
// Copyright (c) 2008-2025 OpenShot Studios, LLC
//
// SPDX-License-Identifier: LGPL-3.0-or-later
#ifndef OPENSHOT_ID_GENERATOR_H
#define OPENSHOT_ID_GENERATOR_H
#include <random>
#include <string>
namespace openshot {
class IdGenerator {
public:
static inline std::string Generate(int length = 8) {
static const char charset[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dist(0, static_cast<int>(sizeof(charset) - 2));
std::string result;
result.reserve(length);
for (int i = 0; i < length; ++i)
result += charset[dist(gen)];
return result;
}
};
} // namespace openshot
#endif // OPENSHOT_ID_GENERATOR_H

View File

@@ -221,16 +221,19 @@ bool ObjectDetection::LoadObjDetectdData(std::string inputFilePath)
tmpObj.stroke_alpha = Keyframe(1.0);
tmpObj.AddBox(frameId, x + w/2, y + h/2, w, h, 0.0);
auto ptr = std::make_shared<TrackedObjectBBox>(tmpObj);
ptr->ParentClip(this->ParentClip());
auto ptr = std::make_shared<TrackedObjectBBox>(tmpObj);
ptr->ParentClip(this->ParentClip());
// Prefix with effect UUID for a unique string ID
ptr->Id(this->Id() + "-" + std::to_string(objectId));
trackedObjects.emplace(objectId, ptr);
}
}
// Prefix with effect UUID for a unique string ID
std::string prefix = this->Id();
if (!prefix.empty())
prefix += "-";
ptr->Id(prefix + std::to_string(objectId));
trackedObjects.emplace(objectId, ptr);
}
}
// Save the DetectionData for this frame
// Save the DetectionData for this frame
detectionsData[frameId] = DetectionData(
classIds, confidences, boxes, frameId, objectIds
);
@@ -354,26 +357,26 @@ void ObjectDetection::SetJson(const std::string value) {
// Load Json::Value into this object
void ObjectDetection::SetJsonValue(const Json::Value root)
{
// Parent properties
EffectBase::SetJsonValue(root);
// Parent properties
EffectBase::SetJsonValue(root);
// If a protobuf path is provided, load & prefix IDs
if (!root["protobuf_data_path"].isNull() && protobuf_data_path.empty()) {
protobuf_data_path = root["protobuf_data_path"].asString();
if (!LoadObjDetectdData(protobuf_data_path)) {
throw InvalidFile("Invalid protobuf data path", "");
}
}
// If a protobuf path is provided, load & prefix IDs
if (!root["protobuf_data_path"].isNull() && protobuf_data_path.empty()) {
protobuf_data_path = root["protobuf_data_path"].asString();
if (!LoadObjDetectdData(protobuf_data_path)) {
throw InvalidFile("Invalid protobuf data path", "");
}
}
// Selected index, thresholds, UI flags, filters, etc.
if (!root["selected_object_index"].isNull())
selectedObjectIndex = root["selected_object_index"].asInt();
if (!root["confidence_threshold"].isNull())
confidence_threshold = root["confidence_threshold"].asFloat();
if (!root["display_box_text"].isNull())
display_box_text.SetJsonValue(root["display_box_text"]);
if (!root["display_boxes"].isNull())
display_boxes.SetJsonValue(root["display_boxes"]);
// Selected index, thresholds, UI flags, filters, etc.
if (!root["selected_object_index"].isNull())
selectedObjectIndex = root["selected_object_index"].asInt();
if (!root["confidence_threshold"].isNull())
confidence_threshold = root["confidence_threshold"].asFloat();
if (!root["display_box_text"].isNull())
display_box_text.SetJsonValue(root["display_box_text"]);
if (!root["display_boxes"].isNull())
display_boxes.SetJsonValue(root["display_boxes"]);
if (!root["class_filter"].isNull()) {
class_filter = root["class_filter"].asString();
@@ -388,24 +391,24 @@ void ObjectDetection::SetJsonValue(const Json::Value root)
}
// Apply any per-object overrides
if (!root["objects"].isNull()) {
for (auto &kv : trackedObjects) {
auto &idx = kv.first;
auto &obj = kv.second;
std::string key = std::to_string(idx);
if (!root["objects"][key].isNull())
obj->SetJsonValue(root["objects"][key]);
}
}
if (!root["objects_id"].isNull()) {
for (auto &kv : trackedObjects) {
auto &idx = kv.first;
auto &obj = kv.second;
Json::Value tmp;
tmp["box_id"] = root["objects_id"][idx].asString();
obj->SetJsonValue(tmp);
}
}
if (!root["objects"].isNull()) {
for (auto &kv : trackedObjects) {
auto &idx = kv.first;
auto &obj = kv.second;
std::string key = std::to_string(idx);
if (!root["objects"][key].isNull())
obj->SetJsonValue(root["objects"][key]);
}
}
if (!root["objects_id"].isNull()) {
for (auto &kv : trackedObjects) {
auto &idx = kv.first;
auto &obj = kv.second;
Json::Value tmp;
tmp["box_id"] = root["objects_id"][idx].asString();
obj->SetJsonValue(tmp);
}
}
}
// Get all properties for a specific frame
@@ -433,9 +436,9 @@ std::string ObjectDetection::PropertiesJSON(int64_t requested_frame) const {
root["display_box_text"]["choices"].append(add_property_choice_json("Yes", true, display_box_text.GetValue(requested_frame)));
root["display_box_text"]["choices"].append(add_property_choice_json("No", false, display_box_text.GetValue(requested_frame)));
root["display_boxes"] = add_property_json("Draw All Boxes", display_boxes.GetValue(requested_frame), "int", "", &display_boxes, 0, 1, false, requested_frame);
root["display_boxes"]["choices"].append(add_property_choice_json("Yes", true, display_boxes.GetValue(requested_frame)));
root["display_boxes"]["choices"].append(add_property_choice_json("No", false, display_boxes.GetValue(requested_frame)));
root["display_boxes"] = add_property_json("Draw All Boxes", display_boxes.GetValue(requested_frame), "int", "", &display_boxes, 0, 1, false, requested_frame);
root["display_boxes"]["choices"].append(add_property_choice_json("Yes", true, display_boxes.GetValue(requested_frame)));
root["display_boxes"]["choices"].append(add_property_choice_json("No", false, display_boxes.GetValue(requested_frame)));
// Return formatted string
return root.toStyledString();

View File

@@ -46,6 +46,10 @@ Tracker::Tracker()
// Seed our map with a single entry at index 0
trackedObjects.clear();
trackedObjects.emplace(0, trackedData);
// Assign ID to the placeholder object
if (trackedData)
trackedData->Id(Id() + "-0");
}
// Init effect settings
@@ -222,18 +226,21 @@ void Tracker::SetJsonValue(const Json::Value root) {
protobuf_data_path.clear();
}
else {
// prefix <effectUUID>-<index> for each entry
// prefix "<effectUUID>-<index>" for each entry
for (auto& kv : trackedObjects) {
auto idx = kv.first;
auto ptr = kv.second;
if (ptr) {
ptr->Id(this->Id() + "-" + std::to_string(idx));
std::string prefix = this->Id();
if (!prefix.empty())
prefix += "-";
ptr->Id(prefix + std::to_string(idx));
}
}
}
}
// then any per-object JSON overrides
// then any per-object JSON overrides...
if (!root["objects"].isNull()) {
for (auto& kv : trackedObjects) {
std::string key = std::to_string(kv.first);