diff --git a/depthai_sdk/src/depthai_sdk/components/camera_component.py b/depthai_sdk/src/depthai_sdk/components/camera_component.py index 4122c9375..d304bfcae 100644 --- a/depthai_sdk/src/depthai_sdk/components/camera_component.py +++ b/depthai_sdk/src/depthai_sdk/components/camera_component.py @@ -106,6 +106,13 @@ def __init__(self, "Please specify sensor type with c/color or m/mono after the ','" " - eg. `cam = oak.create_camera('cama,c')`" ) + elif source in ["COLOR", "RGB"]: + for features in device.getConnectedCameraFeatures(): + if dai.CameraSensorType.COLOR in features.supportedTypes: + source = features.socket + break + if not isinstance(source, dai.CameraBoardSocket): + raise ValueError("Couldn't find a color camera!") socket = parse_camera_socket(source) sensor = [f for f in device.getConnectedCameraFeatures() if f.socket == socket][0] diff --git a/depthai_sdk/src/depthai_sdk/components/stereo_component.py b/depthai_sdk/src/depthai_sdk/components/stereo_component.py index 9f6f7608d..7367c34b5 100644 --- a/depthai_sdk/src/depthai_sdk/components/stereo_component.py +++ b/depthai_sdk/src/depthai_sdk/components/stereo_component.py @@ -127,7 +127,7 @@ def __init__(self, if self._device.getDeviceName() == 'OAK-D-LR': self._resolution = dai.MonoCameraProperties.SensorResolution.THE_1200_P - if not self.left: + if not self.left: # Should never happen self.left = CameraComponent(device, pipeline, 'left', self._resolution, self._fps, replay=self._replay) if not self.right: self.right = CameraComponent(device, pipeline, 'right', self._resolution, self._fps, diff --git a/depthai_sdk/src/depthai_sdk/oak_camera.py b/depthai_sdk/src/depthai_sdk/oak_camera.py index a701d194f..562f3aebc 100644 --- a/depthai_sdk/src/depthai_sdk/oak_camera.py +++ b/depthai_sdk/src/depthai_sdk/oak_camera.py @@ -22,7 +22,7 @@ from depthai_sdk.components.component import Component from depthai_sdk.components.imu_component import IMUComponent from depthai_sdk.components.nn_component import NNComponent -from depthai_sdk.components.parser import parse_usb_speed +from depthai_sdk.components.parser import parse_usb_speed, parse_camera_socket from depthai_sdk.components.stereo_component import StereoComponent from depthai_sdk.components.pointcloud_component import PointcloudComponent from depthai_sdk.oak_device import OakDevice @@ -109,16 +109,16 @@ def __init__(self, self.replay = Replay(replay) self.replay.initPipeline(self.pipeline) logging.info(f'Available streams from recording: {self.replay.getStreams()}') - - def create_camera(self, - source: Union[str, dai.CameraBoardSocket], - resolution: Optional[Union[ - str, dai.ColorCameraProperties.SensorResolution, dai.MonoCameraProperties.SensorResolution - ]] = None, - fps: Optional[float] = None, - encode: Union[None, str, bool, dai.VideoEncoderProperties.Profile] = None, - name: Optional[str] = None, - ) -> CameraComponent: + + def camera(self, + source: Union[str, dai.CameraBoardSocket], + resolution: Optional[Union[ + str, dai.ColorCameraProperties.SensorResolution, dai.MonoCameraProperties.SensorResolution + ]] = None, + fps: Optional[float] = None, + encode: Union[None, str, bool, dai.VideoEncoderProperties.Profile] = None, + name: Optional[str] = None, + ) -> CameraComponent: """ Creates Camera component. This abstracts ColorCamera/MonoCamera nodes and supports mocking the camera when recording is passed during OakCamera initialization. Mocking the camera will send frames from the host to the @@ -131,6 +131,13 @@ def create_camera(self, encode (bool/str/Profile): Whether we want to enable video encoding (accessible via cameraComponent.out_encoded). If True, it will use MJPEG name (str): Name used to identify the X-out stream. This name will also be associated with the frame in the callback function. """ + socket = source + if isinstance(source, str): + socket = parse_camera_socket(source.split(",")[0]) + for comp in self._components: + if isinstance(comp, CameraComponent) and comp.node.getBoardSocket() == socket: + return comp + comp = CameraComponent(self._oak.device, self.pipeline, source=source, @@ -144,13 +151,38 @@ def create_camera(self, self._components.append(comp) return comp - def create_all_cameras(self, - resolution: Optional[Union[ + def create_camera(self, + source: Union[str, dai.CameraBoardSocket], + resolution: Optional[Union[ str, dai.ColorCameraProperties.SensorResolution, dai.MonoCameraProperties.SensorResolution ]] = None, - fps: Optional[float] = None, - encode: Union[None, str, bool, dai.VideoEncoderProperties.Profile] = None, - ) -> List[CameraComponent]: + fps: Optional[float] = None, + encode: Union[None, str, bool, dai.VideoEncoderProperties.Profile] = None, + name: Optional[str] = None, + ) -> CameraComponent: + """ + Deprecated, use camera() instead. + + Creates Camera component. This abstracts ColorCamera/MonoCamera nodes and supports mocking the camera when + recording is passed during OakCamera initialization. Mocking the camera will send frames from the host to the + OAK device (via XLinkIn node). + + Args: + source (str / dai.CameraBoardSocket): Camera source + resolution (str/SensorResolution): Sensor resolution of the camera. + fps (float): Sensor FPS + encode (bool/str/Profile): Whether we want to enable video encoding (accessible via cameraComponent.out_encoded). If True, it will use MJPEG + name (str): Name used to identify the X-out stream. This name will also be associated with the frame in the callback function. + """ + return self.camera(source, resolution, fps, encode, name) + + def all_cameras(self, + resolution: Optional[Union[ + str, dai.ColorCameraProperties.SensorResolution, dai.MonoCameraProperties.SensorResolution + ]] = None, + fps: Optional[float] = None, + encode: Union[None, str, bool, dai.VideoEncoderProperties.Profile] = None, + ) -> List[CameraComponent]: """ Creates Camera component for each camera sensors on the OAK camera. @@ -177,6 +209,25 @@ def create_all_cameras(self, self._components.extend(components) return components + def create_all_cameras(self, + resolution: Optional[Union[ + str, dai.ColorCameraProperties.SensorResolution, + dai.MonoCameraProperties.SensorResolution + ]] = None, + fps: Optional[float] = None, + encode: Union[None, str, bool, dai.VideoEncoderProperties.Profile] = None, + ) -> List[CameraComponent]: + """ + Deprecated, use all_cameras() instead. + + Creates Camera component for each camera sensors on the OAK camera. + + Args: + resolution (str/SensorResolution): Sensor resolution of the camera. + fps (float): Sensor FPS + encode (bool/str/Profile): Whether we want to enable video encoding (accessible via cameraComponent.out_encoded). If True, it will use MJPEG + """ + return self.all_cameras(resolution, fps, encode) def create_nn(self, model: Union[str, Dict, Path], @@ -213,14 +264,14 @@ def create_nn(self, self._components.append(comp) return comp - def create_stereo(self, - resolution: Union[None, str, dai.MonoCameraProperties.SensorResolution] = None, - fps: Optional[float] = None, - left: Union[None, dai.Node.Output, CameraComponent] = None, # Left mono camera - right: Union[None, dai.Node.Output, CameraComponent] = None, # Right mono camera - name: Optional[str] = None, - encode: Union[None, str, bool, dai.VideoEncoderProperties.Profile] = None - ) -> StereoComponent: + def stereo(self, + resolution: Union[None, str, dai.MonoCameraProperties.SensorResolution] = None, + fps: Optional[float] = None, + left: Union[None, dai.Node.Output, CameraComponent] = None, # Left mono camera + right: Union[None, dai.Node.Output, CameraComponent] = None, # Right mono camera + name: Optional[str] = None, + encode: Union[None, str, bool, dai.VideoEncoderProperties.Profile] = None + ) -> StereoComponent: """ Create Stereo camera component. If left/right cameras/component aren't specified they will get created internally. @@ -232,6 +283,11 @@ def create_stereo(self, name (str): Name used to identify the X-out stream. This name will also be associated with the frame in the callback function. encode (bool/str/Profile): Whether we want to enable video encoding (accessible via StereoComponent.out.encoded). If True, it will use h264 codec. """ + if left is None: + left = self.camera(source=dai.CameraBoardSocket.LEFT, resolution=resolution, fps=fps) + if right is None: + right = self.camera(source=dai.CameraBoardSocket.RIGHT, resolution=resolution, fps=fps) + comp = StereoComponent(self._oak.device, self.pipeline, resolution=resolution, @@ -245,6 +301,29 @@ def create_stereo(self, self._components.append(comp) return comp + def create_stereo(self, + resolution: Union[None, str, dai.MonoCameraProperties.SensorResolution] = None, + fps: Optional[float] = None, + left: Union[None, dai.Node.Output, CameraComponent] = None, # Left mono camera + right: Union[None, dai.Node.Output, CameraComponent] = None, # Right mono camera + name: Optional[str] = None, + encode: Union[None, str, bool, dai.VideoEncoderProperties.Profile] = None + ) -> StereoComponent: + """ + Deprecated, use stereo() instead. + + Create Stereo camera component. If left/right cameras/component aren't specified they will get created internally. + + Args: + resolution (str/SensorResolution): If monochrome cameras aren't already passed, create them and set specified resolution + fps (float): If monochrome cameras aren't already passed, create them and set specified FPS + left (CameraComponent/dai.node.MonoCamera): Pass the camera object (component/node) that will be used for stereo camera. + right (CameraComponent/dai.node.MonoCamera): Pass the camera object (component/node) that will be used for stereo camera. + name (str): Name used to identify the X-out stream. This name will also be associated with the frame in the callback function. + encode (bool/str/Profile): Whether we want to enable video encoding (accessible via StereoComponent.out.encoded). If True, it will use h264 codec. + """ + return self.stereo(resolution, fps, left, right, name, encode) + def create_imu(self) -> IMUComponent: """ Create IMU component