Skip to content

Commit 54f4d2a

Browse files
committed
Fixed depth recording in video format (ffv1 codec). Added example to showcase that
1 parent 3fe8c58 commit 54f4d2a

File tree

4 files changed

+39
-4
lines changed

4 files changed

+39
-4
lines changed

apps/record/requirements.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
depthai==2.17.0.0
22
depthai-sdk==1.2.4 # New SDK has Record module completely refactored. TODO port this app to new SDK
3-
numpy==1.23.4
3+
numpy==1.26.4
44
av==9.2.0
55
mcap==0.0.10
66
mcap-ros1-support==0.0.8

apps/uvc/requirements.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
--extra-index-url https://artifacts.luxonis.com/artifactory/luxonis-python-snapshot-local/
22
depthai==2.19.1.0.dev+e88af9a9db3dc630a3011dd52d1f5700cf6bf9b8
3-
depthai-sdk==1.2.1
3+
depthai-sdk==1.2.1
4+
numpy==1.26.4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
from depthai_sdk import OakCamera, RecordType
2+
import depthai as dai
3+
4+
FPS = 30
5+
with OakCamera() as oak:
6+
color = oak.create_camera('CAM_A', resolution='1080p', encode='mjpeg', fps=FPS)
7+
color.config_color_camera(isp_scale=(2,3)) # 720P color frames, mjpeg
8+
9+
stereo = oak.create_stereo(resolution='720p', fps=FPS)
10+
stereo.config_stereo(align=color, subpixel=True, lr_check=True)
11+
stereo.node.setOutputSize(640, 360) # 720p, downscaled to 640x360 (decimation filter, median filtering)
12+
# On-device post processing for stereo depth
13+
config = stereo.node.initialConfig.get()
14+
stereo.node.setPostProcessingHardwareResources(3, 3)
15+
config.postProcessing.speckleFilter.enable = True
16+
config.postProcessing.thresholdFilter.minRange = 400
17+
config.postProcessing.thresholdFilter.maxRange = 10_000 # 10m
18+
config.postProcessing.decimationFilter.decimationFactor = 2
19+
config.postProcessing.decimationFilter.decimationMode = dai.StereoDepthConfig.PostProcessing.DecimationFilter.DecimationMode.NON_ZERO_MEDIAN
20+
stereo.node.initialConfig.set(config)
21+
"""
22+
Depth will get encoded on-host with FFV1 codec (it supports 16bit grey), and color will be
23+
encoded on-device with MJPEG codec. FFV1 works well with .avi container, so depth video will be
24+
saved as .avi, and color video will be saved as .mp4.
25+
"""
26+
record_components = [stereo.out.depth, color.out.encoded]
27+
oak.record(record_components, './', record_type=RecordType.VIDEO).configure_syncing(True, threshold_ms=500/30)
28+
oak.start(blocking=True)
29+
30+

depthai_sdk/src/depthai_sdk/recorders/video_writers/video_writer.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ def _create_file(self, path_to_file: str, frame: dai.ImgFrame):
6060
options = {}
6161
if self._lossless:
6262
self._fourcc = 'rawvideo'
63-
elif frame.getType() == dai.ImgFrame.Type.RAW16:
63+
elif frame.getType() == dai.ImgFrame.Type.RAW16: # Depth map
6464
self._fourcc = 'ffv1'
6565
self._format = 'gray16le'
6666
else: # Mono/Color, encode
@@ -74,6 +74,11 @@ def _create_file(self, path_to_file: str, frame: dai.ImgFrame):
7474
self._stream.codec_context.width = frame.getWidth()
7575
self._stream.codec_context.height = frame.getHeight()
7676

77+
if self._fourcc == 'ffv1':
78+
self._stream.width = frame.getWidth()
79+
self._stream.height = frame.getHeight()
80+
self._stream.pix_fmt = 'gray16le' # Required for depth recording to work correctly
81+
7782
def write(self, img_frame: dai.ImgFrame):
7883
if self._file is None:
7984
self.create_file(subfolder='', frame=img_frame)
@@ -90,7 +95,6 @@ def write(self, img_frame: dai.ImgFrame):
9095
video_format = 'gray16le'
9196
else:
9297
raise ValueError(f'Unsupported frame type: {img_frame.getType()}')
93-
9498
video_frame = av.VideoFrame.from_ndarray(img_frame.getFrame(), format=video_format)
9599

96100
ts = int((img_frame.getTimestampDevice() - self._start_ts).total_seconds() * 1e3) # To milliseconds

0 commit comments

Comments
 (0)