Skip to content

Commit

Permalink
Added ToF configuration function, support ToF depth from pointcloud, …
Browse files Browse the repository at this point in the history
…pin numpy below 2.0, depthai-sdk to 1.15
  • Loading branch information
Erol444 committed Jun 25, 2024
1 parent 2160cf3 commit 29ca479
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 30 deletions.
4 changes: 2 additions & 2 deletions depthai_sdk/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
numpy>=1.19; python_version < "3.7"
numpy>=1.21; python_version >= "3.7"
numpy>=1.19,<2.0.0; python_version < "3.7"
numpy>=1.21,<2.0.0; python_version >= "3.7"
opencv-contrib-python>4
blobconverter>=1.4.1
pytube>=12.1.0
Expand Down
2 changes: 1 addition & 1 deletion depthai_sdk/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

setup(
name='depthai-sdk',
version='1.13.1',
version='1.15.0',
description='This package provides an abstraction of the DepthAI API library.',
long_description=io.open("README.md", encoding="utf-8").read(),
long_description_content_type="text/markdown",
Expand Down
9 changes: 9 additions & 0 deletions depthai_sdk/src/depthai_sdk/classes/packets.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,15 @@ def get_sequence_num(self) -> int:
def get_timestamp(self) -> timedelta:
return self.depth_map.getTimestampDevice()

def crop_points(self, bb: BoundingBox) -> np.ndarray:
"""
Crop points to the bounding box
Returns: Cropped section of the point cloud
"""
x1, y1, x2, y2 = bb.to_tuple(self.points.shape)
return self.points[y1:y2, x1:x2]


class SpatialBbMappingPacket(DisparityDepthPacket):
"""
Expand Down
5 changes: 4 additions & 1 deletion depthai_sdk/src/depthai_sdk/components/nn_component.py
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,10 @@ def config_nn(self,
self._change_resize_mode(self._ar_resize_mode)

if conf_threshold is not None and self.is_detector():
self.node.setConfidenceThreshold(conf_threshold)
if 0 <= conf_threshold <= 1:
self.node.setConfidenceThreshold(conf_threshold)
else:
raise ValueError("Confidence threshold must be between 0 and 1!")

def config_spatial(self,
bb_scale_factor: Optional[float] = None,
Expand Down
29 changes: 16 additions & 13 deletions depthai_sdk/src/depthai_sdk/components/pointcloud_component.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from depthai_sdk.components.camera_component import CameraComponent
from depthai_sdk.components.component import Component, ComponentOutput
from depthai_sdk.components.stereo_component import StereoComponent
from depthai_sdk.components.tof_component import ToFComponent
from depthai_sdk.oak_outputs.xout.xout_base import XoutBase, StreamXout
from depthai_sdk.oak_outputs.xout.xout_pointcloud import XoutPointcloud
from depthai_sdk.replay import Replay
Expand All @@ -15,7 +16,7 @@ class PointcloudComponent(Component):
def __init__(self,
device: dai.Device,
pipeline: dai.Pipeline,
stereo: Union[None, StereoComponent, dai.node.StereoDepth, dai.Node.Output] = None,
depth_input: Union[None, StereoComponent, ToFComponent, dai.node.StereoDepth, dai.Node.Output] = None,
colorize: Optional[CameraComponent] = None,
replay: Optional[Replay] = None,
args: Any = None):
Expand All @@ -28,15 +29,14 @@ def __init__(self,
super().__init__()
self.out = self.Out(self)

self.stereo_depth_node: dai.node.StereoDepth
self.depth: dai.Node.Output # Depth node output
self.depth: dai.Node.Output # depth output

self.colorize_comp: Optional[CameraComponent] = colorize

self._replay: Optional[Replay] = replay

# Depth aspect
if stereo is None:
if depth_input is None:
stereo = StereoComponent(device, pipeline, replay=replay, args=args)
stereo.config_stereo(lr_check=True, subpixel=True, subpixel_bits=3, confidence=230)
stereo.node.initialConfig.setNumInvalidateEdgePixels(20)
Expand All @@ -58,15 +58,18 @@ def __init__(self,
# Align to colorize node
stereo.config_stereo(align=self.colorize_comp)

if isinstance(stereo, StereoComponent):
stereo = stereo.node

if isinstance(stereo, dai.node.StereoDepth):
self.stereo_depth_node = stereo
self.depth = stereo.depth
elif isinstance(stereo, dai.Node.Output):
self.stereo_depth_node = stereo.getParent()
self.depth = stereo
if isinstance(depth_input, StereoComponent):
depth_input = stereo.node
elif isinstance(depth_input, ToFComponent):
if depth_input._align is not None:
self.depth = depth_input._align.outputAligned
else:
self.depth = depth_input.node.depth

if isinstance(depth_input, dai.node.StereoDepth):
self.depth = depth_input.depth
elif isinstance(depth_input, dai.Node.Output):
self.depth = depth_input

def config_postprocessing(self) -> None:
"""
Expand Down
41 changes: 32 additions & 9 deletions depthai_sdk/src/depthai_sdk/components/tof_component.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import List, Optional, Union
from typing import List, Optional, Union, Tuple

import depthai as dai

Expand All @@ -21,6 +21,7 @@ def __init__(
pipeline: dai.Pipeline,
source: Union[str, dai.CameraBoardSocket, None] = None,
align_to: Optional[CameraComponent] = None,
fps: Optional[int] = None,
):
super().__init__()
self.out = self.Out(self)
Expand All @@ -40,17 +41,19 @@ def __init__(
self.camera_node.setBoardSocket(source)
self.camera_socket = source

self.node = pipeline.create(dai.node.ToF)
if fps is not None:
self.camera_node.setFps(fps)

self.node: dai.node.ToF = pipeline.create(dai.node.ToF)
self._control_in = pipeline.create(dai.node.XLinkIn)
self.camera_node.raw.link(self.node.input)
self._control_in.setStreamName(f"{self.node.id}_inputControl")
self._control_in.out.link(self.node.inputConfig)

self._align_to_output: dai.Node.Output = None

if align_to is not None:
self._align = pipeline.create(dai.node.ImageAlign)
self._align_to_output = align_to.node.isp
self.node.depth.link(self._align.input)
self._align_to_output.link(self._align.inputAlignTo)
self.set_align_to(align_to)

def _find_tof(self, device: dai.Device) -> dai.CameraBoardSocket:
# Use the first ToF sensor, usually, there will only be one
Expand All @@ -62,14 +65,34 @@ def _find_tof(self, device: dai.Device) -> dai.CameraBoardSocket:
f"No ToF sensor found on this camera! {device.getConnectedCameraFeatures()}"
)

def set_align_to(self, align_to: CameraComponent) -> None:
def set_align_to(self, align_to: CameraComponent, output_size: Optional[Tuple] = None) -> None:
if self._align is None:
self._align = self._pipeline.create(dai.node.ImageAlign)
self.node.depth.link(self._align.input)
if align_to.is_mono():
align_to.node.out.link(self._align.inputAlignTo)
self._align_to_output = align_to.node.out
else:
align_to.node.isp.link(self._align.inputAlignTo)
self._align_to_output = align_to.node.isp

self._align_to_output.link(self._align.inputAlignTo)

if output_size is not None:
self._align.setOutputSize(*output_size)


def configure_tof(self,
phaseShuffleTemporalFilter: bool = None,
phaseUnwrappingLevel: int = None,
phaseUnwrapErrorThreshold: int = None,
) -> None:
tofConfig = self.node.initialConfig.get()
if phaseShuffleTemporalFilter is not None:
tofConfig.enablePhaseShuffleTemporalFilter = phaseShuffleTemporalFilter
if phaseUnwrappingLevel is not None:
tofConfig.phaseUnwrappingLevel = phaseUnwrappingLevel
if phaseUnwrapErrorThreshold is not None:
tofConfig.phaseUnwrapErrorThreshold = phaseUnwrapErrorThreshold
self.node.initialConfig.set(tofConfig)

def on_pipeline_started(self, device: dai.Device) -> None:
self.control.set_input_queue(
Expand Down
13 changes: 9 additions & 4 deletions depthai_sdk/src/depthai_sdk/oak_camera.py
Original file line number Diff line number Diff line change
Expand Up @@ -390,14 +390,19 @@ def create_stereo(self,
"""
return self.stereo(resolution, fps, left, right, encode)

def create_tof(self, source: Union[str, dai.CameraBoardSocket, None] = None, align_to: Optional[CameraComponent] = None) -> ToFComponent:
def create_tof(self,
source: Union[str, dai.CameraBoardSocket, None] = None,
fps: Optional[float] = None,
align_to: Optional[CameraComponent] = None) -> ToFComponent:
"""
Create ToF component.
Args:
source (str / dai.CameraBoardSocket): ToF camera source
fps (float): Sensor FPS
align_to (CameraComponent): Align ToF to this camera component
"""
comp = ToFComponent(self.device, self.pipeline, source, align_to)
comp = ToFComponent(self.device, self.pipeline, source, align_to, fps)
self._components.append(comp)
return comp

Expand All @@ -410,7 +415,7 @@ def create_imu(self) -> IMUComponent:
return comp

def create_pointcloud(self,
stereo: Union[None, StereoComponent, dai.node.StereoDepth, dai.Node.Output] = None,
depth_input: Union[None, StereoComponent, ToFComponent, dai.node.StereoDepth, dai.Node.Output] = None,
colorize: Union[None, CameraComponent, dai.node.MonoCamera, dai.node.ColorCamera, dai.Node.Output, bool] = None,
) -> PointcloudComponent:

Expand All @@ -427,7 +432,7 @@ def create_pointcloud(self,
comp = PointcloudComponent(
self.device,
self.pipeline,
stereo=stereo,
depth_input=depth_input,
colorize=colorize,
replay=self.replay,
args=self._args,
Expand Down

0 comments on commit 29ca479

Please sign in to comment.