I would like to live stream OAK ToF camera and save undistorted, spatially aligned and time synced RGB image, depth image, and point cloud using the newest DepthAI. Due to my sensor application requirements, I must minimize motion blur for both RGB and ToF cameras as much as possible, as the camera will be mounted on a fast-moving vehicle. This is the code that I have currently based on the RGBD node:
import depthai as dai
import cv2
import numpy as np
import open3d as o3d
import os
output_dir = "oak_tof_capture"
os.makedirs(output_dir, exist_ok=True)
with dai.Pipeline() as pipeline:
rgbd = pipeline.create(dai.node.RGBD).build(
autocreate=True,
mode=dai.node.StereoDepth.PresetMode.DEFAULT,
size=(640, 400)
)
tof = next(n for n in pipeline.getAllNodes() if isinstance(n, dai.node.ToF))
config = tof.getInitialConfig()
config.enableOpticalCorrection = True
config.enableDistortionCorrection = True
config.enablePhaseShuffleTemporalFilter = False
config.enablePhaseUnwrapping = False
config.phaseUnwrappingLevel = 0
config.phaseUnwrapErrorThreshold = 300
config.enableBurstMode = True
config.setMedianFilter(dai.MedianFilter.KERNEL_5x5)
tof.setInitialConfig(config)
cam_rgb = next(n for n in pipeline.getAllNodes() if isinstance(n, dai.node.Camera))
camControlQueue = cam_rgb.inputControl.createInputQueue()
qRgbd = rgbd.rgbd.createOutputQueue(maxSize=1, blocking=False)
qPcl = rgbd.pcl.createOutputQueue(maxSize=1, blocking=False)
pipeline.start()
ctrl = dai.CameraControl()
ctrl.setAutoExposureLimit(500)
camControlQueue.send(ctrl)
frame_id = 0
while pipeline.isRunning():
rgbdData = qRgbd.get()
pclData = qPcl.get()
rgb = rgbdData.getRGBFrame().getCvFrame()
depth = rgbdData.getDepthFrame().getCvFrame()
depth_vis = cv2.normalize(depth, None, 0, 255, cv2.NORM_MINMAX).astype(np.uint8)
cv2.imshow("RGB", rgb)
cv2.imshow("Depth", depth_vis)
cv2.imwrite(f"{output_dir}/rgb_{frame_id:06d}.png", rgb)
cv2.imwrite(f"{output_dir}/depth_{frame_id:06d}.png", depth)
points, colors = pclData.getPointsRGB()
pcd = o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(points.astype(np.float64))
colors_rgb = np.delete(colors, 3, 1).astype(np.float64) / 255.0
pcd.colors = o3d.utility.Vector3dVector(colors_rgb)
o3d.io.write_point_cloud(f"{output_dir}/pc_{frame_id:06d}.ply", pcd)
frame_id += 1
if cv2.waitKey(1) == 27:
break
I was able to control motion blur for RGB camera using setAutoExposureLimit. I configured the ToF camera based on this link: https://docs.luxonis.com/software-v3/depthai/depthai-components/nodes/tof/. Unfortunately, my depth images and point clouds are still rather noisy even when the camera moves slightly. I have a few questions:
1. rgbd = pipeline.create(dai.node.RGBD).build(
autocreate=True,
mode=dai.node.StereoDepth.PresetMode.DEFAULT,
size=(640, 400)
)
Here the depth and point cloud information comes from the stereo pair or the ToF camera? I would like to use the ToF camera.
2. Is there anything that can be optimized in the code?
3. According to the link, "Sensor/emitter can go up to 160 FPS, which will translte to depth output at either 40 FPS (burst mode enabled) or 80 FPS (burst mode disabled). This is due to different modulation frequencies (80MHz and 100MHz) and the need to combine shuffled/non-shuffled frames to reduce noise." How can I set the frame rate of the ToF camera explicitly to the absolute max? I can't seem to figure that out.