Skip to content

Commit 484f664

Browse files
Merge pull request #936 from luxonis/sdk/on_host_stereo_colorization
On-device stereo colorization
2 parents 9e588bd + f0e20b3 commit 484f664

File tree

3 files changed

+73
-36
lines changed

3 files changed

+73
-36
lines changed

depthai_sdk/examples/StereoComponent/stereo.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,10 @@
55
from depthai_sdk.visualize.configs import StereoColor
66

77
with OakCamera() as oak:
8-
stereo = oak.create_stereo('800p', fps=30)
9-
stereo.config_postprocessing(
10-
colorize=StereoColor.GRAY,
11-
colormap=cv2.COLORMAP_BONE,
12-
wls_filter=True,
13-
wls_level=WLSLevel.HIGH
14-
)
8+
stereo = oak.create_stereo('800p', fps=30, encode='h264')
9+
10+
stereo.config_postprocessing(colorize=StereoColor.RGBD, colormap=cv2.COLORMAP_MAGMA)
11+
stereo.config_wls(wls_level=WLSLevel.MEDIUM)
1512

1613
oak.visualize(stereo.out.disparity)
1714
oak.start(blocking=True)

depthai_sdk/setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
setup(
1111
name='depthai-sdk',
12-
version='1.9.3.1',
12+
version='1.9.4',
1313
description='This package provides an abstraction of the DepthAI API library.',
1414
long_description=io.open("README.md", encoding="utf-8").read(),
1515
long_description_content_type="text/markdown",

depthai_sdk/src/depthai_sdk/components/stereo_component.py

Lines changed: 68 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import warnings
12
from enum import Enum
23
from typing import Optional, Union, Any, Dict
34

@@ -6,11 +7,11 @@
67
from depthai_sdk.components.camera_component import CameraComponent
78
from depthai_sdk.components.component import Component
89
from depthai_sdk.components.parser import parse_cam_socket, parse_median_filter, parse_encode
9-
from depthai_sdk.oak_outputs.xout.xout_disparity import XoutDisparity
10+
from depthai_sdk.oak_outputs.xout.xout_base import XoutBase, StreamXout
1011
from depthai_sdk.oak_outputs.xout.xout_depth import XoutDepth
12+
from depthai_sdk.oak_outputs.xout.xout_disparity import XoutDisparity
1113
from depthai_sdk.oak_outputs.xout.xout_h26x import XoutH26x
1214
from depthai_sdk.oak_outputs.xout.xout_mjpeg import XoutMjpeg
13-
from depthai_sdk.oak_outputs.xout.xout_base import XoutBase, StreamXout
1415
from depthai_sdk.replay import Replay
1516
from depthai_sdk.visualize.configs import StereoColor
1617

@@ -32,8 +33,7 @@ def __init__(self,
3233
replay: Optional[Replay] = None,
3334
args: Any = None,
3435
name: Optional[str] = None,
35-
encode: Union[None, str, bool, dai.VideoEncoderProperties.Profile] = None
36-
):
36+
encode: Union[None, str, bool, dai.VideoEncoderProperties.Profile] = None):
3737
"""
3838
Args:
3939
pipeline (dai.Pipeline): DepthAI pipeline
@@ -44,15 +44,18 @@ def __init__(self,
4444
replay (Replay object, optional): Replay
4545
args (Any, optional): Use user defined arguments when constructing the pipeline
4646
name (str, optional): Name of the output stream
47+
encode (str/bool/Profile, optional): Encode the output stream
4748
"""
4849
super().__init__()
4950
self.out = self.Out(self)
5051

51-
left: Union[None, CameraComponent, dai.node.MonoCamera, dai.node.ColorCamera, dai.Node.Output]
52-
right: Union[None, CameraComponent, dai.node.MonoCamera, dai.node.ColorCamera, dai.Node.Output]
52+
self.left: Union[None, CameraComponent, dai.node.MonoCamera, dai.node.ColorCamera, dai.Node.Output]
53+
self.right: Union[None, CameraComponent, dai.node.MonoCamera, dai.node.ColorCamera, dai.Node.Output]
5354

54-
_left_stream: dai.Node.Output
55-
_right_stream: dai.Node.Output
55+
self._left_stream: dai.Node.Output
56+
self._right_stream: dai.Node.Output
57+
58+
self.colormap = None
5659

5760
self._replay: Optional[Replay] = replay
5861
self._resolution: Optional[Union[str, dai.MonoCameraProperties.SensorResolution]] = resolution
@@ -74,8 +77,8 @@ def __init__(self,
7477

7578
# Configuration variables
7679
self._colorize = None
77-
self._colormap = None
78-
self._use_wls_filter = None
80+
self._postprocess_colormap = None
81+
self.wls_enabled = None
7982
self._wls_level = None
8083
self._wls_lambda = None
8184
self._wls_sigma = None
@@ -129,14 +132,25 @@ def on_init(self, pipeline: dai.Pipeline, device: dai.Device, version: dai.OpenV
129132
self._left_stream.link(self.node.left)
130133
self._right_stream.link(self.node.right)
131134

135+
colormap_manip = None
136+
if self.colormap:
137+
colormap_manip = pipeline.create(dai.node.ImageManip)
138+
colormap_manip.initialConfig.setColormap(self.colormap, self.node.initialConfig.getMaxDisparity())
139+
colormap_manip.initialConfig.setFrameType(dai.ImgFrame.Type.NV12)
140+
colormap_manip.setMaxOutputFrameSize(1200 * 800 * 3)
141+
self.node.disparity.link(colormap_manip.inputImage)
142+
132143
if self.encoder:
133144
try:
134145
fps = self.left.get_fps() # CameraComponent
135146
except AttributeError:
136147
fps = self.left.getFps() # MonoCamera
137148

138149
self.encoder.setDefaultProfilePreset(fps, self._encoderProfile)
139-
self.node.disparity.link(self.encoder.input)
150+
if colormap_manip:
151+
colormap_manip.out.link(self.encoder.input)
152+
else:
153+
self.node.disparity.link(self.encoder.input)
140154

141155
self.node.setOutputSize(1200, 800)
142156

@@ -181,22 +195,14 @@ def config_stereo(self,
181195

182196
def config_postprocessing(self,
183197
colorize: Union[StereoColor, bool] = None,
184-
colormap: int = None,
185-
wls_filter: bool = None,
186-
wls_level: WLSLevel = None,
187-
wls_lambda: float = None,
188-
wls_sigma: float = None
198+
colormap: int = None
189199
) -> None:
190200
"""
191201
Configures postprocessing options.
192202
193203
Args:
194204
colorize: Colorize the disparity map. Can be either a StereoColor enum, string or bool.
195205
colormap: Colormap to use for colorizing the disparity map.
196-
wls_filter: Enable WLS filter. If enabled, the output will be filtered using WLS filter.
197-
wls_level: WLS filter level. Can be either a WLSLevel enum or string.
198-
wls_lambda: WLS filter lambda.
199-
wls_sigma: WLS filter sigma.
200206
"""
201207
if colorize is None:
202208
self._colorize = StereoColor.GRAY
@@ -207,8 +213,22 @@ def config_postprocessing(self,
207213
elif isinstance(colorize, str):
208214
self._colorize = StereoColor[colorize.upper()]
209215

210-
self._colormap = colormap
211-
self._use_wls_filter = wls_filter
216+
self._postprocess_colormap = colormap
217+
218+
def config_wls(self,
219+
wls_level: Union[WLSLevel, str] = None,
220+
wls_lambda: float = None,
221+
wls_sigma: float = None
222+
) -> None:
223+
"""
224+
Configures WLS filter options.
225+
226+
Args:
227+
wls_level: WLS filter level. Can be either a WLSLevel enum or string.
228+
wls_lambda: WLS filter lambda.
229+
wls_sigma: WLS filter sigma.
230+
"""
231+
self.wls_enabled = True if wls_level else False
212232

213233
if isinstance(wls_level, WLSLevel):
214234
self._wls_level = wls_level
@@ -218,6 +238,15 @@ def config_postprocessing(self,
218238
self._wls_lambda = wls_lambda
219239
self._wls_sigma = wls_sigma
220240

241+
def set_colormap(self, colormap: dai.Colormap):
242+
"""
243+
Sets the colormap to use for colorizing the disparity map. Used for on-device postprocessing.
244+
245+
Args:
246+
colormap: Colormap to use for colorizing the disparity map.
247+
"""
248+
self.colormap = colormap
249+
221250
def _get_disparity_factor(self, device: dai.Device) -> float:
222251
"""
223252
Calculates the disparity factor used to calculate depth from disparity.
@@ -254,6 +283,10 @@ def main(self, pipeline: dai.Pipeline, device: dai.Device) -> XoutBase:
254283
return self.depth(pipeline, device)
255284

256285
def disparity(self, pipeline: dai.Pipeline, device: dai.Device) -> XoutBase:
286+
if self._comp.colormap:
287+
warnings.warn('Colormap set with `set_colormap` is ignored when using disparity output. '
288+
'Please use `configure_postprocessing` instead.')
289+
257290
fps = self._comp.left.get_fps() if self._comp._replay is None else self._comp._replay.getFps()
258291

259292
out = XoutDisparity(
@@ -262,8 +295,8 @@ def disparity(self, pipeline: dai.Pipeline, device: dai.Device) -> XoutBase:
262295
max_disp=self._comp.node.getMaxDisparity(),
263296
fps=fps,
264297
colorize=self._comp._colorize,
265-
colormap=self._comp._colormap,
266-
use_wls_filter=self._comp._use_wls_filter,
298+
colormap=self._comp._postprocess_colormap,
299+
use_wls_filter=self._comp.wls_enabled,
267300
wls_level=self._comp._wls_level,
268301
wls_lambda=self._comp._wls_lambda,
269302
wls_sigma=self._comp._wls_sigma
@@ -272,15 +305,19 @@ def disparity(self, pipeline: dai.Pipeline, device: dai.Device) -> XoutBase:
272305
return self._comp._create_xout(pipeline, out)
273306

274307
def depth(self, pipeline: dai.Pipeline, device: dai.Device) -> XoutBase:
308+
if self._comp.colormap:
309+
warnings.warn('Colormap set with `set_colormap` is ignored when using depth output. '
310+
'Please use `configure_postprocessing` instead.')
311+
275312
fps = self._comp.left.get_fps() if self._comp._replay is None else self._comp._replay.getFps()
276313
out = XoutDepth(
277314
device=device,
278315
frames=StreamXout(self._comp.node.id, self._comp.depth, name=self._comp.name),
279316
mono_frames=StreamXout(self._comp.node.id, self._comp._right_stream, name=self._comp.name),
280317
fps=fps,
281318
colorize=self._comp._colorize,
282-
colormap=self._comp._colormap,
283-
use_wls_filter=self._comp._use_wls_filter,
319+
colormap=self._comp._postprocess_colormap,
320+
use_wls_filter=self._comp.wls_enabled,
284321
wls_level=self._comp._wls_level,
285322
wls_lambda=self._comp._wls_lambda,
286323
wls_sigma=self._comp._wls_sigma
@@ -291,15 +328,18 @@ def encoded(self, pipeline: dai.Pipeline, device: dai.Device) -> XoutBase:
291328
if not self._comp.encoder:
292329
raise RuntimeError('Encoder not enabled, cannot output encoded frames')
293330

331+
if self._comp.wls_enabled:
332+
warnings.warn('WLS filter is enabled, but cannot be applied to encoded frames.')
333+
294334
if self._comp._encoderProfile == dai.VideoEncoderProperties.Profile.MJPEG:
295335
out = XoutMjpeg(frames=StreamXout(self._comp.encoder.id, self._comp.encoder.bitstream),
296-
color=False,
336+
color=self._comp.colormap is not None,
297337
lossless=self._comp.encoder.getLossless(),
298338
fps=self._comp.encoder.getFrameRate(),
299339
frame_shape=(1200, 800))
300340
else:
301341
out = XoutH26x(frames=StreamXout(self._comp.encoder.id, self._comp.encoder.bitstream),
302-
color=False,
342+
color=self._comp.colormap is not None,
303343
profile=self._comp._encoderProfile,
304344
fps=self._comp.encoder.getFrameRate(),
305345
frame_shape=(1200, 800))

0 commit comments

Comments
 (0)