Skip to content

Commit 3f04748

Browse files
Merge pull request #1109 from luxonis/object_tracker_improvements
ObjectTracker: expose tracking paramters; add force remove functionality
2 parents a3f153c + 0c90bc6 commit 3f04748

File tree

6 files changed

+95
-2
lines changed

6 files changed

+95
-2
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ pybind11_add_module(${TARGET_NAME}
159159
src/pipeline/datatype/PointCloudConfigBindings.cpp
160160
src/pipeline/datatype/PointCloudDataBindings.cpp
161161
src/pipeline/datatype/ImageAlignConfigBindings.cpp
162+
src/pipeline/datatype/ObjectTrackerConfigBindings.cpp
162163
)
163164

164165
if(WIN32)

examples/ObjectTracker/object_tracker.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,11 @@
2929

3030
xlinkOut = pipeline.create(dai.node.XLinkOut)
3131
trackerOut = pipeline.create(dai.node.XLinkOut)
32+
xinTrackerConfig = pipeline.create(dai.node.XLinkIn)
3233

3334
xlinkOut.setStreamName("preview")
3435
trackerOut.setStreamName("tracklets")
36+
xinTrackerConfig.setStreamName("trackerConfig")
3537

3638
# Properties
3739
camRgb.setPreviewSize(300, 300)
@@ -64,18 +66,27 @@
6466
detectionNetwork.out.link(objectTracker.inputDetections)
6567
objectTracker.out.link(trackerOut.input)
6668

69+
# set tracking parameters
70+
objectTracker.setOcclusionRatioThreshold(0.4)
71+
objectTracker.setTrackletMaxLifespan(120)
72+
objectTracker.setTrackletBirthThreshold(3)
73+
74+
xinTrackerConfig.out.link(objectTracker.inputConfig)
75+
6776
# Connect to device and start pipeline
6877
with dai.Device(pipeline) as device:
6978

7079
preview = device.getOutputQueue("preview", 4, False)
7180
tracklets = device.getOutputQueue("tracklets", 4, False)
81+
trackerConfigQueue = device.getInputQueue("trackerConfig")
7282

7383
startTime = time.monotonic()
7484
counter = 0
7585
fps = 0
7686
frame = None
7787

7888
while(True):
89+
latestTrackedIds = []
7990
imgFrame = preview.get()
8091
track = tracklets.get()
8192

@@ -106,9 +117,26 @@
106117
cv2.putText(frame, t.status.name, (x1 + 10, y1 + 50), cv2.FONT_HERSHEY_TRIPLEX, 0.5, 255)
107118
cv2.rectangle(frame, (x1, y1), (x2, y2), color, cv2.FONT_HERSHEY_SIMPLEX)
108119

120+
if t.status == dai.Tracklet.TrackingStatus.TRACKED:
121+
latestTrackedIds.append(t.id)
122+
109123
cv2.putText(frame, "NN fps: {:.2f}".format(fps), (2, frame.shape[0] - 4), cv2.FONT_HERSHEY_TRIPLEX, 0.4, color)
110124

111125
cv2.imshow("tracker", frame)
112126

113-
if cv2.waitKey(1) == ord('q'):
127+
key = cv2.waitKey(1)
128+
if key == ord('q'):
114129
break
130+
elif key == ord('g'):
131+
# send tracker config to device
132+
config = dai.ObjectTrackerConfig()
133+
134+
# take a random ID from the latest tracked IDs
135+
if len(latestTrackedIds) > 0:
136+
idToRemove = (np.random.choice(latestTrackedIds))
137+
print(f"Force removing ID: {idToRemove}")
138+
config.forceRemoveID(idToRemove)
139+
trackerConfigQueue.send(config)
140+
else:
141+
print("No tracked IDs available to force remove")
142+

src/DatatypeBindings.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ void bind_tracklets(pybind11::module& m, void* pCallstack);
2828
void bind_pointcloudconfig(pybind11::module& m, void* pCallstack);
2929
void bind_pointclouddata(pybind11::module& m, void* pCallstack);
3030
void bind_imagealignconfig(pybind11::module& m, void* pCallstack);
31+
void bind_objecttrackerconfig(pybind11::module& m, void* pCallstack);
3132

3233
void DatatypeBindings::addToCallstack(std::deque<StackFunction>& callstack) {
3334
// Bind common datatypebindings
@@ -59,6 +60,7 @@ void DatatypeBindings::addToCallstack(std::deque<StackFunction>& callstack) {
5960
callstack.push_front(bind_pointcloudconfig);
6061
callstack.push_front(bind_pointclouddata);
6162
callstack.push_front(bind_imagealignconfig);
63+
callstack.push_front(bind_objecttrackerconfig);
6264
}
6365

6466
void DatatypeBindings::bind(pybind11::module& m, void* pCallstack){
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#include "DatatypeBindings.hpp"
2+
#include "pipeline/CommonBindings.hpp"
3+
#include <unordered_map>
4+
#include <memory>
5+
6+
// depthai
7+
#include "depthai/pipeline/datatype/ObjectTrackerConfig.hpp"
8+
9+
//pybind
10+
#include <pybind11/chrono.h>
11+
#include <pybind11/numpy.h>
12+
13+
// #include "spdlog/spdlog.h"
14+
15+
void bind_objecttrackerconfig(pybind11::module& m, void* pCallstack){
16+
17+
using namespace dai;
18+
19+
py::class_<RawObjectTrackerConfig, RawBuffer, std::shared_ptr<RawObjectTrackerConfig>> rawConfig(m, "RawObjectTrackerConfig", DOC(dai, RawObjectTrackerConfig));
20+
py::class_<ObjectTrackerConfig, Buffer, std::shared_ptr<ObjectTrackerConfig>> config(m, "ObjectTrackerConfig", DOC(dai, ObjectTrackerConfig));
21+
22+
///////////////////////////////////////////////////////////////////////
23+
///////////////////////////////////////////////////////////////////////
24+
///////////////////////////////////////////////////////////////////////
25+
// Call the rest of the type defines, then perform the actual bindings
26+
Callstack* callstack = (Callstack*) pCallstack;
27+
auto cb = callstack->top();
28+
callstack->pop();
29+
cb(m, pCallstack);
30+
// Actual bindings
31+
///////////////////////////////////////////////////////////////////////
32+
///////////////////////////////////////////////////////////////////////
33+
///////////////////////////////////////////////////////////////////////
34+
35+
// Metadata / raw
36+
rawConfig
37+
.def(py::init<>())
38+
.def_readwrite("trackletIdsToRemove", &RawObjectTrackerConfig::trackletIdsToRemove, DOC(dai, RawObjectTrackerConfig, trackletIdsToRemove))
39+
;
40+
41+
// Message
42+
config
43+
.def(py::init<>())
44+
.def(py::init<std::shared_ptr<RawObjectTrackerConfig>>())
45+
46+
.def("set", &ObjectTrackerConfig::set, py::arg("config"), DOC(dai, ObjectTrackerConfig, set))
47+
.def("get", &ObjectTrackerConfig::get, DOC(dai, ObjectTrackerConfig, get))
48+
.def("forceRemoveID", &ObjectTrackerConfig::forceRemoveID, DOC(dai, ObjectTrackerConfig, forceRemoveID))
49+
.def("forceRemoveIDs", &ObjectTrackerConfig::forceRemoveIDs, DOC(dai, ObjectTrackerConfig, forceRemoveIDs))
50+
;
51+
52+
// add aliases
53+
54+
}

src/pipeline/node/ObjectTrackerBindings.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,18 @@ void bind_objecttracker(pybind11::module& m, void* pCallstack){
4848
.def_readwrite("detectionLabelsToTrack", &ObjectTrackerProperties::detectionLabelsToTrack, DOC(dai, ObjectTrackerProperties, detectionLabelsToTrack))
4949
.def_readwrite("trackerType", &ObjectTrackerProperties::trackerType, DOC(dai, ObjectTrackerProperties, trackerType))
5050
.def_readwrite("trackerIdAssignmentPolicy", &ObjectTrackerProperties::trackerIdAssignmentPolicy, DOC(dai, ObjectTrackerProperties, trackerIdAssignmentPolicy))
51+
.def_readwrite("trackingPerClass", &ObjectTrackerProperties::trackingPerClass, DOC(dai, ObjectTrackerProperties, trackingPerClass))
52+
.def_readwrite("occlusionRatioThreshold", &ObjectTrackerProperties::occlusionRatioThreshold, DOC(dai, ObjectTrackerProperties, occlusionRatioThreshold))
53+
.def_readwrite("trackletMaxLifespan", &ObjectTrackerProperties::trackletMaxLifespan, DOC(dai, ObjectTrackerProperties, trackletMaxLifespan))
54+
.def_readwrite("trackletBirthThreshold", &ObjectTrackerProperties::trackletBirthThreshold, DOC(dai, ObjectTrackerProperties, trackletBirthThreshold))
5155
;
5256

5357
// Node
5458
objectTracker
5559
.def_readonly("inputTrackerFrame", &ObjectTracker::inputTrackerFrame, DOC(dai, node, ObjectTracker, inputTrackerFrame))
5660
.def_readonly("inputDetectionFrame", &ObjectTracker::inputDetectionFrame, DOC(dai, node, ObjectTracker, inputDetectionFrame))
5761
.def_readonly("inputDetections", &ObjectTracker::inputDetections, DOC(dai, node, ObjectTracker, inputDetections))
62+
.def_readonly("inputConfig", &ObjectTracker::inputConfig, DOC(dai, node, ObjectTracker, inputConfig))
5863
.def_readonly("out", &ObjectTracker::out, DOC(dai, node, ObjectTracker, out))
5964
.def_readonly("passthroughTrackerFrame", &ObjectTracker::passthroughTrackerFrame, DOC(dai, node, ObjectTracker, passthroughTrackerFrame))
6065
.def_readonly("passthroughDetectionFrame", &ObjectTracker::passthroughDetectionFrame, DOC(dai, node, ObjectTracker, passthroughDetectionFrame))
@@ -66,6 +71,9 @@ void bind_objecttracker(pybind11::module& m, void* pCallstack){
6671
.def("setTrackerType", &ObjectTracker::setTrackerType, py::arg("type"), DOC(dai, node, ObjectTracker, setTrackerType))
6772
.def("setTrackerIdAssignmentPolicy", &ObjectTracker::setTrackerIdAssignmentPolicy, py::arg("type"), DOC(dai, node, ObjectTracker, setTrackerIdAssignmentPolicy))
6873
.def("setTrackingPerClass", &ObjectTracker::setTrackingPerClass, py::arg("trackingPerClass"), DOC(dai, node, ObjectTracker, setTrackingPerClass))
74+
.def("setOcclusionRatioThreshold", &ObjectTracker::setOcclusionRatioThreshold, py::arg("occlusionRatioThreshold"), DOC(dai, node, ObjectTracker, setOcclusionRatioThreshold))
75+
.def("setTrackletMaxLifespan", &ObjectTracker::setTrackletMaxLifespan, py::arg("lifespan"), DOC(dai, node, ObjectTracker, setTrackletMaxLifespan))
76+
.def("setTrackletBirthThreshold", &ObjectTracker::setTrackletBirthThreshold, py::arg("threshold"), DOC(dai, node, ObjectTracker, setTrackletBirthThreshold))
6977
;
7078
daiNodeModule.attr("ObjectTracker").attr("Properties") = objectTrackerProperties;
7179

0 commit comments

Comments
 (0)