Skip to content

Commit 4a28654

Browse files
committed
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.
1 parent ce2c4e0 commit 4a28654

File tree

4 files changed

+102
-53
lines changed

4 files changed

+102
-53
lines changed

src/Timeline.cpp

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,8 @@ std::list<std::string> Timeline::GetTrackedObjectsIds() const{
290290
return trackedObjects_ids;
291291
}
292292

293-
std::string Timeline::GetTrackedObjectValues(std::string id) const {
293+
// Return the trackedObject's properties as a JSON string
294+
std::string Timeline::GetTrackedObjectValues(std::string id, int64_t frame_number) const {
294295

295296
// Initialize the JSON object
296297
Json::Value trackedObjectJson;
@@ -304,19 +305,34 @@ std::string Timeline::GetTrackedObjectValues(std::string id) const {
304305
std::shared_ptr<TrackedObjectBBox> trackedObject = std::static_pointer_cast<TrackedObjectBBox>(iterator->second);
305306

306307
// Get the trackedObject values for it's first frame
307-
auto boxes = trackedObject->BoxVec;
308-
auto firstBox = boxes.begin()->second;
309-
float x1 = firstBox.cx - (firstBox.width/2);
310-
float y1 = firstBox.cy - (firstBox.height/2);
311-
float x2 = firstBox.cx + (firstBox.width/2);
312-
float y2 = firstBox.cy + (firstBox.height/2);
313-
float r = firstBox.angle;
314-
315-
trackedObjectJson["x1"] = x1;
316-
trackedObjectJson["y1"] = y1;
317-
trackedObjectJson["x2"] = x2;
318-
trackedObjectJson["y2"] = y2;
319-
trackedObjectJson["r"] = r;
308+
if (trackedObject->ExactlyContains(frame_number)){
309+
BBox box = trackedObject->GetBox(frame_number);
310+
float x1 = box.cx - (box.width/2);
311+
float y1 = box.cy - (box.height/2);
312+
float x2 = box.cx + (box.width/2);
313+
float y2 = box.cy + (box.height/2);
314+
float rotation = box.angle;
315+
316+
trackedObjectJson["x1"] = x1;
317+
trackedObjectJson["y1"] = y1;
318+
trackedObjectJson["x2"] = x2;
319+
trackedObjectJson["y2"] = y2;
320+
trackedObjectJson["rotation"] = rotation;
321+
322+
} else {
323+
BBox box = trackedObject->BoxVec.begin()->second;
324+
float x1 = box.cx - (box.width/2);
325+
float y1 = box.cy - (box.height/2);
326+
float x2 = box.cx + (box.width/2);
327+
float y2 = box.cy + (box.height/2);
328+
float rotation = box.angle;
329+
330+
trackedObjectJson["x1"] = x1;
331+
trackedObjectJson["y1"] = y1;
332+
trackedObjectJson["x2"] = x2;
333+
trackedObjectJson["y2"] = y2;
334+
trackedObjectJson["rotation"] = rotation;
335+
}
320336

321337
}
322338
else {
@@ -325,7 +341,7 @@ std::string Timeline::GetTrackedObjectValues(std::string id) const {
325341
trackedObjectJson["y1"] = 0;
326342
trackedObjectJson["x2"] = 0;
327343
trackedObjectJson["y2"] = 0;
328-
trackedObjectJson["r"] = 0;
344+
trackedObjectJson["rotation"] = 0;
329345
}
330346

331347
return trackedObjectJson.toStyledString();

src/Timeline.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,8 +250,8 @@ namespace openshot {
250250
std::shared_ptr<openshot::TrackedObjectBase> GetTrackedObject(std::string id) const;
251251
/// Return the ID's of the tracked objects as a list of strings
252252
std::list<std::string> GetTrackedObjectsIds() const;
253-
/// Return the first trackedObject's properties as a JSON string
254-
std::string GetTrackedObjectValues(std::string id) const;
253+
/// Return the trackedObject's properties as a JSON string
254+
std::string GetTrackedObjectValues(std::string id, int64_t frame_number) const;
255255

256256
/// @brief Add an openshot::Clip to the timeline
257257
/// @param clip Add an openshot::Clip to the timeline. A clip can contain any type of Reader.

src/effects/ObjectDetection.cpp

Lines changed: 66 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ ObjectDetection::ObjectDetection(std::string clipObDetectDataPath)
4545

4646
// Tries to load the tracker data from protobuf
4747
LoadObjDetectdData(clipObDetectDataPath);
48+
49+
// Initialize the selected object index as the first object index
50+
selectedObjectIndex = trackedObjects.begin()->first;
4851
}
4952

5053
// Default constructor
@@ -53,6 +56,8 @@ ObjectDetection::ObjectDetection()
5356
// Init effect properties
5457
init_effect_details();
5558

59+
// Initialize the selected object index as the first object index
60+
selectedObjectIndex = trackedObjects.begin()->first;
5661
}
5762

5863
// Init effect settings
@@ -273,18 +278,23 @@ Json::Value ObjectDetection::JsonValue() const {
273278
Json::Value root = EffectBase::JsonValue(); // get parent properties
274279
root["type"] = info.class_name;
275280
root["protobuf_data_path"] = protobuf_data_path;
281+
root["selected_object_index"] = selectedObjectIndex;
276282

277-
// Add trackedObjects IDs to JSON
278-
for (auto const& trackedObject : trackedObjects){
279-
Json::Value trackedObjectJSON = trackedObject.second->JsonValue();
280-
// Save the trackedObject JSON on root
283+
for (auto const& trackedObject : trackedObjects){
284+
Json::Value trackedObjectJSON = trackedObject.second->JsonValue();
281285
root["box_id-"+to_string(trackedObject.first)] = trackedObjectJSON["box_id"];
282-
root["delta_x-"+to_string(trackedObject.first)] = trackedObjectJSON["delta_x"];
283-
root["delta_y-"+to_string(trackedObject.first)] = trackedObjectJSON["delta_y"];
284-
root["scale_x-"+to_string(trackedObject.first)] = trackedObjectJSON["scale_x"];
285-
root["scale_y-"+to_string(trackedObject.first)] = trackedObjectJSON["scale_y"];
286-
root["rotation-"+to_string(trackedObject.first)] = trackedObjectJSON["rotation"];
287-
}
286+
}
287+
288+
// Add the selected object Json to root
289+
auto selectedObject = trackedObjects.at(selectedObjectIndex);
290+
if (selectedObject){
291+
Json::Value selectedObjectJSON = selectedObject->JsonValue();
292+
root["delta_x-"+to_string(selectedObjectIndex)] = selectedObjectJSON["delta_x"];
293+
root["delta_y-"+to_string(selectedObjectIndex)] = selectedObjectJSON["delta_y"];
294+
root["scale_x-"+to_string(selectedObjectIndex)] = selectedObjectJSON["scale_x"];
295+
root["scale_y-"+to_string(selectedObjectIndex)] = selectedObjectJSON["scale_y"];
296+
root["rotation-"+to_string(selectedObjectIndex)] = selectedObjectJSON["rotation"];
297+
}
288298

289299
// return JsonValue
290300
return root;
@@ -322,17 +332,31 @@ void ObjectDetection::SetJsonValue(const Json::Value root) {
322332
}
323333
}
324334

335+
// Set the selected object index
336+
if (!root["selected_object_index"].isNull())
337+
selectedObjectIndex = root["selected_object_index"].asInt();
338+
325339
for (auto const& trackedObject : trackedObjects){
326340
Json::Value trackedObjectJSON;
327341
trackedObjectJSON["box_id"] = root["box_id-"+to_string(trackedObject.first)];
328-
trackedObjectJSON["delta_x"] = root["delta_x-"+to_string(trackedObject.first)];
329-
trackedObjectJSON["delta_y"] = root["delta_y-"+to_string(trackedObject.first)];
330-
trackedObjectJSON["scale_x"] = root["scale_x-"+to_string(trackedObject.first)];
331-
trackedObjectJSON["scale_y"] = root["scale_y-"+to_string(trackedObject.first)];
332-
trackedObjectJSON["rotation"] = root["rotation-"+to_string(trackedObject.first)];
333-
if (!trackedObjectJSON.isNull())
334-
trackedObject.second->SetJsonValue(trackedObjectJSON);
335-
}
342+
trackedObject.second->SetJsonValue(trackedObjectJSON);
343+
}
344+
345+
// Set the selectec object's properties
346+
if (!root["box_id-"+to_string(selectedObjectIndex)].isNull()){
347+
Json::Value selectedObjectJSON;
348+
selectedObjectJSON["box_id"] = root["box_id-"+to_string(selectedObjectIndex)];
349+
selectedObjectJSON["delta_x"] = root["delta_x-"+to_string(selectedObjectIndex)];
350+
selectedObjectJSON["delta_y"] = root["delta_y-"+to_string(selectedObjectIndex)];
351+
selectedObjectJSON["scale_x"] = root["scale_x-"+to_string(selectedObjectIndex)];
352+
selectedObjectJSON["scale_y"] = root["scale_y-"+to_string(selectedObjectIndex)];
353+
selectedObjectJSON["rotation"] = root["rotation-"+to_string(selectedObjectIndex)];
354+
if (!selectedObjectJSON.isNull()){
355+
auto selectedObject = trackedObjects.at(selectedObjectIndex);
356+
if (selectedObject)
357+
selectedObject->SetJsonValue(selectedObjectJSON);
358+
}
359+
}
336360
}
337361

338362
// Get all properties for a specific frame
@@ -341,27 +365,33 @@ std::string ObjectDetection::PropertiesJSON(int64_t requested_frame) const {
341365
// Generate JSON properties list
342366
Json::Value root;
343367

344-
// Add trackedObjects IDs to JSON
345-
for (auto const& trackedObject : trackedObjects){
346-
// Save the trackedObject Id on root
368+
// root["visible_objects"] = Json::Value(Json::arrayValue);
369+
370+
for (auto const& trackedObject : trackedObjects){
347371
Json::Value trackedObjectJSON = trackedObject.second->PropertiesJSON(requested_frame);
348-
root["box_id-"+to_string(trackedObject.first)] = trackedObjectJSON["box_id"];
349372
root["visible-"+to_string(trackedObject.first)] = trackedObjectJSON["visible"];
350-
351-
// Add trackedObject's properties only if it's visible in this frame (performance boost)
352-
if (trackedObjectJSON["visible"]["value"].asBool()){
353-
root["x1-"+to_string(trackedObject.first)] = trackedObjectJSON["x1"];
354-
root["y1-"+to_string(trackedObject.first)] = trackedObjectJSON["y1"];
355-
root["x2-"+to_string(trackedObject.first)] = trackedObjectJSON["x2"];
356-
root["y2-"+to_string(trackedObject.first)] = trackedObjectJSON["y2"];
357-
root["delta_x-"+to_string(trackedObject.first)] = trackedObjectJSON["delta_x"];
358-
root["delta_y-"+to_string(trackedObject.first)] = trackedObjectJSON["delta_y"];
359-
root["scale_x-"+to_string(trackedObject.first)] = trackedObjectJSON["scale_x"];
360-
root["scale_y-"+to_string(trackedObject.first)] = trackedObjectJSON["scale_y"];
361-
root["rotation-"+to_string(trackedObject.first)] = trackedObjectJSON["rotation"];
362-
}
363-
}
373+
if (trackedObjectJSON["visible"]["value"].asBool())
374+
root["box_id-"+to_string(trackedObject.first)] = trackedObjectJSON["box_id"];
375+
}
376+
377+
// Add the selected object Json to root
378+
auto selectedObject = trackedObjects.at(selectedObjectIndex);
379+
if (selectedObject){
380+
Json::Value selectedObjectJSON = selectedObject->PropertiesJSON(requested_frame);
381+
root["box_id-"+to_string(selectedObjectIndex)] = selectedObjectJSON["box_id"];
382+
root["visible-"+to_string(selectedObjectIndex)] = selectedObjectJSON["visible"];
383+
root["x1-"+to_string(selectedObjectIndex)] = selectedObjectJSON["x1"];
384+
root["y1-"+to_string(selectedObjectIndex)] = selectedObjectJSON["y1"];
385+
root["x2-"+to_string(selectedObjectIndex)] = selectedObjectJSON["x2"];
386+
root["y2-"+to_string(selectedObjectIndex)] = selectedObjectJSON["y2"];
387+
root["delta_x-"+to_string(selectedObjectIndex)] = selectedObjectJSON["delta_x"];
388+
root["delta_y-"+to_string(selectedObjectIndex)] = selectedObjectJSON["delta_y"];
389+
root["scale_x-"+to_string(selectedObjectIndex)] = selectedObjectJSON["scale_x"];
390+
root["scale_y-"+to_string(selectedObjectIndex)] = selectedObjectJSON["scale_y"];
391+
root["rotation-"+to_string(selectedObjectIndex)] = selectedObjectJSON["rotation"];
392+
}
364393

394+
root["selected_object_index"] = add_property_json("Selected Object", selectedObjectIndex, "int", "", NULL, 0, 200, false, requested_frame);
365395
root["id"] = add_property_json("ID", 0.0, "string", Id(), NULL, -1, -1, true, requested_frame);
366396
root["position"] = add_property_json("Position", Position(), "float", "", NULL, 0, 1000 * 60 * 30, false, requested_frame);
367397
root["layer"] = add_property_json("Track", Layer(), "int", "", NULL, 0, 20, false, requested_frame);

src/effects/ObjectDetection.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ namespace openshot
8686

8787
public:
8888

89+
/// Index of the Tracked Object that was selected to modify it's properties
90+
int selectedObjectIndex;
91+
8992
/// Blank constructor, useful when using Json to load the effect properties
9093
ObjectDetection(std::string clipTrackerDataPath);
9194

0 commit comments

Comments
 (0)