Skip to content

Commit d6e6608

Browse files
Merge pull request #423 from luxonis/develop
Release v2.12.0.0
2 parents b4fe121 + 25feadf commit d6e6608

17 files changed

+234
-27
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ endif()
2929

3030
# Pybindings project
3131
set(TARGET_NAME depthai)
32-
project(depthai VERSION "1") # revision of bindings [depthai-core].[rev]
32+
project(depthai VERSION "0") # revision of bindings [depthai-core].[rev]
3333

3434
# Set default build type depending on context
3535
set(default_build_type "Release")

examples/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ add_python_example(edge_detector EdgeDetector/edge_detector.py)
109109

110110
## FeatureTracker
111111
add_python_example(feature_tracker FeatureTracker/feature_tracker.py)
112+
add_python_example(feature_tracker_color FeatureTracker/feature_tracker_color.py)
112113
add_python_example(feature_detector FeatureTracker/feature_detector.py)
113114

114115
## HostSide

examples/ColorCamera/rgb_scene.py

100644100755
File mode changed.
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
#!/usr/bin/env python3
2+
3+
import cv2
4+
import depthai as dai
5+
from collections import deque
6+
7+
class FeatureTrackerDrawer:
8+
9+
lineColor = (200, 0, 200)
10+
pointColor = (0, 0, 255)
11+
circleRadius = 2
12+
maxTrackedFeaturesPathLength = 30
13+
# for how many frames the feature is tracked
14+
trackedFeaturesPathLength = 10
15+
16+
trackedIDs = None
17+
trackedFeaturesPath = None
18+
19+
def onTrackBar(self, val):
20+
FeatureTrackerDrawer.trackedFeaturesPathLength = val
21+
pass
22+
23+
def trackFeaturePath(self, features):
24+
25+
newTrackedIDs = set()
26+
for currentFeature in features:
27+
currentID = currentFeature.id
28+
newTrackedIDs.add(currentID)
29+
30+
if currentID not in self.trackedFeaturesPath:
31+
self.trackedFeaturesPath[currentID] = deque()
32+
33+
path = self.trackedFeaturesPath[currentID]
34+
35+
path.append(currentFeature.position)
36+
while(len(path) > max(1, FeatureTrackerDrawer.trackedFeaturesPathLength)):
37+
path.popleft()
38+
39+
self.trackedFeaturesPath[currentID] = path
40+
41+
featuresToRemove = set()
42+
for oldId in self.trackedIDs:
43+
if oldId not in newTrackedIDs:
44+
featuresToRemove.add(oldId)
45+
46+
for id in featuresToRemove:
47+
self.trackedFeaturesPath.pop(id)
48+
49+
self.trackedIDs = newTrackedIDs
50+
51+
def drawFeatures(self, img):
52+
53+
cv2.setTrackbarPos(self.trackbarName, self.windowName, FeatureTrackerDrawer.trackedFeaturesPathLength)
54+
55+
for featurePath in self.trackedFeaturesPath.values():
56+
path = featurePath
57+
58+
for j in range(len(path) - 1):
59+
src = (int(path[j].x), int(path[j].y))
60+
dst = (int(path[j + 1].x), int(path[j + 1].y))
61+
cv2.line(img, src, dst, self.lineColor, 1, cv2.LINE_AA, 0)
62+
j = len(path) - 1
63+
cv2.circle(img, (int(path[j].x), int(path[j].y)), self.circleRadius, self.pointColor, -1, cv2.LINE_AA, 0)
64+
65+
def __init__(self, trackbarName, windowName):
66+
self.trackbarName = trackbarName
67+
self.windowName = windowName
68+
cv2.namedWindow(windowName)
69+
cv2.createTrackbar(trackbarName, windowName, FeatureTrackerDrawer.trackedFeaturesPathLength, FeatureTrackerDrawer.maxTrackedFeaturesPathLength, self.onTrackBar)
70+
self.trackedIDs = set()
71+
self.trackedFeaturesPath = dict()
72+
73+
74+
# Create pipeline
75+
pipeline = dai.Pipeline()
76+
77+
# Define sources and outputs
78+
colorCam = pipeline.create(dai.node.ColorCamera)
79+
featureTrackerColor = pipeline.create(dai.node.FeatureTracker)
80+
81+
xoutPassthroughFrameColor = pipeline.create(dai.node.XLinkOut)
82+
xoutTrackedFeaturesColor = pipeline.create(dai.node.XLinkOut)
83+
xinTrackedFeaturesConfig = pipeline.create(dai.node.XLinkIn)
84+
85+
xoutPassthroughFrameColor.setStreamName("passthroughFrameColor")
86+
xoutTrackedFeaturesColor.setStreamName("trackedFeaturesColor")
87+
xinTrackedFeaturesConfig.setStreamName("trackedFeaturesConfig")
88+
89+
# Properties
90+
colorCam.setResolution(dai.ColorCameraProperties.SensorResolution.THE_1080_P)
91+
92+
if 1:
93+
colorCam.setIspScale(2,3)
94+
colorCam.video.link(featureTrackerColor.inputImage)
95+
else:
96+
colorCam.isp.link(featureTrackerColor.inputImage)
97+
98+
# Linking
99+
featureTrackerColor.passthroughInputImage.link(xoutPassthroughFrameColor.input)
100+
featureTrackerColor.outputFeatures.link(xoutTrackedFeaturesColor.input)
101+
xinTrackedFeaturesConfig.out.link(featureTrackerColor.inputConfig)
102+
103+
# By default the least mount of resources are allocated
104+
# increasing it improves performance
105+
numShaves = 2
106+
numMemorySlices = 2
107+
featureTrackerColor.setHardwareResources(numShaves, numMemorySlices)
108+
featureTrackerConfig = featureTrackerColor.initialConfig.get()
109+
110+
print("Press 's' to switch between Lucas-Kanade optical flow and hardware accelerated motion estimation!")
111+
112+
# Connect to device and start pipeline
113+
with dai.Device(pipeline) as device:
114+
115+
# Output queues used to receive the results
116+
passthroughImageColorQueue = device.getOutputQueue("passthroughFrameColor", 8, False)
117+
outputFeaturesColorQueue = device.getOutputQueue("trackedFeaturesColor", 8, False)
118+
119+
inputFeatureTrackerConfigQueue = device.getInputQueue("trackedFeaturesConfig")
120+
121+
colorWindowName = "color"
122+
colorFeatureDrawer = FeatureTrackerDrawer("Feature tracking duration (frames)", colorWindowName)
123+
124+
while True:
125+
inPassthroughFrameColor = passthroughImageColorQueue.get()
126+
passthroughFrameColor = inPassthroughFrameColor.getCvFrame()
127+
colorFrame = passthroughFrameColor
128+
129+
trackedFeaturesColor = outputFeaturesColorQueue.get().trackedFeatures
130+
colorFeatureDrawer.trackFeaturePath(trackedFeaturesColor)
131+
colorFeatureDrawer.drawFeatures(colorFrame)
132+
133+
# Show the frame
134+
cv2.imshow(colorWindowName, colorFrame)
135+
136+
key = cv2.waitKey(1)
137+
if key == ord('q'):
138+
break
139+
elif key == ord('s'):
140+
if featureTrackerConfig.motionEstimator.type == dai.FeatureTrackerConfig.MotionEstimator.Type.LUCAS_KANADE_OPTICAL_FLOW:
141+
featureTrackerConfig.motionEstimator.type = dai.FeatureTrackerConfig.MotionEstimator.Type.HW_MOTION_ESTIMATION
142+
print("Switching to hardware accelerated motion estimation")
143+
else:
144+
featureTrackerConfig.motionEstimator.type = dai.FeatureTrackerConfig.MotionEstimator.Type.LUCAS_KANADE_OPTICAL_FLOW
145+
print("Switching to Lucas-Kanade optical flow")
146+
147+
cfg = dai.FeatureTrackerConfig()
148+
cfg.set(featureTrackerConfig)
149+
inputFeatureTrackerConfigQueue.send(cfg)

examples/ImageManip/image_manip_rotate.py

100644100755
File mode changed.

examples/ImageManip/image_manip_tiling.py

100644100755
File mode changed.

examples/Script/script_camera_control.py

100644100755
File mode changed.

examples/Script/script_get_ip.py

100644100755
File mode changed.

examples/Script/script_http_client.py

100644100755
File mode changed.

examples/Script/script_http_server.py

100644100755
File mode changed.

examples/Script/script_mjpeg_server.py

100644100755
File mode changed.

examples/Script/script_nndata_example.py

100644100755
File mode changed.

examples/StereoDepth/stereo_depth_from_host.py

Lines changed: 64 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,6 @@
1616
parser.add_argument('-dumpdispcost', "--dumpdisparitycostvalues", action="store_true", help="Dumps the disparity cost values for each disparity range. 96 byte for each pixel.")
1717
args = parser.parse_args()
1818

19-
if args.debug and args.dumpdisparitycostvalues:
20-
print("-debug and --dumpdisparitycostvalues are mutually exclusive!")
21-
exit(1)
22-
2319
if not Path(datasetDefault).exists():
2420
import sys
2521
raise FileNotFoundError(f'Required file/s not found, please run "{sys.executable} install_requirements.py"')
@@ -54,6 +50,8 @@ def set(self, value):
5450
trLineqAlpha = list()
5551
trLineqBeta = list()
5652
trLineqThreshold = list()
53+
trCostAggregationP1 = list()
54+
trCostAggregationP2 = list()
5755

5856
def trackbarSigma(value):
5957
StereoConfigHandler.config.postProcessing.bilateralSigmaValue = value
@@ -96,6 +94,20 @@ def trackbarLineqThreshold(value):
9694
for tr in StereoConfigHandler.trLineqThreshold:
9795
tr.set(value)
9896

97+
def trackbarCostAggregationP1(value):
98+
StereoConfigHandler.config.costAggregation.horizontalPenaltyCostP1 = value
99+
StereoConfigHandler.config.costAggregation.verticalPenaltyCostP1 = value
100+
StereoConfigHandler.newConfig = True
101+
for tr in StereoConfigHandler.trCostAggregationP1:
102+
tr.set(value)
103+
104+
def trackbarCostAggregationP2(value):
105+
StereoConfigHandler.config.costAggregation.horizontalPenaltyCostP2 = value
106+
StereoConfigHandler.config.costAggregation.verticalPenaltyCostP2 = value
107+
StereoConfigHandler.newConfig = True
108+
for tr in StereoConfigHandler.trCostAggregationP2:
109+
tr.set(value)
110+
99111
def handleKeypress(key, stereoDepthConfigInQueue):
100112
if key == ord('m'):
101113
StereoConfigHandler.newConfig = True
@@ -138,6 +150,11 @@ def handleKeypress(key, stereoDepthConfigInQueue):
138150
StereoConfigHandler.config.algorithmControl.enableSubpixel = not StereoConfigHandler.config.algorithmControl.enableSubpixel
139151
state = "on" if StereoConfigHandler.config.algorithmControl.enableSubpixel else "off"
140152
print(f"Subpixel {state}")
153+
elif key == ord('3'):
154+
StereoConfigHandler.newConfig = True
155+
StereoConfigHandler.config.algorithmControl.enableExtended = not StereoConfigHandler.config.algorithmControl.enableExtended
156+
state = "on" if StereoConfigHandler.config.algorithmControl.enableExtended else "off"
157+
print(f"Extended {state}")
141158

142159
StereoConfigHandler.sendConfig(stereoDepthConfigInQueue)
143160

@@ -157,6 +174,8 @@ def registerWindow(stream):
157174
StereoConfigHandler.trLineqAlpha.append(StereoConfigHandler.Trackbar('Linear equation alpha', stream, 0, 15, StereoConfigHandler.config.costMatching.linearEquationParameters.alpha, StereoConfigHandler.trackbarLineqAlpha))
158175
StereoConfigHandler.trLineqBeta.append(StereoConfigHandler.Trackbar('Linear equation beta', stream, 0, 15, StereoConfigHandler.config.costMatching.linearEquationParameters.beta, StereoConfigHandler.trackbarLineqBeta))
159176
StereoConfigHandler.trLineqThreshold.append(StereoConfigHandler.Trackbar('Linear equation threshold', stream, 0, 255, StereoConfigHandler.config.costMatching.linearEquationParameters.threshold, StereoConfigHandler.trackbarLineqThreshold))
177+
StereoConfigHandler.trCostAggregationP1.append(StereoConfigHandler.Trackbar('Cost aggregation P1', stream, 0, 500, StereoConfigHandler.config.costAggregation.horizontalPenaltyCostP1, StereoConfigHandler.trackbarCostAggregationP1))
178+
StereoConfigHandler.trCostAggregationP2.append(StereoConfigHandler.Trackbar('Cost aggregation P2', stream, 0, 500, StereoConfigHandler.config.costAggregation.horizontalPenaltyCostP2, StereoConfigHandler.trackbarCostAggregationP2))
160179

161180
def __init__(self, config):
162181
print("Control median filter using the 'm' key.")
@@ -166,6 +185,7 @@ def __init__(self, config):
166185
print("Control census transform mean mode using the 'v' key.")
167186
print("Control left-right check mode using the '1' key.")
168187
print("Control subpixel mode using the '2' key.")
188+
print("Control extended mode using the '3' key.")
169189

170190
StereoConfigHandler.config = config
171191

@@ -204,6 +224,8 @@ def __init__(self, config):
204224
if args.debug:
205225
xoutDebugLrCheckIt1 = pipeline.create(dai.node.XLinkOut)
206226
xoutDebugLrCheckIt2 = pipeline.create(dai.node.XLinkOut)
227+
xoutDebugExtLrCheckIt1 = pipeline.create(dai.node.XLinkOut)
228+
xoutDebugExtLrCheckIt2 = pipeline.create(dai.node.XLinkOut)
207229
if args.dumpdisparitycostvalues:
208230
xoutDebugCostDump = pipeline.create(dai.node.XLinkOut)
209231

@@ -222,6 +244,8 @@ def __init__(self, config):
222244
if args.debug:
223245
xoutDebugLrCheckIt1.setStreamName('disparity_lr_check_iteration1')
224246
xoutDebugLrCheckIt2.setStreamName('disparity_lr_check_iteration2')
247+
xoutDebugExtLrCheckIt1.setStreamName('disparity_ext_lr_check_iteration1')
248+
xoutDebugExtLrCheckIt2.setStreamName('disparity_ext_lr_check_iteration2')
225249
if args.dumpdisparitycostvalues:
226250
xoutDebugCostDump.setStreamName('disparity_cost_dump')
227251

@@ -253,6 +277,8 @@ def __init__(self, config):
253277
if args.debug:
254278
stereo.debugDispLrCheckIt1.link(xoutDebugLrCheckIt1.input)
255279
stereo.debugDispLrCheckIt2.link(xoutDebugLrCheckIt2.input)
280+
stereo.debugExtDispLrCheckIt1.link(xoutDebugExtLrCheckIt1.input)
281+
stereo.debugExtDispLrCheckIt2.link(xoutDebugExtLrCheckIt2.input)
256282
if args.dumpdisparitycostvalues:
257283
stereo.debugDispCostDump.link(xoutDebugCostDump.input)
258284

@@ -278,6 +304,7 @@ def __init__(self, config):
278304
debugStreams = []
279305
if args.debug:
280306
debugStreams.extend(['disparity_lr_check_iteration1', 'disparity_lr_check_iteration2'])
307+
debugStreams.extend(['disparity_ext_lr_check_iteration1', 'disparity_ext_lr_check_iteration2'])
281308
if args.dumpdisparitycostvalues:
282309
debugStreams.append('disparity_cost_dump')
283310

@@ -327,22 +354,17 @@ def convertToCv2Frame(name, image, config):
327354

328355
# Create a receive queue for each stream
329356
q_list = []
330-
q_list_debug = []
331357
for s in streams:
332358
q = device.getOutputQueue(s, 8, blocking=False)
333359
q_list.append(q)
334360

335-
if args.debug or args.dumpdisparitycostvalues:
336-
q_list_debug = q_list.copy()
337-
for s in debugStreams:
338-
q = device.getOutputQueue(s, 8, blocking=False)
339-
q_list_debug.append(q)
340361

341362
inCfg = device.getOutputQueue("stereo_cfg", 8, blocking=False)
342363

343364
# Need to set a timestamp for input frames, for the sync stage in Stereo node
344365
timestamp_ms = 0
345366
index = 0
367+
prevQueues = q_list.copy()
346368
while True:
347369
# Handle input streams, if any
348370
if in_q_list:
@@ -374,13 +396,38 @@ def convertToCv2Frame(name, image, config):
374396
currentConfig = inCfg.get()
375397

376398
lrCheckEnabled = currentConfig.get().algorithmControl.enableLeftRightCheck
377-
queues = q_list
378-
379-
if (args.debug and lrCheckEnabled) or args.dumpdisparitycostvalues:
380-
queues = q_list_debug
381-
else:
382-
for s in debugStreams:
383-
cv2.destroyWindow(s)
399+
extendedEnabled = currentConfig.get().algorithmControl.enableExtended
400+
queues = q_list.copy()
401+
402+
if args.dumpdisparitycostvalues:
403+
q = device.getOutputQueue('disparity_cost_dump', 8, blocking=False)
404+
queues.append(q)
405+
406+
if args.debug:
407+
q_list_debug = []
408+
409+
activeDebugStreams = []
410+
if lrCheckEnabled:
411+
activeDebugStreams.extend(['disparity_lr_check_iteration1', 'disparity_lr_check_iteration2'])
412+
if extendedEnabled:
413+
activeDebugStreams.extend(['disparity_ext_lr_check_iteration1'])
414+
if lrCheckEnabled:
415+
activeDebugStreams.extend(['disparity_ext_lr_check_iteration2'])
416+
417+
for s in activeDebugStreams:
418+
q = device.getOutputQueue(s, 8, blocking=False)
419+
q_list_debug.append(q)
420+
421+
queues.extend(q_list_debug)
422+
423+
def ListDiff(li1, li2):
424+
return list(set(li1) - set(li2)) + list(set(li2) - set(li1))
425+
426+
diff = ListDiff(prevQueues, queues)
427+
for s in diff:
428+
name = s.getName()
429+
cv2.destroyWindow(name)
430+
prevQueues = queues.copy()
384431

385432
for q in queues:
386433
if q.getName() in ['left', 'right']: continue

examples/StereoDepth/stereo_depth_video.py

100644100755
File mode changed.

src/DatatypeBindings.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,6 +1062,7 @@ void DatatypeBindings::bind(pybind11::module& m, void* pCallstack){
10621062
algorithmControl
10631063
.def(py::init<>())
10641064
.def_readwrite("enableLeftRightCheck", &RawStereoDepthConfig::AlgorithmControl::enableLeftRightCheck, DOC(dai, RawStereoDepthConfig, AlgorithmControl, enableLeftRightCheck))
1065+
.def_readwrite("enableExtended", &RawStereoDepthConfig::AlgorithmControl::enableExtended, DOC(dai, RawStereoDepthConfig, AlgorithmControl, enableExtended))
10651066
.def_readwrite("enableSubpixel", &RawStereoDepthConfig::AlgorithmControl::enableSubpixel, DOC(dai, RawStereoDepthConfig, AlgorithmControl, enableSubpixel))
10661067
.def_readwrite("leftRightCheckThreshold", &RawStereoDepthConfig::AlgorithmControl::leftRightCheckThreshold, DOC(dai, RawStereoDepthConfig, AlgorithmControl, leftRightCheckThreshold))
10671068
.def_readwrite("subpixelFractionalBits", &RawStereoDepthConfig::AlgorithmControl::subpixelFractionalBits, DOC(dai, RawStereoDepthConfig, AlgorithmControl, subpixelFractionalBits))
@@ -1114,8 +1115,10 @@ void DatatypeBindings::bind(pybind11::module& m, void* pCallstack){
11141115
costAggregation
11151116
.def(py::init<>())
11161117
.def_readwrite("divisionFactor", &RawStereoDepthConfig::CostAggregation::divisionFactor, DOC(dai, RawStereoDepthConfig, CostAggregation, divisionFactor))
1117-
.def_readwrite("horizontalPenaltyCosts", &RawStereoDepthConfig::CostAggregation::horizontalPenaltyCosts, DOC(dai, RawStereoDepthConfig, CostAggregation, horizontalPenaltyCosts))
1118-
.def_readwrite("verticalPenaltyCosts", &RawStereoDepthConfig::CostAggregation::verticalPenaltyCosts, DOC(dai, RawStereoDepthConfig, CostAggregation, verticalPenaltyCosts))
1118+
.def_readwrite("horizontalPenaltyCostP1", &RawStereoDepthConfig::CostAggregation::horizontalPenaltyCostP1, DOC(dai, RawStereoDepthConfig, CostAggregation, horizontalPenaltyCostP1))
1119+
.def_readwrite("horizontalPenaltyCostP2", &RawStereoDepthConfig::CostAggregation::horizontalPenaltyCostP2, DOC(dai, RawStereoDepthConfig, CostAggregation, horizontalPenaltyCostP2))
1120+
.def_readwrite("verticalPenaltyCostP1", &RawStereoDepthConfig::CostAggregation::verticalPenaltyCostP1, DOC(dai, RawStereoDepthConfig, CostAggregation, verticalPenaltyCostP1))
1121+
.def_readwrite("verticalPenaltyCostP2", &RawStereoDepthConfig::CostAggregation::verticalPenaltyCostP2, DOC(dai, RawStereoDepthConfig, CostAggregation, verticalPenaltyCostP2))
11191122
;
11201123

11211124
rawStereoDepthConfig
@@ -1141,8 +1144,9 @@ void DatatypeBindings::bind(pybind11::module& m, void* pCallstack){
11411144
.def("getMedianFilter", &StereoDepthConfig::getMedianFilter, DOC(dai, StereoDepthConfig, getMedianFilter))
11421145
.def("getBilateralFilterSigma", &StereoDepthConfig::getBilateralFilterSigma, DOC(dai, StereoDepthConfig, getBilateralFilterSigma))
11431146
.def("getLeftRightCheckThreshold", &StereoDepthConfig::getLeftRightCheckThreshold, DOC(dai, StereoDepthConfig, getLeftRightCheckThreshold))
1144-
.def("setLeftRightCheck", &StereoDepthConfig::setLeftRightCheck, DOC(dai, StereoDepthConfig, setLeftRightCheck))
1145-
.def("setSubpixel", &StereoDepthConfig::setSubpixel, DOC(dai, StereoDepthConfig, setSubpixel))
1147+
.def("setLeftRightCheck", &StereoDepthConfig::setLeftRightCheck, py::arg("enable"), DOC(dai, StereoDepthConfig, setLeftRightCheck))
1148+
.def("setExtendedDisparity", &StereoDepthConfig::setExtendedDisparity, py::arg("enable"), DOC(dai, StereoDepthConfig, setExtendedDisparity))
1149+
.def("setSubpixel", &StereoDepthConfig::setSubpixel, py::arg("enable"), DOC(dai, StereoDepthConfig, setSubpixel))
11461150
.def("getMaxDisparity", &StereoDepthConfig::getMaxDisparity, DOC(dai, StereoDepthConfig, getMaxDisparity))
11471151
.def("set", &StereoDepthConfig::set, py::arg("config"), DOC(dai, StereoDepthConfig, set))
11481152
.def("get", &StereoDepthConfig::get, DOC(dai, StereoDepthConfig, get))

0 commit comments

Comments
 (0)