Skip to content

Commit 97f9d6f

Browse files
authored
Merge pull request #1114 from luxonis/release_2.31.0.0
Release 2.31.0.0
2 parents 765299d + 7a3e683 commit 97f9d6f

File tree

12 files changed

+181
-48
lines changed

12 files changed

+181
-48
lines changed

.github/workflows/docker-hub.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@ jobs:
1313
runs-on: ${{ matrix.os }}
1414
strategy:
1515
matrix:
16-
os: [ubuntu-latest, [Linux, ARM], [Linux, ARM64]]
16+
os: [ubuntu-latest, [Linux, ARM], ubuntu-24.04-arm]
1717
include:
1818
- os: ubuntu-latest
1919
arch: amd64
2020
- os: [Linux, ARM]
2121
arch: armv7
22-
- os: [Linux, ARM64]
22+
- os: ubuntu-24.04-arm
2323
arch: armv8
2424
steps:
2525
- name: Clean the workspace

.github/workflows/main.yml

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,13 @@ jobs:
6767
needs: build-docstrings
6868
strategy:
6969
matrix:
70-
os: [ubuntu-latest, windows-latest, macos-latest]
70+
os: [ubuntu-latest, windows-latest, macos-14]
7171
runs-on: ${{ matrix.os }}
7272
steps:
7373
- name: Print home directory
7474
run: echo Home directory inside container $HOME
7575
- name: Setup cmake
76-
if: matrix.os == 'macos-latest'
76+
if: matrix.os == 'macos-14'
7777
uses: jwlawson/[email protected]
7878
with:
7979
cmake-version: '3.29.x'
@@ -113,7 +113,7 @@ jobs:
113113
sudo apt install libusb-1.0-0-dev
114114
115115
- name: Install dependencies (MacOS)
116-
if: matrix.os == 'macos-latest'
116+
if: matrix.os == 'macos-14'
117117
run: |
118118
python -m pip install --upgrade pip
119119
brew install libusb
@@ -184,7 +184,7 @@ jobs:
184184
runs-on: windows-latest
185185
strategy:
186186
matrix:
187-
python-version: [3.7, 3.8, 3.9, '3.10', '3.11', '3.12', '3.13']
187+
python-version: [3.9, '3.10', '3.11', '3.12', '3.13', '3.14']
188188
python-architecture: [x64, x86]
189189
fail-fast: false
190190
steps:
@@ -207,6 +207,11 @@ jobs:
207207
- name: Select Windows SDK
208208
run: echo "CMAKE_ARGS=-DCMAKE_SYSTEM_VERSION=${{ env.CMAKE_WINDOWS_SDK_VERSION }}" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
209209

210+
- name: Set UTF-8 encoding
211+
run: |
212+
echo "PYTHONIOENCODING=utf-8" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
213+
echo "PYTHONUTF8=1" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
214+
210215
- name: Install dependencies
211216
run: choco install strawberryperl
212217
- name: Set up Python ${{ matrix.python-version }}
@@ -240,7 +245,7 @@ jobs:
240245
needs: build-docstrings
241246
strategy:
242247
matrix:
243-
python-version: [3.8, 3.9, '3.10', '3.11', '3.12', '3.13']
248+
python-version: [3.9, '3.10', '3.11', '3.12', '3.13', '3.14']
244249
os: [macos-13, macos-14] # macos-13 is x64, macos-14 is arm64
245250
runs-on: ${{ matrix.os }}
246251
steps:
@@ -301,7 +306,7 @@ jobs:
301306
needs: build-docstrings
302307
runs-on: ubuntu-latest
303308
container:
304-
image: quay.io/pypa/manylinux_2_28_x86_64:latest
309+
image: quay.io/pypa/manylinux_2_28_x86_64:2025.11.10-2
305310
env:
306311
PLAT: manylinux_2_28_x86_64
307312
steps:
@@ -317,7 +322,7 @@ jobs:
317322
run: yum install -y --disableplugin=fastestmirror libusb1-devel perl-core
318323
- name: Installing cmake dependency
319324
run: |
320-
/opt/python/cp38-cp38/bin/python3.8 -m pip install cmake
325+
/opt/python/cp38-cp38/bin/python3.8 -m pip install "cmake<4.0"
321326
ln -s /opt/python/cp38-cp38/bin/cmake /bin/
322327
- name: Create folder structure
323328
run: mkdir -p wheelhouse/audited/
@@ -331,8 +336,8 @@ jobs:
331336

332337
- name: Build and install depthai-core
333338
run: |
334-
cmake -S depthai-core/ -B build_core -D CMAKE_BUILD_TYPE=Release -D CMAKE_TOOLCHAIN_FILE=$PWD/cmake/toolchain/pic.cmake
335-
cmake --build build_core --target install --parallel 4
339+
/opt/python/cp38-cp38/bin/cmake -S depthai-core/ -B build_core -D CMAKE_BUILD_TYPE=Release -D CMAKE_TOOLCHAIN_FILE=$PWD/cmake/toolchain/pic.cmake
340+
/opt/python/cp38-cp38/bin/cmake --build build_core --target install --parallel 4
336341
echo "DEPTHAI_INSTALLATION_DIR=$PWD/build_core/install/" >> $GITHUB_ENV
337342
338343
- name: Append build hash if not a tagged commit
@@ -341,10 +346,11 @@ jobs:
341346

342347
- name: Building source distribution
343348
run: |
349+
/opt/python/cp38-cp38/bin/python3.8 -m pip install --upgrade setuptools wheel
344350
/opt/python/cp38-cp38/bin/python3.8 setup.py sdist --formats=gztar
345351
mv dist/* wheelhouse/audited/
346352
- name: Build wheels
347-
run: for PYBIN in /opt/python/cp3{7..13}*/bin; do "${PYBIN}/pip" wheel . -w ./wheelhouse/ --verbose; done
353+
run: for PYBIN in /opt/python/cp3{9..14}*/bin; do "${PYBIN}/pip" wheel . -w ./wheelhouse/ --verbose; done
348354
- name: Audit wheels
349355
run: for whl in wheelhouse/*.whl; do auditwheel repair "$whl" --plat $PLAT -w wheelhouse/audited/; done
350356
- name: Archive wheel artifacts
@@ -363,9 +369,9 @@ jobs:
363369
# This job builds wheels for ARM64 arch
364370
build-linux-arm64:
365371
needs: build-docstrings
366-
runs-on: [self-hosted, linux, ARM64]
372+
runs-on: ubuntu-24.04-arm
367373
container:
368-
image: quay.io/pypa/manylinux_2_28_aarch64:latest
374+
image: quay.io/pypa/manylinux_2_28_aarch64:2025.11.10-2
369375
env:
370376
PLAT: manylinux_2_28_aarch64
371377
# Mount local hunter cache directory, instead of transfering to Github and back
@@ -379,7 +385,7 @@ jobs:
379385
run: yum install -y --disableplugin=fastestmirror libusb1-devel perl-core
380386
- name: Installing cmake dependency
381387
run: |
382-
/opt/python/cp38-cp38/bin/python3.8 -m pip install cmake
388+
/opt/python/cp38-cp38/bin/python3.8 -m pip install "cmake<4"
383389
ln -s /opt/python/cp38-cp38/bin/cmake /bin/
384390
- name: Create folder structure
385391
run: mkdir -p wheelhouse/audited/
@@ -393,15 +399,15 @@ jobs:
393399

394400
- name: Build and install depthai-core
395401
run: |
396-
cmake -S depthai-core/ -B build_core -D CMAKE_BUILD_TYPE=Release -D CMAKE_TOOLCHAIN_FILE=$PWD/cmake/toolchain/pic.cmake
397-
cmake --build build_core --target install --parallel 4
402+
/opt/python/cp38-cp38/bin/cmake -S depthai-core/ -B build_core -D CMAKE_BUILD_TYPE=Release -D CMAKE_TOOLCHAIN_FILE=$PWD/cmake/toolchain/pic.cmake
403+
/opt/python/cp38-cp38/bin/cmake --build build_core --target install --parallel 4
398404
echo "DEPTHAI_INSTALLATION_DIR=$PWD/build_core/install/" >> $GITHUB_ENV
399405
400406
- name: Append build hash if not a tagged commit
401407
if: startsWith(github.ref, 'refs/tags/v') != true
402408
run: echo "BUILD_COMMIT_HASH=${{github.sha}}" >> $GITHUB_ENV
403409
- name: Building wheels
404-
run: for PYBIN in /opt/python/cp3{7..13}*/bin; do "${PYBIN}/pip" wheel . -w ./wheelhouse/ --verbose; done
410+
run: for PYBIN in /opt/python/cp3{9..14}*/bin; do "${PYBIN}/pip" wheel . -w ./wheelhouse/ --verbose; done
405411
- name: Auditing wheels
406412
run: for whl in wheelhouse/*.whl; do auditwheel repair "$whl" --plat $PLAT -w wheelhouse/audited/; done
407413
- name: Archive wheel artifacts

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)

cmake/Hunter/config.cmake

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
hunter_config(
33
pybind11
44
VERSION "2.12.0"
5-
URL "https://github.com/pybind/pybind11/archive/refs/tags/v2.12.0.tar.gz"
6-
SHA1 "e70610cba7b6b7d7a57827d5357c016ad2155c0f"
5+
URL "https://github.com/pybind/pybind11/archive/refs/tags/v3.0.1.tar.gz"
6+
SHA1 "b20ddcd79e2b03b7e2777a2a0b06b646f2f23ce0"
77
)

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+

setup.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -238,19 +238,18 @@ def build_extension(self, ext):
238238
"Operating System :: Unix",
239239
"Programming Language :: Python",
240240
"Programming Language :: Python :: 3",
241-
"Programming Language :: Python :: 3.7",
242-
"Programming Language :: Python :: 3.8",
243241
"Programming Language :: Python :: 3.9",
244242
"Programming Language :: Python :: 3.10",
245243
"Programming Language :: Python :: 3.11",
246244
"Programming Language :: Python :: 3.12",
247245
"Programming Language :: Python :: 3.13",
246+
"Programming Language :: Python :: 3.14",
248247
"Programming Language :: C++",
249248
"Programming Language :: Python :: Implementation :: CPython",
250249
"Topic :: Scientific/Engineering",
251250
"Topic :: Software Development",
252251
],
253-
python_requires='>=3.7',
252+
python_requires='>=3.9',
254253
entry_points={
255254
"console_scripts": [
256255
f'depthai={DEPTHAI_CLI_MODULE_NAME}.depthai_cli:cli'

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)