From bd4e35182a37871b177a359e677e202da39d1a15 Mon Sep 17 00:00:00 2001 From: Matic Tonin <77620080+MaticTonin@users.noreply.github.com> Date: Thu, 28 Sep 2023 21:49:05 +0200 Subject: [PATCH 01/12] Adding debug (#1121) * Update requirements * Adding the debug mode to calibrate without camera * Fix bug with paths to boards * Change requirements --------- Co-authored-by: Matevz Morato --- calibrate.py | 67 +++++++++++++++++++++++----------------- resources/depthai_boards | 2 +- 2 files changed, 40 insertions(+), 29 deletions(-) diff --git a/calibrate.py b/calibrate.py index 11854405f..186b2e7ef 100755 --- a/calibrate.py +++ b/calibrate.py @@ -164,6 +164,8 @@ def parse_args(): help="Number of pictures taken.") parser.add_argument('-ebp', '--enablePolygonsDisplay', default=False, action="store_true", help="Enable the display of polynoms.") + parser.add_argument('-dbg', '--debugProcessingMode', default=False, action="store_true", + help="Enable processing of images without using the camera.") options = parser.parse_args() # Set some extra defaults, `-brd` would override them if options.defaultBoard is not None: @@ -185,7 +187,10 @@ def parse_args(): raise argparse.ArgumentTypeError("-s / --squareSizeCm needs to be greater than 2.2 cm") if options.traceLevel == 1: print(f"Charuco board selected is: board_name = {board_name}, numX = {numX}, numY = {numY}, squareSize {options.squareSizeCm} cm, markerSize {options.markerSizeCm} cm") - + if options.debugProcessingMode: + options.mode = "process" + if options.board is None: + raise argparse.ArgumentError(options.board, "Board name (-brd) of camera must be specified in case of using debug mode (-dbg).") return options class HostSync: @@ -350,26 +355,27 @@ def __init__(self): self.output_scale_factor = self.args.outputScaleFactor self.aruco_dictionary = cv2.aruco.Dictionary_get( cv2.aruco.DICT_4X4_1000) - self.device = dai.Device() self.enablePolygonsDisplay = self.args.enablePolygonsDisplay self.board_name = None - cameraProperties = self.device.getConnectedCameraFeatures() - calibData = self.device.readCalibration() - eeprom = calibData.getEepromData() + if not self.args.debugProcessingMode: + self.device = dai.Device() + cameraProperties = self.device.getConnectedCameraFeatures() + calibData = self.device.readCalibration() + eeprom = calibData.getEepromData() #TODO Change only in getDeviceName in next revision. if self.args.board: self.board_name = self.args.board - board_path = Path(self.args.board) + board_path = Path(Path(__file__).parent /self.args.board) if not board_path.exists(): board_path = (Path(__file__).parent / 'resources/depthai_boards/boards' / self.args.board.upper()).with_suffix('.json').resolve() if not board_path.exists(): raise ValueError( - 'Board config not found: {}'.format(board_path)) + 'Board config not found: {}'.format(Path(Path(__file__).parent /self.args.board))) with open(board_path) as fp: self.board_config = json.load(fp) self.board_config = self.board_config['board_config'] self.board_config_backup = self.board_config - else: + elif not self.args.debugProcessingMode: try: detection = self.device.getDeviceName() print(f"Device name: {detection}") @@ -394,7 +400,7 @@ def __init__(self): if "9782" in detection: detection.remove("9782") self.board_name = '-'.join(detection) - board_path = Path(self.board_name) + board_path = Path(Path(__file__).parent /self.board_name) if self.traceLevel == 1: print(f"Board path specified as {board_path}") if not board_path.exists(): @@ -431,18 +437,18 @@ def __init__(self): for cam_id in self.board_config['cameras']: name = self.board_config['cameras'][cam_id]['name'] self.coverageImages[name] = None - - cameraProperties = self.device.getConnectedCameraFeatures() - for properties in cameraProperties: - for in_cam in self.board_config['cameras'].keys(): - cam_info = self.board_config['cameras'][in_cam] - if cam_info["name"] not in self.args.disableCamera: - if properties.socket == stringToCam[in_cam]: - self.board_config['cameras'][in_cam]['sensorName'] = properties.sensorName - print('Cam: {} and focus: {}'.format(cam_info['name'], properties.hasAutofocus)) - self.board_config['cameras'][in_cam]['hasAutofocus'] = properties.hasAutofocus - # self.auto_checkbox_dict[cam_info['name'] + '-Camera-connected'].check() - break + if not self.args.debugProcessingMode: + cameraProperties = self.device.getConnectedCameraFeatures() + for properties in cameraProperties: + for in_cam in self.board_config['cameras'].keys(): + cam_info = self.board_config['cameras'][in_cam] + if cam_info["name"] not in self.args.disableCamera: + if properties.socket == stringToCam[in_cam]: + self.board_config['cameras'][in_cam]['sensorName'] = properties.sensorName + print('Cam: {} and focus: {}'.format(cam_info['name'], properties.hasAutofocus)) + self.board_config['cameras'][in_cam]['hasAutofocus'] = properties.hasAutofocus + # self.auto_checkbox_dict[cam_info['name'] + '-Camera-connected'].check() + break self.charuco_board = cv2.aruco.CharucoBoard_create( self.args.squaresX, self.args.squaresY, @@ -969,7 +975,7 @@ def calibrate(self): self.args.cameraMode, self.args.rectifiedDisp) # Turn off enable disp rectify - if self.args.noInitCalibration: + if self.args.noInitCalibration or self.args.debugProcessingMode: calibration_handler = dai.CalibrationHandler() else: calibration_handler = self.device.readCalibration() @@ -982,7 +988,8 @@ def calibrate(self): calibration_handler.setBoardInfo(str(self.device.getDeviceName()), str(self.args.revision)) except Exception as e: print('Device closed in exception..' ) - self.device.close() + if not self.args.debugProcessingMode: + self.device.close() print(e) print(traceback.format_exc()) raise SystemExit(1) @@ -1067,7 +1074,7 @@ def calibrate(self): calibration_handler.setStereoLeft(stringToCam[cam_info['extrinsics']['to_cam']], result_config['stereo_config']['rectification_left']) target_file.close() - if len(error_text) == 0: + if len(error_text) == 0 and self.args.debugProcessingMode: print('Flashing Calibration data into ') # print(calib_dest_path) @@ -1101,7 +1108,8 @@ def calibrate(self): is_write_factory_sucessful = False if is_write_succesful: - self.device.close() + if not self.args.debugProcessingMode: + self.device.close() text = "EEPROM written succesfully" resImage = create_blank(900, 512, rgb_color=green) cv2.putText(resImage, text, (10, 250), font, 2, (0, 0, 0), 2) @@ -1109,7 +1117,8 @@ def calibrate(self): cv2.waitKey(0) else: - self.device.close() + if not self.args.debugProcessingMode: + self.device.close() text = "EEPROM write Failed!!" resImage = create_blank(900, 512, rgb_color=red) cv2.putText(resImage, text, (10, 250), font, 2, (0, 0, 0), 2) @@ -1118,7 +1127,8 @@ def calibrate(self): # return (False, "EEPROM write Failed!!") else: - self.device.close() + if not self.args.debugProcessingMode: + self.device.close() print(error_text) for text in error_text: # text = error_text[0] @@ -1127,7 +1137,8 @@ def calibrate(self): cv2.imshow("Result Image", resImage) cv2.waitKey(0) except Exception as e: - self.device.close() + if not self.args.debugProcessingMode: + self.device.close() print('Device closed in exception..' ) print(e) print(traceback.format_exc()) diff --git a/resources/depthai_boards b/resources/depthai_boards index 90ccd0506..cce87acb8 160000 --- a/resources/depthai_boards +++ b/resources/depthai_boards @@ -1 +1 @@ -Subproject commit 90ccd05065343fdf04159f6987ec33d239ba7b68 +Subproject commit cce87acb84dcc77cc2ef4ba504adbad77a236b6d From 3f3ea7f20ad8ebfd6e7194d51251b490f9017501 Mon Sep 17 00:00:00 2001 From: Sachin Guruswamy <43363595+saching13@users.noreply.github.com> Date: Tue, 3 Oct 2023 15:50:26 -0700 Subject: [PATCH 02/12] Update calibrate.py --- calibrate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/calibrate.py b/calibrate.py index 186b2e7ef..9d782335d 100755 --- a/calibrate.py +++ b/calibrate.py @@ -1074,7 +1074,7 @@ def calibrate(self): calibration_handler.setStereoLeft(stringToCam[cam_info['extrinsics']['to_cam']], result_config['stereo_config']['rectification_left']) target_file.close() - if len(error_text) == 0 and self.args.debugProcessingMode: + if len(error_text) == 0 and not self.args.debugProcessingMode: print('Flashing Calibration data into ') # print(calib_dest_path) From 3bcb5ec3ce53307615562f4c822125c41be953dc Mon Sep 17 00:00:00 2001 From: Arnaud Lenglet Date: Mon, 16 Oct 2023 11:57:25 +0200 Subject: [PATCH 03/12] fix(IMU): remove wrong arg in oak.visualize() call --- depthai_sdk/examples/IMUComponent/imu.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/depthai_sdk/examples/IMUComponent/imu.py b/depthai_sdk/examples/IMUComponent/imu.py index 3db1d2d6d..a88292b46 100644 --- a/depthai_sdk/examples/IMUComponent/imu.py +++ b/depthai_sdk/examples/IMUComponent/imu.py @@ -5,5 +5,5 @@ imu.config_imu(report_rate=400, batch_report_threshold=5) # DepthAI viewer should open, and IMU data can be viewed on the right-side panel, # under "Stats" tab (right of the "Device Settings" tab). - oak.visualize(imu.out.main, visualizer='viewer') + oak.visualize(imu.out.main) oak.start(blocking=True) From bc07e59709f5985acda23d73b970d45c49502fdb Mon Sep 17 00:00:00 2001 From: hexbabe Date: Mon, 6 Nov 2023 13:31:57 -0500 Subject: [PATCH 04/12] Change root logger implementations to instance-based impl --- .../depthai_sdk/classes/packet_handlers.py | 5 +- .../components/camera_component.py | 8 +- .../depthai_sdk/components/camera_control.py | 84 +++++++++---------- .../depthai_sdk/components/nn_component.py | 14 ++-- .../components/stereo_component.py | 10 +-- .../depthai_sdk/components/stereo_control.py | 24 +++--- .../src/depthai_sdk/integrations/roboflow.py | 8 +- .../integrations/ros/ros2_streaming.py | 4 +- depthai_sdk/src/depthai_sdk/logger.py | 15 ++-- depthai_sdk/src/depthai_sdk/oak_camera.py | 10 +-- .../oak_outputs/xout/xout_disparity.py | 6 +- .../oak_outputs/xout/xout_tracker.py | 4 +- depthai_sdk/src/depthai_sdk/record.py | 7 +- .../depthai_sdk/recorders/mcap_recorder.py | 4 +- .../depthai_sdk/recorders/rosbag_recorder.py | 7 +- .../depthai_sdk/recorders/video_recorder.py | 6 +- depthai_sdk/src/depthai_sdk/replay.py | 9 +- .../trigger_action/actions/record_action.py | 6 +- .../trigger_action/trigger_action.py | 2 +- depthai_sdk/src/depthai_sdk/utils.py | 8 +- .../src/depthai_sdk/visualize/objects.py | 4 +- .../visualizers/opencv_visualizer.py | 4 +- .../visualizers/viewer_visualizer.py | 4 +- 23 files changed, 126 insertions(+), 127 deletions(-) diff --git a/depthai_sdk/src/depthai_sdk/classes/packet_handlers.py b/depthai_sdk/src/depthai_sdk/classes/packet_handlers.py index 6b2a08ae4..faa338212 100644 --- a/depthai_sdk/src/depthai_sdk/classes/packet_handlers.py +++ b/depthai_sdk/src/depthai_sdk/classes/packet_handlers.py @@ -1,4 +1,4 @@ -import logging + import os from abc import abstractmethod from queue import Queue, Empty @@ -8,6 +8,7 @@ from depthai_sdk.classes.packets import BasePacket from depthai_sdk.components.component import Component, ComponentOutput +from depthai_sdk.logger import LOGGER from depthai_sdk.oak_outputs.fps import FPS from depthai_sdk.oak_outputs.syncing import TimestampSync from depthai_sdk.oak_outputs.xout.xout_base import XoutBase, ReplayStream @@ -65,7 +66,7 @@ def configure_syncing(self, """ if enable_sync: if len(self.outputs) < 2: - logging.error('Syncing requires at least 2 outputs! Skipping syncing.') + LOGGER.error('Syncing requires at least 2 outputs! Skipping syncing.') return self.sync = TimestampSync(len(self.outputs), threshold_ms) diff --git a/depthai_sdk/src/depthai_sdk/components/camera_component.py b/depthai_sdk/src/depthai_sdk/components/camera_component.py index 34ae1534a..d84891df0 100644 --- a/depthai_sdk/src/depthai_sdk/components/camera_component.py +++ b/depthai_sdk/src/depthai_sdk/components/camera_component.py @@ -1,4 +1,3 @@ -import logging from typing import Dict from depthai_sdk.classes.enum import ResizeMode @@ -6,6 +5,7 @@ from depthai_sdk.components.camera_helper import * from depthai_sdk.components.component import Component, ComponentOutput from depthai_sdk.components.parser import parse_resolution, parse_encode, encoder_profile_to_fourcc +from depthai_sdk.logger import LOGGER from depthai_sdk.oak_outputs.xout.xout_base import XoutBase, StreamXout, ReplayStream from depthai_sdk.oak_outputs.xout.xout_frames import XoutFrames from depthai_sdk.replay import Replay @@ -297,7 +297,7 @@ def control_with_nn(self, detection_component: 'NNComponent', auto_focus=True, a """ if not auto_focus and not auto_exposure: - logging.error('Attempted to control camera with NN, ' + LOGGER.error('Attempted to control camera with NN, ' 'but both Auto-Focus and Auto-Exposure were disabled! Attempt ignored.') return @@ -337,12 +337,12 @@ def config_color_camera(self, chroma_denoise: Optional[int] = None, ) -> None: if not self.is_color(): - logging.info('Attempted to configure ColorCamera, ' + LOGGER.info('Attempted to configure ColorCamera, ' 'but this component doesn\'t have it. Config attempt ignored.') return if self.is_replay(): - logging.info('Tried configuring ColorCamera, but replaying is enabled. Config attempt ignored.') + LOGGER.info('Tried configuring ColorCamera, but replaying is enabled. Config attempt ignored.') return if interleaved is not None: self.node.setInterleaved(interleaved) diff --git a/depthai_sdk/src/depthai_sdk/components/camera_control.py b/depthai_sdk/src/depthai_sdk/components/camera_control.py index fb871c62d..1d21660ac 100644 --- a/depthai_sdk/src/depthai_sdk/components/camera_control.py +++ b/depthai_sdk/src/depthai_sdk/components/camera_control.py @@ -1,9 +1,7 @@ -import logging from itertools import cycle import depthai as dai - -logger = logging.getLogger(__name__) +from depthai_sdk.logger import LOGGER LIMITS = { 'exposure_compensation': (-9, 9), @@ -53,7 +51,7 @@ def switch_white_balance_mode(self): Switch between auto white balance modes. """ mode = next(self._cycle_awb_mode) - logger.info(f'Setting white balance mode to {mode}.') + LOGGER.info(f'Setting white balance mode to {mode}.') self.send_controls({'white-balance': {'mode': mode}}) def switch_anti_banding_mode(self): @@ -61,7 +59,7 @@ def switch_anti_banding_mode(self): Switch between anti-banding modes. """ mode = next(self._cycle_ab_mode) - logger.info(f'Setting anti-banding mode to {mode}.') + LOGGER.info(f'Setting anti-banding mode to {mode}.') self.send_controls({'ab_mode': mode}) def switch_focus_mode(self): @@ -69,7 +67,7 @@ def switch_focus_mode(self): Switch between focus modes. """ mode = next(self._cycle_af_mode) - logger.info(f'Setting focus mode to {mode}.') + LOGGER.info(f'Setting focus mode to {mode}.') self.send_controls({'focus': {'mode': mode}}) def exposure_time_up(self, step=500): @@ -79,7 +77,7 @@ def exposure_time_up(self, step=500): step: In microseconds """ if LIMITS['exposure'][1] < self._current_vals['exposure_time'] + step: - logger.error(f'Exposure time cannot be greater than {LIMITS["exposure"][1]}') + LOGGER.error(f'Exposure time cannot be greater than {LIMITS["exposure"][1]}') return self._current_vals['exposure_time'] += step self.send_controls( @@ -92,7 +90,7 @@ def exposure_time_down(self, step=500): step: In microseconds """ if LIMITS['exposure'][0] > self._current_vals['exposure_time'] - step: - logger.error(f'Exposure time cannot be less than {LIMITS["exposure"][0]}') + LOGGER.error(f'Exposure time cannot be less than {LIMITS["exposure"][0]}') return self._current_vals['exposure_time'] -= step self.send_controls( @@ -105,7 +103,7 @@ def sensitivity_up(self, step=50): step: In ISO """ if LIMITS['gain'][1] < self._current_vals['sensitivity'] + step: - logger.error(f'Sensitivity cannot be greater than {LIMITS["gain"][1]}') + LOGGER.error(f'Sensitivity cannot be greater than {LIMITS["gain"][1]}') return self._current_vals['sensitivity'] += step self.send_controls( @@ -118,7 +116,7 @@ def sensitivity_down(self, step=50): step: In ISO """ if LIMITS['gain'][0] > self._current_vals['sensitivity'] - step: - logger.error(f'Sensitivity cannot be less than {LIMITS["gain"][0]}') + LOGGER.error(f'Sensitivity cannot be less than {LIMITS["gain"][0]}') return self._current_vals['sensitivity'] -= step self.send_controls( @@ -129,7 +127,7 @@ def focus_up(self, step=3): Increase focus by step. """ if LIMITS['focus'][1] < self._current_vals['focus'] + step: - logger.error(f'Focus cannot be greater than {LIMITS["focus"][1]}') + LOGGER.error(f'Focus cannot be greater than {LIMITS["focus"][1]}') return self._current_vals['focus'] += step self.send_controls({'focus': {'manual': self._current_vals['focus']}}) @@ -139,7 +137,7 @@ def focus_down(self, step=3): Decrease focus by step. """ if LIMITS['focus'][0] > self._current_vals['focus'] - step: - logger.error(f'Focus cannot be less than {LIMITS["focus"][0]}') + LOGGER.error(f'Focus cannot be less than {LIMITS["focus"][0]}') return self._current_vals['focus'] -= step self.send_controls({'focus': {'manual': self._current_vals['focus']}}) @@ -149,7 +147,7 @@ def sharpness_up(self, step=1): Increase sharpness by step """ if LIMITS['sharpness'][1] < self._current_vals['sharpness'] + step: - logger.error(f'Sharpness cannot be greater than {LIMITS["sharpness"][1]}') + LOGGER.error(f'Sharpness cannot be greater than {LIMITS["sharpness"][1]}') return self._current_vals['sharpness'] += step self.send_controls({'isp': {'sharpness': self._current_vals['sharpness']}}) @@ -159,7 +157,7 @@ def sharpness_down(self, step=1): Decrease sharpness by step """ if LIMITS['sharpness'][0] > self._current_vals['sharpness'] - step: - logger.error(f'Sharpness cannot be less than {LIMITS["sharpness"][0]}') + LOGGER.error(f'Sharpness cannot be less than {LIMITS["sharpness"][0]}') return self._current_vals['sharpness'] -= step self.send_controls({'isp': {'sharpness': self._current_vals['sharpness']}}) @@ -169,7 +167,7 @@ def luma_denoise_up(self, step=1): Increase luma denoise by step """ if LIMITS['luma_denoise'][1] < self._current_vals['luma_denoise'] + step: - logger.error(f'Luma denoise cannot be greater than {LIMITS["luma_denoise"][1]}') + LOGGER.error(f'Luma denoise cannot be greater than {LIMITS["luma_denoise"][1]}') return self._current_vals['luma_denoise'] += step self.send_controls({'isp': {'luma_denoise': self._current_vals['luma_denoise']}}) @@ -179,7 +177,7 @@ def luma_denoise_down(self, step=1): Decrease luma denoise by step """ if LIMITS['luma_denoise'][0] > self._current_vals['luma_denoise'] - step: - logger.error(f'Luma denoise cannot be less than {LIMITS["luma_denoise"][0]}') + LOGGER.error(f'Luma denoise cannot be less than {LIMITS["luma_denoise"][0]}') return self._current_vals['luma_denoise'] -= step self.send_controls({'isp': {'luma_denoise': self._current_vals['luma_denoise']}}) @@ -189,7 +187,7 @@ def chroma_denoise_up(self, step=1): Increase chroma denoise by step """ if LIMITS['chroma_denoise'][1] < self._current_vals['chroma_denoise'] + step: - logger.error(f'Chroma denoise cannot be greater than {LIMITS["chroma_denoise"][1]}') + LOGGER.error(f'Chroma denoise cannot be greater than {LIMITS["chroma_denoise"][1]}') return self._current_vals['chroma_denoise'] += step self.send_controls({'isp': {'chroma_denoise': self._current_vals['chroma_denoise']}}) @@ -199,7 +197,7 @@ def chroma_denoise_down(self, step=1): Decrease chroma denoise by step """ if LIMITS['chroma_denoise'][0] > self._current_vals['chroma_denoise'] - step: - logger.error(f'Chroma denoise cannot be less than {LIMITS["chroma_denoise"][0]}') + LOGGER.error(f'Chroma denoise cannot be less than {LIMITS["chroma_denoise"][0]}') return self._current_vals['chroma_denoise'] -= step self.send_controls({'isp': {'chroma_denoise': self._current_vals['chroma_denoise']}}) @@ -242,13 +240,13 @@ def send_controls(self, controls: dict = None): } """ if self.queue is None: - logger.error('Cannot send controls when replaying.') + LOGGER.error('Cannot send controls when replaying.') return ctrl = dai.CameraControl() if controls.get('reset', None) and controls['reset']: - logger.info('Resetting camera controls.') + LOGGER.info('Resetting camera controls.') ctrl.setAntiBandingMode(dai.CameraControl.AntiBandingMode.AUTO) ctrl.setAutoExposureEnable(True) ctrl.setAutoFocusMode(dai.CameraControl.AutoFocusMode.CONTINUOUS_VIDEO) @@ -258,51 +256,51 @@ def send_controls(self, controls: dict = None): if controls.get('exposure', None) is not None: if controls['exposure'].get('auto', False) and controls['exposure']['auto']: - logger.info(f'Setting auto exposure to {controls["exposure"]["auto"]}.') + LOGGER.info(f'Setting auto exposure to {controls["exposure"]["auto"]}.') ctrl.setAutoExposureEnable() if controls['exposure'].get('lock', None) is not None: - logger.info(f'Setting exposure lock to {controls["exposure"]["lock"]}.') + LOGGER.info(f'Setting exposure lock to {controls["exposure"]["lock"]}.') ctrl.setAutoExposureLock(controls['exposure']['lock']) if controls['exposure'].get('region', None) is not None: - # logger.info(f'Setting exposure region to {controls["exposure"]["region"]}.') + # LOGGER.info(f'Setting exposure region to {controls["exposure"]["region"]}.') # ctrl.setAutoExposureRegion(*controls['exposure']['region']) - logger.error('exposure region not yet implemented') + LOGGER.error('exposure region not yet implemented') if controls['exposure'].get('compensation', None) is not None: exp_comp = clamp(controls['exposure']['compensation'], *LIMITS['exposure_compensation']) - logger.info(f'Setting exposure compensation to {exp_comp}.') + LOGGER.info(f'Setting exposure compensation to {exp_comp}.') ctrl.setAutoExposureCompensation(exp_comp) if controls['exposure'].get('manual', None) is not None: exp_time = clamp(controls['exposure']['manual'][0], *LIMITS['exposure']) exp_gain = clamp(controls['exposure']['manual'][1], *LIMITS['gain']) - logger.info(f'Setting exposure to {exp_time}, gain to {exp_gain}.') + LOGGER.info(f'Setting exposure to {exp_time}, gain to {exp_gain}.') ctrl.setManualExposure(exp_time, exp_gain) if controls.get('ab_mode', None) is not None: if isinstance(controls["ab_mode"], str): controls["ab_mode"] = getattr(dai.CameraControl.AntiBandingMode, controls["ab_mode"]) - logger.info(f'Setting anti-banding mode to {controls["ab_mode"]}.') + LOGGER.info(f'Setting anti-banding mode to {controls["ab_mode"]}.') ctrl.setAntiBandingMode(controls["ab_mode"]) if controls.get('focus', None) is not None: if controls['focus'].get('range', None) is not None: - logger.info(f'Setting focus range to {controls["focus"]["range"]}.') + LOGGER.info(f'Setting focus range to {controls["focus"]["range"]}.') ctrl.setAutoFocusLensRange(*controls['focus']['range']) if controls['focus'].get('region', None) is not None: - # logger.info(f'Setting focus region to {controls["focus"]["region"]}.') + # LOGGER.info(f'Setting focus region to {controls["focus"]["region"]}.') # ctrl.setAutoFocusRegion(*controls['focus']['region']) - logger.error('focus region not yet implemented') + LOGGER.error('focus region not yet implemented') if controls['focus'].get('trigger', None) is not None: if controls['focus']['trigger']: - logger.info('Auto-focus triggered.') + LOGGER.info('Auto-focus triggered.') ctrl.setAutoFocusTrigger() if controls['focus'].get('mode', None) is not None: if isinstance(controls["focus"]["mode"], str): controls["focus"]["mode"] = getattr(dai.CameraControl.AutoFocusMode, controls["focus"]["mode"]) - logger.info(f'Setting focus mode to {controls["focus"]["mode"]}.') + LOGGER.info(f'Setting focus mode to {controls["focus"]["mode"]}.') ctrl.setAutoFocusMode(controls["focus"]["mode"]) if controls['focus'].get('manual', None) is not None: focus = clamp(controls['focus']['manual'], *LIMITS['focus']) - logger.info(f'Setting focus to {focus}.') + LOGGER.info(f'Setting focus to {focus}.') ctrl.setManualFocus(focus) if controls.get('white-balance', None) is not None: @@ -310,44 +308,44 @@ def send_controls(self, controls: dict = None): if isinstance(controls["focus"]["mode"], str): controls["white-balance"]["mode"] = getattr(dai.CameraControl.AutoFocusMode, controls["white-balance"]["mode"]) - logger.info(f'Setting white balance mode to {controls["white-balance"]["mode"]}.') + LOGGER.info(f'Setting white balance mode to {controls["white-balance"]["mode"]}.') ctrl.setAutoWhiteBalanceMode(controls["white-balance"]["mode"]) if controls['white-balance'].get('lock', None) is not None: - logger.info(f'Setting white balance lock to {controls["white-balance"]["lock"]}.') + LOGGER.info(f'Setting white balance lock to {controls["white-balance"]["lock"]}.') ctrl.setAutoWhiteBalanceLock(controls['white-balance']['lock']) if controls['white-balance'].get('manual', None) is not None: wb_temp = clamp(controls['white-balance']['manual'], *LIMITS['white_balance']) - logger.info(f'Setting white balance to {wb_temp}.') + LOGGER.info(f'Setting white balance to {wb_temp}.') ctrl.setManualWhiteBalance(wb_temp) if controls.get('isp', None) is not None: if controls['isp'].get('brightness', None) is not None: brightness = clamp(controls['isp']['brightness'], *LIMITS['brightness']) - logger.info(f'Setting brightness to {brightness}.') + LOGGER.info(f'Setting brightness to {brightness}.') ctrl.setBrightness(brightness) if controls['isp'].get('contrast', None) is not None: contrast = clamp(controls['isp']['contrast'], *LIMITS['contrast']) - logger.info(f'Setting contrast to {contrast}.') + LOGGER.info(f'Setting contrast to {contrast}.') ctrl.setContrast(contrast) if controls['isp'].get('saturation', None) is not None: saturation = clamp(controls['isp']['saturation'], *LIMITS['saturation']) - logger.info(f'Setting saturation to {saturation}.') + LOGGER.info(f'Setting saturation to {saturation}.') ctrl.setSaturation(saturation) if controls['isp'].get('sharpness', None) is not None: sharpness = clamp(controls['isp']['sharpness'], *LIMITS['sharpness']) - logger.info(f'Setting sharpness to {sharpness}.') + LOGGER.info(f'Setting sharpness to {sharpness}.') ctrl.setSharpness(sharpness) if controls['isp'].get('luma_denoise', None) is not None: luma_denoise = clamp(controls['isp']['luma_denoise'], *LIMITS['luma_denoise']) - logger.info(f'Setting luma denoise to {luma_denoise}.') + LOGGER.info(f'Setting luma denoise to {luma_denoise}.') ctrl.setLumaDenoise(luma_denoise) if controls['isp'].get('chroma_denoise', None) is not None: chroma_denoise = clamp(controls['isp']['chroma_denoise'], *LIMITS['chroma_denoise']) - logger.info(f'Setting chroma denoise to {chroma_denoise}.') + LOGGER.info(f'Setting chroma denoise to {chroma_denoise}.') ctrl.setChromaDenoise(chroma_denoise) if controls.get('still', None) is not None: - logger.info('Capturing still photo.') + LOGGER.info('Capturing still photo.') ctrl.setCaptureStill(controls['still']) self.queue.send(ctrl) diff --git a/depthai_sdk/src/depthai_sdk/components/nn_component.py b/depthai_sdk/src/depthai_sdk/components/nn_component.py index 6449f9841..bc8e378e2 100644 --- a/depthai_sdk/src/depthai_sdk/components/nn_component.py +++ b/depthai_sdk/src/depthai_sdk/components/nn_component.py @@ -1,5 +1,4 @@ import json -import logging import warnings from collections import defaultdict from pathlib import Path @@ -22,6 +21,7 @@ from depthai_sdk.classes.enum import ResizeMode from depthai_sdk.components.parser import * from depthai_sdk.components.stereo_component import StereoComponent +from depthai_sdk.logger import LOGGER from depthai_sdk.visualize.visualizer_helper import depth_to_disp_factor from depthai_sdk.oak_outputs.xout.xout_base import StreamXout, XoutBase from depthai_sdk.oak_outputs.xout.xout_frames import XoutFrames @@ -178,7 +178,7 @@ def __init__(self, self.node.input.setBlocking(True) self.node.input.setQueueSize(20) else: - logging.debug('Using on-host decoding for multi-stage NN') + LOGGER.debug('Using on-host decoding for multi-stage NN') # Custom NN self.image_manip.setResize(*self._size) self.image_manip.setMaxOutputFrameSize(self._size[0] * self._size[1] * 3) @@ -246,7 +246,7 @@ def _parse_model(self, model): model = models[str(model)] / 'config.json' self._parse_config(model) elif str(model) in zoo_models: - logging.warning( + LOGGER.warning( 'Models from the OpenVINO Model Zoo do not carry any metadata' ' (e.g., label map, decoding logic). Please keep this in mind when using models from Zoo.' ) @@ -322,7 +322,7 @@ def _parse_config(self, model_config: Union[Path, str, Dict]): self._handler = loadModule(model_config.parent / self._config["handler"]) if not callable(getattr(self._handler, "decode", None)): - logging.debug("Custom model handler does not contain 'decode' method!") + LOGGER.debug("Custom model handler does not contain 'decode' method!") else: self._decode_fn = self._handler.decode if self._decode_fn is None else self._decode_fn @@ -410,7 +410,7 @@ def config_multistage_nn(self, num_frame_pool (int, optional): Number of frames to pool for inference. If None, will use the default value. """ if not self.is_multi_stage(): - logging.warning("Input to this model was not a NNComponent, so 2-stage NN inferencing isn't possible!" + LOGGER.warning("Input to this model was not a NNComponent, so 2-stage NN inferencing isn't possible!" "This configuration attempt will be ignored.") return @@ -520,7 +520,7 @@ def config_yolo(self, Configures (Spatial) Yolo Detection Network node. """ if not self.is_yolo(): - logging.warning('This is not a YOLO detection network! This configuration attempt will be ignored.') + LOGGER.warning('This is not a YOLO detection network! This configuration attempt will be ignored.') return if not self.node: @@ -569,7 +569,7 @@ def config_spatial(self, calc_algo (dai.SpatialLocationCalculatorAlgorithm, optional): Specifies spatial location calculator algorithm: Average/Min/Max """ if not self.is_spatial(): - logging.warning('This is not a Spatial Detection network! This configuration attempt will be ignored.') + LOGGER.warning('This is not a Spatial Detection network! This configuration attempt will be ignored.') return if bb_scale_factor is not None: diff --git a/depthai_sdk/src/depthai_sdk/components/stereo_component.py b/depthai_sdk/src/depthai_sdk/components/stereo_component.py index 2b9d7de72..021b2b382 100644 --- a/depthai_sdk/src/depthai_sdk/components/stereo_component.py +++ b/depthai_sdk/src/depthai_sdk/components/stereo_component.py @@ -1,4 +1,3 @@ -import logging import warnings from enum import Enum from typing import Optional, Union, Any, Dict, Tuple, List @@ -12,6 +11,7 @@ from depthai_sdk.components.parser import parse_median_filter, parse_encode, encoder_profile_to_fourcc from depthai_sdk.components.stereo_control import StereoControl from depthai_sdk.components.undistort import _get_mesh +from depthai_sdk.logger import LOGGER from depthai_sdk.oak_outputs.xout.xout_base import XoutBase, StreamXout from depthai_sdk.oak_outputs.xout.xout_depth import XoutDisparityDepth from depthai_sdk.oak_outputs.xout.xout_disparity import XoutDisparity @@ -115,12 +115,12 @@ def __init__(self, laser = laser if laser is not None else 800 if 0 < laser: device.setIrLaserDotProjectorBrightness(laser) - logging.info(f'Setting IR laser dot projector brightness to {laser}mA') + LOGGER.info(f'Setting IR laser dot projector brightness to {laser}mA') led = self._args.get('irFloodBrightness', None) if led is not None: device.setIrFloodLightBrightness(int(led)) - logging.info(f'Setting IR flood LED brightness to {int(led)}mA') + LOGGER.info(f'Setting IR flood LED brightness to {int(led)}mA') input_size = self._get_stream_size(self.left) if input_size: @@ -139,7 +139,7 @@ def __init__(self, manip = pipeline.create(dai.node.ImageManip) new_h = int(h * (1280 / w)) manip.setResize(1280, new_h) - logging.info(f'Input frame size to stereo component was {w}x{h}, added downscalling to 1280x{new_h}') + LOGGER.info(f'Input frame size to stereo component was {w}x{h}, added downscalling to 1280x{new_h}') manip.setMaxOutputFrameSize(1280 * new_h) # Stereo works on GRAY8 frames manip.setFrameType(dai.ImgFrame.Type.GRAY8) @@ -153,7 +153,7 @@ def __init__(self, manip = pipeline.create(dai.node.ImageManip) new_h = int(h * (1280 / w)) manip.setResize(1280, new_h) - logging.info(f'Input frame size to stereo component was {w}x{h}, added downscalling to 1280x{new_h}') + LOGGER.info(f'Input frame size to stereo component was {w}x{h}, added downscalling to 1280x{new_h}') manip.setMaxOutputFrameSize(1280 * new_h) # Stereo works on GRAY8 frames manip.setFrameType(dai.ImgFrame.Type.GRAY8) diff --git a/depthai_sdk/src/depthai_sdk/components/stereo_control.py b/depthai_sdk/src/depthai_sdk/components/stereo_control.py index cf52e688b..2d311127f 100644 --- a/depthai_sdk/src/depthai_sdk/components/stereo_control.py +++ b/depthai_sdk/src/depthai_sdk/components/stereo_control.py @@ -1,9 +1,7 @@ import depthai as dai from itertools import cycle -import logging from depthai_sdk.components.parser import parse_median_filter - -logger = logging.getLogger(__name__) +from depthai_sdk.logger import LOGGER LIMITS = { 'confidence_threshold': (0, 255), @@ -43,7 +41,7 @@ def switch_median_filter(self): Switch between auto white balance modes. """ mode = next(self._cycle_median_filter) - logger.info(f'Switching median filter to {mode}') + LOGGER.info(f'Switching median filter to {mode}') self.send_controls({'postprocessing': {'median': mode}}) def confidence_threshold_up(self, step=10): @@ -51,7 +49,7 @@ def confidence_threshold_up(self, step=10): Increase confidence threshold by step """ if LIMITS['confidence_threshold'][1] < self._current_vals['conf_threshold'] + step: - logger.error(f'Confidence threshold cannot be greater than {LIMITS["confidence_threshold"][1]}') + LOGGER.error(f'Confidence threshold cannot be greater than {LIMITS["confidence_threshold"][1]}') return self._current_vals['conf_threshold'] += step self.send_controls({'cost_matching': {'confidence_threshold': self._current_vals['conf_threshold']}}) @@ -61,7 +59,7 @@ def confidence_threshold_down(self, step=10): Decrease confidence threshold by step """ if LIMITS['confidence_threshold'][0] > self._current_vals['conf_threshold'] - step: - logger.error(f'Confidence threshold cannot be less than {LIMITS["confidence_threshold"][0]}') + LOGGER.error(f'Confidence threshold cannot be less than {LIMITS["confidence_threshold"][0]}') return self._current_vals['conf_threshold'] -= step self.send_controls({'cost_matching': {'confidence_threshold': self._current_vals['conf_threshold']}}) @@ -71,7 +69,7 @@ def dot_projector_up(self, step=50): Increase dot projector power by step """ if LIMITS['dot_projector'][1] < self._current_vals['dot_projector'] + step: - logger.error(f'Dot projector power cannot be greater than {LIMITS["dot_projector"][1]}') + LOGGER.error(f'Dot projector power cannot be greater than {LIMITS["dot_projector"][1]}') return self._current_vals['dot_projector'] += step self.device.setIrFloodLightBrightness(self._current_vals['dot_projector']) @@ -81,7 +79,7 @@ def dot_projector_down(self, step=50): Decrease dot projector power by step """ if LIMITS['dot_projector'][0] > self._current_vals['dot_projector'] - step: - logger.error(f'Dot projector power cannot be less than {LIMITS["dot_projector"][0]}') + LOGGER.error(f'Dot projector power cannot be less than {LIMITS["dot_projector"][0]}') return self._current_vals['dot_projector'] -= step self.device.setIrFloodLightBrightness(self._current_vals['dot_projector']) @@ -91,7 +89,7 @@ def illumination_led_up(self, step=50): Increase illumination led power by step """ if LIMITS['illumination_led'][1] < self._current_vals['illumination_led'] + step: - logger.error(f'Illumination led power cannot be greater than {LIMITS["illumination_led"][1]}') + LOGGER.error(f'Illumination led power cannot be greater than {LIMITS["illumination_led"][1]}') return self._current_vals['illumination_led'] += step self.device.setIrLaserDotProjectorBrightness(self._current_vals['illumination_led']) @@ -101,7 +99,7 @@ def illumination_led_down(self, step=50): Decrease illumination led power by step """ if LIMITS['illumination_led'][0] > self._current_vals['illumination_led'] - step: - logger.error(f'Illumination led power cannot be less than {LIMITS["illumination_led"][0]}') + LOGGER.error(f'Illumination led power cannot be less than {LIMITS["illumination_led"][0]}') return self._current_vals['illumination_led'] -= step self.device.setIrLaserDotProjectorBrightness(self._current_vals['illumination_led']) @@ -183,15 +181,15 @@ def send_controls(self, controls: dict): } """ if self.queue is None: - logger.error('Cannot send controls when replaying.') + LOGGER.error('Cannot send controls when replaying.') return - logger.info(f'Sending controls to StereoDepth node: {controls}') + LOGGER.info(f'Sending controls to StereoDepth node: {controls}') ctrl = dai.StereoDepthConfig() if controls.get('reset', None) and controls['reset']: - logger.info('Resetting camera controls.') + LOGGER.info('Resetting camera controls.') self.raw_cfg = ctrl.get() ctrl.set(self.raw_cfg) self.queue.send(ctrl) diff --git a/depthai_sdk/src/depthai_sdk/integrations/roboflow.py b/depthai_sdk/src/depthai_sdk/integrations/roboflow.py index 40a6e3919..0edf19963 100644 --- a/depthai_sdk/src/depthai_sdk/integrations/roboflow.py +++ b/depthai_sdk/src/depthai_sdk/integrations/roboflow.py @@ -1,10 +1,10 @@ import json -import logging from pathlib import Path from typing import Dict, Optional from zipfile import ZipFile import depthai as dai +from depthai_sdk.logger import LOGGER import requests ROBOFLOW_MODELS = Path.home() / Path('.cache/roboflow-models') @@ -48,9 +48,9 @@ def device_update(self, device: dai.Device) -> Path: raise ValueError("This Roboflow's model is not from YOLO family!") if not str(ret['modelType']).endswith('n'): - logging.info('We recommend using a lighter version of the model to get a better performance!') + LOGGER.info('We recommend using a lighter version of the model to get a better performance!') - logging.info(f"Downloading '{ret['name']}' model from Roboflow server") + LOGGER.info(f"Downloading '{ret['name']}' model from Roboflow server") zip_file_req = requests.get(ret['model']) zip_file_req.raise_for_status() @@ -61,7 +61,7 @@ def device_update(self, device: dai.Device) -> Path: with open(zip_file_path, 'wb') as f: f.write(zip_file_req.content) - logging.info(f"Downloaded the model to {zip_file_path}") + LOGGER.info(f"Downloaded the model to {zip_file_path}") with ZipFile(zip_file_path, 'r') as zObject: # Extract the zip zObject.extractall(str(ROBOFLOW_MODELS / name)) diff --git a/depthai_sdk/src/depthai_sdk/integrations/ros/ros2_streaming.py b/depthai_sdk/src/depthai_sdk/integrations/ros/ros2_streaming.py index f8d4a1a97..0398dc2c4 100644 --- a/depthai_sdk/src/depthai_sdk/integrations/ros/ros2_streaming.py +++ b/depthai_sdk/src/depthai_sdk/integrations/ros/ros2_streaming.py @@ -1,4 +1,3 @@ -import logging from queue import Queue from threading import Thread from typing import Dict, Any @@ -6,6 +5,7 @@ import rclpy from depthai_sdk.integrations.ros.ros_base import RosBase +from depthai_sdk.logger import LOGGER def ros_thread(queue: Queue): @@ -18,7 +18,7 @@ def ros_thread(queue: Queue): for topic, msg in msgs.items(): if topic not in publishers: publishers[topic] = node.create_publisher(type(msg), topic, 10) - logging.info(f'SDK started publishing ROS messages to {topic}') + LOGGER.info(f'SDK started publishing ROS messages to {topic}') publishers[topic].publish(msg) rclpy.spin_once(node, timeout_sec=0.001) # 1ms timeout diff --git a/depthai_sdk/src/depthai_sdk/logger.py b/depthai_sdk/src/depthai_sdk/logger.py index d8893772e..017063d94 100644 --- a/depthai_sdk/src/depthai_sdk/logger.py +++ b/depthai_sdk/src/depthai_sdk/logger.py @@ -2,21 +2,24 @@ __all__ = ['set_logging_level'] +LOGGER = logging.getLogger(__name__) +"""The DepthAI SDK logger.""" def _configure_logger(): """ Configure the logging module. """ - logging.basicConfig(level=logging.INFO, - format='[%(asctime)s] %(levelname)s [%(name)s.%(funcName)s:%(lineno)d] %(message)s', - datefmt='%Y-%m-%d %H:%M:%S') - + handler = logging.StreamHandler() + handler.setLevel(logging.INFO) + formatter = logging.Formatter('[%(asctime)s] %(levelname)s [%(name)s.%(funcName)s:%(lineno)d] %(message)s', datefmt='%Y-%m-%d %H:%M:%S') + handler.setFormatter(formatter) + LOGGER.addHandler(handler) def set_logging_level(level): """ - Set the logging level for the root logger. + Set the logging level for the DepthAI SDK logger. """ - logging.getLogger().setLevel(level) + LOGGER.setLevel(level) _configure_logger() diff --git a/depthai_sdk/src/depthai_sdk/oak_camera.py b/depthai_sdk/src/depthai_sdk/oak_camera.py index d1e9fab51..55e999aa3 100644 --- a/depthai_sdk/src/depthai_sdk/oak_camera.py +++ b/depthai_sdk/src/depthai_sdk/oak_camera.py @@ -1,9 +1,9 @@ -import logging import time import warnings from pathlib import Path from typing import Dict, Any, Optional, List, Union, Callable +from depthai_sdk.logger import LOGGER from depthai_sdk import CV2_HAS_GUI_SUPPORT from depthai_sdk.types import Resolution from depthai_sdk.visualize.visualizer import Visualizer @@ -127,7 +127,7 @@ def __init__(self, if replay is not None: self.replay = Replay(replay) self.replay.initPipeline(self.pipeline) - logging.info(f'Available streams from recording: {self.replay.getStreams()}') + LOGGER.info(f'Available streams from recording: {self.replay.getStreams()}') self._calibration = self._init_calibration() def camera(self, @@ -453,7 +453,7 @@ def __exit__(self, exc_type, exc_value, tb): self.close() def close(self): - logging.info("Closing OAK camera") + LOGGER.info("Closing OAK camera") if self.replay: self.replay.close() @@ -503,7 +503,7 @@ def start(self, blocking=False): # self._polling.append() if self._pipeine_graph is not None: self._pipeine_graph.create_graph(self.pipeline.serializeToJson()['pipeline'], self.device) - logging.info('Pipeline graph process started') + LOGGER.info('Pipeline graph process started') # Call on_pipeline_started() for each component for comp in self._components: @@ -691,5 +691,5 @@ def _init_calibration(self) -> dai.CalibrationHandler: else: calibration = self.device.readCalibration() if calibration is None: - logging.warning("No calibration data found on the device or in replay") + LOGGER.warning("No calibration data found on the device or in replay") return calibration diff --git a/depthai_sdk/src/depthai_sdk/oak_outputs/xout/xout_disparity.py b/depthai_sdk/src/depthai_sdk/oak_outputs/xout/xout_disparity.py index 80bf7f28f..2424e96eb 100644 --- a/depthai_sdk/src/depthai_sdk/oak_outputs/xout/xout_disparity.py +++ b/depthai_sdk/src/depthai_sdk/oak_outputs/xout/xout_disparity.py @@ -1,5 +1,4 @@ import itertools -import logging import warnings from collections import defaultdict from typing import List, Optional, Dict @@ -8,6 +7,7 @@ import numpy as np from depthai_sdk.classes.packets import DisparityPacket +from depthai_sdk.logger import LOGGER from depthai_sdk.oak_outputs.xout.xout_base import StreamXout from depthai_sdk.oak_outputs.xout.xout_frames import XoutFrames from depthai_sdk.oak_outputs.xout.xout_seq_sync import XoutSeqSync @@ -56,7 +56,7 @@ def __init__(self, self.use_wls_filter = wls_config['enabled'] if wls_config else False if self.use_wls_filter: wls_level = wls_config['level'] - logging.debug( + LOGGER.debug( f'Using WLS level: {wls_level.name} (lambda: {wls_level.value[0]}, sigma: {wls_level.value[1]})' ) self.wls_lambda = wls_level.value[0] or wls_config['lambda'] @@ -151,7 +151,7 @@ def _ir_grid_search_iteration(self, frame: np.array, candidate_pairs: list = Non self._auto_ir_converged = True self._checking_neighbourhood = False - logging.debug(f'Auto IR converged: dot projector - {self._dot_projector_brightness}mA, ' + LOGGER.debug(f'Auto IR converged: dot projector - {self._dot_projector_brightness}mA, ' f'flood - {self._flood_brightness}mA') else: self._dot_projector_brightness, self._flood_brightness = candidate_pairs[candidate_idx] diff --git a/depthai_sdk/src/depthai_sdk/oak_outputs/xout/xout_tracker.py b/depthai_sdk/src/depthai_sdk/oak_outputs/xout/xout_tracker.py index ecd989d5f..03e89e0d2 100644 --- a/depthai_sdk/src/depthai_sdk/oak_outputs/xout/xout_tracker.py +++ b/depthai_sdk/src/depthai_sdk/oak_outputs/xout/xout_tracker.py @@ -1,4 +1,3 @@ -import logging import math from datetime import timedelta from typing import Dict, Optional, List, Union, Tuple @@ -8,6 +7,7 @@ from depthai_sdk.classes import TrackerPacket from depthai_sdk.classes.packets import TrackingDetection +from depthai_sdk.logger import LOGGER from depthai_sdk.oak_outputs.xout.xout_base import StreamXout from depthai_sdk.oak_outputs.xout.xout_nn import XoutNnResults from depthai_sdk.tracking import KalmanFilter @@ -213,6 +213,6 @@ def __read_device_calibration(self, device: dai.Device): fov = calib.getFov(calib.getStereoLeftCameraId()) self.focal = (cam_info.width / 2) / (2. * math.tan(math.radians(fov / 2))) else: - logging.warning("Calibration data missing, using OAK-D defaults") + LOGGER.warning("Calibration data missing, using OAK-D defaults") self.baseline = 75 self.focal = 440 diff --git a/depthai_sdk/src/depthai_sdk/record.py b/depthai_sdk/src/depthai_sdk/record.py index 97869447c..54666f206 100644 --- a/depthai_sdk/src/depthai_sdk/record.py +++ b/depthai_sdk/src/depthai_sdk/record.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -import logging from enum import IntEnum from pathlib import Path from queue import Queue @@ -9,10 +8,10 @@ import depthai as dai from depthai_sdk.classes.packets import FramePacket, IMUPacket +from depthai_sdk.logger import LOGGER from depthai_sdk.oak_outputs.xout.xout_frames import XoutFrames from depthai_sdk.recorders.abstract_recorder import Recorder - def _run(recorder: Recorder, frame_queue: Queue): """ Start recording infinite loop @@ -30,7 +29,7 @@ def _run(recorder: Recorder, frame_queue: Queue): break # Close all recorders - Can't use ExitStack with VideoWriter recorder.close() - logging.info('Exiting store frame thread') + LOGGER.info('Exiting store frame thread') class RecordType(IntEnum): @@ -112,7 +111,7 @@ def start(self, device: dai.Device, xouts: List[XoutFrames]): # TODO: support pointclouds in MCAP def config_mcap(self, pointcloud: bool): if self.record_type != RecordType.MCAP: - logging.info(f"Recorder type is {self.record_type}, not MCAP! Config attempt ignored.") + LOGGER.info(f"Recorder type is {self.record_type}, not MCAP! Config attempt ignored.") return self.recorder.set_pointcloud(pointcloud) diff --git a/depthai_sdk/src/depthai_sdk/recorders/mcap_recorder.py b/depthai_sdk/src/depthai_sdk/recorders/mcap_recorder.py index 5988e7c32..1368279e0 100644 --- a/depthai_sdk/src/depthai_sdk/recorders/mcap_recorder.py +++ b/depthai_sdk/src/depthai_sdk/recorders/mcap_recorder.py @@ -1,10 +1,10 @@ -import logging from pathlib import Path from typing import Dict import depthai as dai from mcap_ros1.writer import Writer as Ros1Writer +from depthai_sdk.logger import LOGGER from depthai_sdk.integrations.ros.ros_base import RosBase # from depthai_sdk.integrations.ros.depthai2ros import DepthAi2Ros1 from depthai_sdk.oak_outputs.xout.xout_frames import XoutFrames @@ -88,4 +88,4 @@ def close(self) -> None: self._closed = True self.ros_writer.finish() self.stream.close() - logging.info(f'.MCAP recording saved at {self.path}') + LOGGER.info(f'.MCAP recording saved at {self.path}') diff --git a/depthai_sdk/src/depthai_sdk/recorders/rosbag_recorder.py b/depthai_sdk/src/depthai_sdk/recorders/rosbag_recorder.py index 72d868380..1cd475521 100755 --- a/depthai_sdk/src/depthai_sdk/recorders/rosbag_recorder.py +++ b/depthai_sdk/src/depthai_sdk/recorders/rosbag_recorder.py @@ -2,7 +2,6 @@ This is a helper class that let's you save depth frames into rosbag (.bag), which can be replayed using RealSense Viewer app. ''' import datetime -import logging import os import time from pathlib import Path @@ -31,9 +30,9 @@ from rosbags.typesys.types import diagnostic_msgs__msg__KeyValue as KeyValue -from depthai_sdk.recorders.abstract_recorder import Recorder - +from depthai_sdk.logger import LOGGER from depthai_sdk.integrations.ros.imu_interpolation import ImuInterpolation, ImuSyncMethod +from depthai_sdk.recorders.abstract_recorder import Recorder CAMERA_INFO = """ # This message defines meta information for a camera. It should be in a @@ -415,7 +414,7 @@ def write(self, name: str, dai_msg: dai.Buffer): def close(self): if self._closed: return self._closed = True - logging.info(f'ROS .bag saved at: {str(self.path)}') + LOGGER.info(f'ROS .bag saved at: {str(self.path)}') self.writer.close() # def write_streamInfo(self, depth=False, rgb=False): diff --git a/depthai_sdk/src/depthai_sdk/recorders/video_recorder.py b/depthai_sdk/src/depthai_sdk/recorders/video_recorder.py index 1e183cbd7..88b43d8eb 100644 --- a/depthai_sdk/src/depthai_sdk/recorders/video_recorder.py +++ b/depthai_sdk/src/depthai_sdk/recorders/video_recorder.py @@ -1,9 +1,9 @@ -import logging from typing import Union, Dict import numpy as np from .abstract_recorder import * +from depthai_sdk.logger import LOGGER class VideoRecorder(Recorder): @@ -57,7 +57,7 @@ def update(self, path: Path, device: dai.Device, xouts: List['XoutFrames']): self._writers[xout_name] = AvWriter(self.path, file_name, fourcc) except Exception as e: # TODO here can be other errors, not only import error - logging.warning(f'Exception while creating AvWriter: {e}.' + LOGGER.warning(f'Exception while creating AvWriter: {e}.' '\nFalling back to FileWriter, saving uncontainerized encoded streams.') from .video_writers.file_writer import FileWriter self._writers[xout_name] = FileWriter(self.path, file_name, fourcc) @@ -104,7 +104,7 @@ def close(self): if self._closed: return self._closed = True - logging.info(f'Video Recorder saved stream(s) to folder: {str(self.path)}') + LOGGER.info(f'Video Recorder saved stream(s) to folder: {str(self.path)}') # Close opened files for name, writer in self._writers.items(): writer.close() diff --git a/depthai_sdk/src/depthai_sdk/replay.py b/depthai_sdk/src/depthai_sdk/replay.py index 8bfc48c66..549b24d48 100644 --- a/depthai_sdk/src/depthai_sdk/replay.py +++ b/depthai_sdk/src/depthai_sdk/replay.py @@ -8,6 +8,7 @@ import depthai as dai from depthai_sdk.classes.enum import ResizeMode +from depthai_sdk.logger import LOGGER from depthai_sdk.readers.abstract_reader import AbstractReader from depthai_sdk.utils import * @@ -22,7 +23,7 @@ def _run(delay: float, sendFrames: Callable): if not sendFrames(): break time.sleep(delay) - logging.info('Replay `run` thread stopped') + LOGGER.info('Replay `run` thread stopped') class ReplayStream: @@ -172,7 +173,7 @@ def _get_path(self, path: str) -> Path: dic = getAvailableRecordings() if recording_name in dic: arr = dic[recording_name] - logging.info("Downloading depthai recording '{}' from Luxonis' servers, in total {:.2f} MB" + LOGGER.info("Downloading depthai recording '{}' from Luxonis' servers, in total {:.2f} MB" .format(recording_name, arr[1] / 1e6)) path = downloadRecording(recording_name, arr[0]) return path @@ -240,14 +241,14 @@ def disableStream(self, stream_name: str, disableReading: bool = False): self.reader.disableStream(stream_name) if stream_name.lower() not in self.streams: - logging.info(f"There's no stream '{stream_name}' available!") + LOGGER.info(f"There's no stream '{stream_name}' available!") return self.streams[stream_name.lower()].disabled = True def specify_socket(self, stream_name: str, socket: dai.CameraBoardSocket): if stream_name.lower() not in self.streams: - logging.info(f"There's no stream '{stream_name}' available!") + LOGGER.info(f"There's no stream '{stream_name}' available!") return self.streams[stream_name.lower()].camera_socket = socket diff --git a/depthai_sdk/src/depthai_sdk/trigger_action/actions/record_action.py b/depthai_sdk/src/depthai_sdk/trigger_action/actions/record_action.py index e249fe33d..78a9e7868 100644 --- a/depthai_sdk/src/depthai_sdk/trigger_action/actions/record_action.py +++ b/depthai_sdk/src/depthai_sdk/trigger_action/actions/record_action.py @@ -1,4 +1,3 @@ -import logging import time from datetime import timedelta, datetime from pathlib import Path @@ -9,6 +8,7 @@ from depthai_sdk.classes import FramePacket from depthai_sdk.components import Component +from depthai_sdk.logger import LOGGER from depthai_sdk.recorders.video_recorder import VideoRecorder from depthai_sdk.trigger_action.actions.abstract_action import Action @@ -91,7 +91,7 @@ def _run(self): time.sleep(0.01) # Close files - logging.debug(f'Saved to {str(self.path / subfolder)}') + LOGGER.debug(f'Saved to {str(self.path / subfolder)}') self.recorder.close_files() # Call on_finish_callback if it is specified @@ -146,7 +146,7 @@ def on_new_packets(self, packets: Dict[str, FramePacket]): def setup(self, device: dai.Device, xouts: List['XoutFrames']): self.stream_names = [xout.name for xout in xouts] # e.g., [color_video, color_bitstream] - logging.debug(f'RecordAction: stream_names = {self.stream_names}') + LOGGER.debug(f'RecordAction: stream_names = {self.stream_names}') self.recorder.update(self.path, device, xouts) self._run_thread() diff --git a/depthai_sdk/src/depthai_sdk/trigger_action/trigger_action.py b/depthai_sdk/src/depthai_sdk/trigger_action/trigger_action.py index a9db8afc8..4c60fde18 100644 --- a/depthai_sdk/src/depthai_sdk/trigger_action/trigger_action.py +++ b/depthai_sdk/src/depthai_sdk/trigger_action/trigger_action.py @@ -1,9 +1,9 @@ -import logging from datetime import datetime from typing import Union, Callable from depthai_sdk.classes import FramePacket from depthai_sdk.oak_outputs.syncing import SequenceNumSync +from depthai_sdk.logger import LOGGER from depthai_sdk.trigger_action.actions.abstract_action import Action from depthai_sdk.trigger_action.triggers.abstract_trigger import Trigger diff --git a/depthai_sdk/src/depthai_sdk/utils.py b/depthai_sdk/src/depthai_sdk/utils.py index 58ae3bc43..c367c3cd4 100644 --- a/depthai_sdk/src/depthai_sdk/utils.py +++ b/depthai_sdk/src/depthai_sdk/utils.py @@ -1,6 +1,5 @@ import importlib import json -import logging import sys import tempfile import traceback @@ -14,6 +13,7 @@ cv2 = None import depthai as dai +from depthai_sdk.logger import LOGGER import numpy as np import requests import xmltodict @@ -394,7 +394,7 @@ def _create_cache_folder() -> bool: try: Path.home().joinpath(".depthai_sdk").mkdir(parents=True, exist_ok=True) except PermissionError: - logging.debug('Failed to create cache folder.') + LOGGER.debug('Failed to create cache folder.') return False return True @@ -408,7 +408,7 @@ def _create_config() -> Optional[dict]: dict: Config file content. """ if not _create_cache_folder(): - logging.debug('Failed to create config file.') + LOGGER.debug('Failed to create config file.') return None config_file = Path.home().joinpath('.depthai_sdk', 'config.json') @@ -481,7 +481,7 @@ def report_crash_dump(device: dai.Device) -> None: json.dump(crash_dump_json, f) with configure_scope() as scope: - logging.info('Reporting crash dump to sentry.') + LOGGER.info('Reporting crash dump to sentry.') scope.add_attachment(content_type='application/json', path=str(path)) capture_exception(CrashDumpException()) diff --git a/depthai_sdk/src/depthai_sdk/visualize/objects.py b/depthai_sdk/src/depthai_sdk/visualize/objects.py index e7d19704b..651d86ef4 100644 --- a/depthai_sdk/src/depthai_sdk/visualize/objects.py +++ b/depthai_sdk/src/depthai_sdk/visualize/objects.py @@ -1,4 +1,3 @@ -import logging import math from abc import ABC, abstractmethod from collections import defaultdict @@ -9,6 +8,7 @@ import numpy as np from depthai import ImgDetection +from depthai_sdk.logger import LOGGER from depthai_sdk.visualize.bbox import BoundingBox from depthai_sdk.visualize.configs import VisConfig, BboxStyle, TextPosition @@ -233,7 +233,7 @@ def prepare(self) -> 'VisDetections': # Get normalized bounding box normalized_bbox = self.normalizer.get_relative_bbox(BoundingBox(detection)) if len(self.frame_shape) < 2: - logging.debug(f'Visualizer: skipping detection because frame shape is invalid: {self.frame_shape}') + LOGGER.debug(f'Visualizer: skipping detection because frame shape is invalid: {self.frame_shape}') return self # TODO can normalize accept frame shape? diff --git a/depthai_sdk/src/depthai_sdk/visualize/visualizers/opencv_visualizer.py b/depthai_sdk/src/depthai_sdk/visualize/visualizers/opencv_visualizer.py index ca204a39b..601003051 100644 --- a/depthai_sdk/src/depthai_sdk/visualize/visualizers/opencv_visualizer.py +++ b/depthai_sdk/src/depthai_sdk/visualize/visualizers/opencv_visualizer.py @@ -1,10 +1,10 @@ -import logging from typing import Optional import cv2 import numpy as np from depthai_sdk.classes.packets import DisparityPacket, FramePacket +from depthai_sdk.logger import LOGGER from depthai_sdk.visualize.configs import TextPosition from depthai_sdk.visualize.objects import ( VisBoundingBox, @@ -86,7 +86,7 @@ def show(self, packet) -> None: elif isinstance(packet, FramePacket): frame = packet.decode() else: - logging.warning(f'Unknown packet type: {type(packet)}') + LOGGER.warning(f'Unknown packet type: {type(packet)}') return if frame is not None: diff --git a/depthai_sdk/src/depthai_sdk/visualize/visualizers/viewer_visualizer.py b/depthai_sdk/src/depthai_sdk/visualize/visualizers/viewer_visualizer.py index 90f788005..2d6ae3d96 100644 --- a/depthai_sdk/src/depthai_sdk/visualize/visualizers/viewer_visualizer.py +++ b/depthai_sdk/src/depthai_sdk/visualize/visualizers/viewer_visualizer.py @@ -1,4 +1,3 @@ -import logging import subprocess import sys @@ -7,6 +6,7 @@ from depthai_viewer.components.rect2d import RectFormat from depthai_sdk.classes.packets import FramePacket, IMUPacket, PointcloudPacket +from depthai_sdk.logger import LOGGER from depthai_sdk.visualize.objects import ( VisBoundingBox, VisCircle, @@ -42,7 +42,7 @@ def __init__(self, scale, fps): raise Exception(f"DepthAI Viewer is not installed. " f"Please run '{sys.executable} -m pip install depthai_viewer' to install it.") else: - logging.exception(f"Error occurred while trying to run depthai_viewer: {err_msg}") + LOGGER.exception(f"Error occurred while trying to run depthai_viewer: {err_msg}") else: print("depthai_viewer ran successfully.") except subprocess.TimeoutExpired: From 44165539bbb727d17db75d749dd9d0ccad79c05e Mon Sep 17 00:00:00 2001 From: Erol444 Date: Mon, 5 Feb 2024 11:18:23 +0200 Subject: [PATCH 05/12] Updated lib version, updated depthai-demo a bit so it doesn't throw warnings --- depthai_demo.py | 5 +++-- depthai_sdk/requirements.txt | 2 +- requirements.txt | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/depthai_demo.py b/depthai_demo.py index 691a89880..41a2a3d36 100755 --- a/depthai_demo.py +++ b/depthai_demo.py @@ -206,7 +206,8 @@ def setup(self, conf: ConfigManager): self._nnManager.countLabel(self._conf.getCountLabel(self._nnManager)) self._pm.setNnManager(self._nnManager) - self._device = dai.Device(self._pm.pipeline.getOpenVINOVersion(), self._deviceInfo, usb2Mode=self._conf.args.usbSpeed == "usb2") + maxUsbSpeed = dai.UsbSpeed.HIGH if self._conf.args.usbSpeed == "usb2" else dai.UsbSpeed.SUPER + self._device = dai.Device(self._pm.pipeline.getOpenVINOVersion(), self._deviceInfo, maxUsbSpeed) self._device.addLogCallback(self._logMonitorCallback) if sentryEnabled: try: @@ -288,7 +289,7 @@ def run(self): if self._conf.useCamera: cameras = self._device.getConnectedCameras() - if dai.CameraBoardSocket.LEFT in cameras and dai.CameraBoardSocket.RIGHT in cameras: + if dai.CameraBoardSocket.CAM_B in cameras and dai.CameraBoardSocket.CAM_C in cameras: self._pv.collectCalibData(self._device) self._updateCameraConfigs({ diff --git a/depthai_sdk/requirements.txt b/depthai_sdk/requirements.txt index 01580b840..a4b309dd8 100644 --- a/depthai_sdk/requirements.txt +++ b/depthai_sdk/requirements.txt @@ -4,7 +4,7 @@ opencv-contrib-python>4 blobconverter>=1.4.1 pytube>=12.1.0 --extra-index-url https://artifacts.luxonis.com/artifactory/luxonis-python-snapshot-local/ -depthai==2.22.0 +depthai==2.24.0 PyTurboJPEG==1.6.4 marshmallow==3.17.0 xmltodict diff --git a/requirements.txt b/requirements.txt index 59a73c082..5be95088c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,6 +6,6 @@ depthai-sdk==1.9.4 --extra-index-url https://artifacts.luxonis.com/artifactory/luxonis-depthai-data-local/wheels/ pyqt5>5,<5.15.6 ; platform_machine != "armv6l" and platform_machine != "armv7l" and platform_machine != "aarch64" and platform_machine != "arm64" --extra-index-url https://artifacts.luxonis.com/artifactory/luxonis-python-snapshot-local/ -depthai==2.21.2.0 +depthai==2.24.0.0 Qt.py scipy \ No newline at end of file From 706ecc3f8a7290b5e2749afe706ebf259f0bd7c5 Mon Sep 17 00:00:00 2001 From: Erol444 Date: Mon, 5 Feb 2024 11:43:37 +0200 Subject: [PATCH 06/12] Try to fix windows tests --- .github/workflows/test_install_requirements.yml | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test_install_requirements.yml b/.github/workflows/test_install_requirements.yml index 56ba8e41f..45b1ace27 100644 --- a/.github/workflows/test_install_requirements.yml +++ b/.github/workflows/test_install_requirements.yml @@ -91,9 +91,18 @@ - name: Download chocolatey shell: pwsh run: Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')) - - name: Install dependencies + - name: Install cmake dependency shell: pwsh - run: choco install cmake git python --version 3.10 pycharm-community -y + run: choco install cmake -y + - name: Install git dependency + shell: pwsh + run: choco install git -y + - name: Install python dependency + shell: pwsh + run: choco install python --version 3.10 -y + - name: Install pycharm-community dependency + shell: pwsh + run: choco install pycharm-community -y - name: Install requrirements run: | python install_requirements.py From c50e2174443b271d3eb941b1896322e2c7295059 Mon Sep 17 00:00:00 2001 From: Erol444 Date: Mon, 5 Feb 2024 12:23:34 +0200 Subject: [PATCH 07/12] Force install python version for windows tests --- .github/workflows/test_install_requirements.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_install_requirements.yml b/.github/workflows/test_install_requirements.yml index 45b1ace27..874deb3f0 100644 --- a/.github/workflows/test_install_requirements.yml +++ b/.github/workflows/test_install_requirements.yml @@ -99,7 +99,7 @@ run: choco install git -y - name: Install python dependency shell: pwsh - run: choco install python --version 3.10 -y + run: choco install python --version 3.10 --force -y - name: Install pycharm-community dependency shell: pwsh run: choco install pycharm-community -y From 6210b02a0aa3e51af11bc82744c140c79f48013a Mon Sep 17 00:00:00 2001 From: jakaskerl <53253318+jakaskerl@users.noreply.github.com> Date: Mon, 5 Feb 2024 19:27:19 +0100 Subject: [PATCH 08/12] Fixing windows tests - removed already installed packages: (https://github.com/actions/runner-images/blob/main/images/windows/Windows2022-Readme.md) --- .github/workflows/test_install_requirements.yml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/.github/workflows/test_install_requirements.yml b/.github/workflows/test_install_requirements.yml index 874deb3f0..4dab13002 100644 --- a/.github/workflows/test_install_requirements.yml +++ b/.github/workflows/test_install_requirements.yml @@ -91,15 +91,6 @@ - name: Download chocolatey shell: pwsh run: Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')) - - name: Install cmake dependency - shell: pwsh - run: choco install cmake -y - - name: Install git dependency - shell: pwsh - run: choco install git -y - - name: Install python dependency - shell: pwsh - run: choco install python --version 3.10 --force -y - name: Install pycharm-community dependency shell: pwsh run: choco install pycharm-community -y From a7049c01e7de803ab6f7f053db697e82743796c7 Mon Sep 17 00:00:00 2001 From: jakaskerl <53253318+jakaskerl@users.noreply.github.com> Date: Wed, 7 Feb 2024 19:02:33 +0100 Subject: [PATCH 09/12] Update sdk_sync_multiple_outputs.rst Fixing link to example. --- .../docs/source/samples/mixed/sdk_sync_multiple_outputs.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/depthai_sdk/docs/source/samples/mixed/sdk_sync_multiple_outputs.rst b/depthai_sdk/docs/source/samples/mixed/sdk_sync_multiple_outputs.rst index d24fa89f9..c26f8d040 100644 --- a/depthai_sdk/docs/source/samples/mixed/sdk_sync_multiple_outputs.rst +++ b/depthai_sdk/docs/source/samples/mixed/sdk_sync_multiple_outputs.rst @@ -34,8 +34,8 @@ Source Code Also `available on GitHub `__ - .. literalinclude:: ../../../../examples/CameraComponent/sync_multiple_outputs.py + .. literalinclude:: ../../../../examples/mixed/sync_multiple_outputs.py :language: python :linenos: -.. include:: /includes/footer-short.rst \ No newline at end of file +.. include:: /includes/footer-short.rst From 46c72266e156a3d435b1d42c87c90eb798eab011 Mon Sep 17 00:00:00 2001 From: dlaflotte Date: Thu, 8 Feb 2024 23:51:51 -0500 Subject: [PATCH 10/12] Allow use of prior cached model Moving the requests.get(url) below the check for cache. If your vision system is offline, and you have a cached model, the check prior to checking cache throws an exception. Now if you have a cached model it will use that first and only if you dont have a model will it switch to checking api.roboflow.com --- depthai_sdk/src/depthai_sdk/integrations/roboflow.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/depthai_sdk/src/depthai_sdk/integrations/roboflow.py b/depthai_sdk/src/depthai_sdk/integrations/roboflow.py index 0edf19963..3564e05a7 100644 --- a/depthai_sdk/src/depthai_sdk/integrations/roboflow.py +++ b/depthai_sdk/src/depthai_sdk/integrations/roboflow.py @@ -27,9 +27,6 @@ def _file_with_ext(self, folder: Path, ext: str) -> Optional[Path]: def device_update(self, device: dai.Device) -> Path: mxid = device.getMxId() - url = f"https://api.roboflow.com/depthai/{self.config['model']}/?api_key={self.config['key']}&device={mxid}" - response = requests.get(url) - name = self.config['model'].replace('/', '_') # '/' isn't valid folder name model_folder = ROBOFLOW_MODELS / name @@ -37,6 +34,11 @@ def device_update(self, device: dai.Device) -> Path: if json_file: return json_file + #Check the URL after checking the cache to make sure vision systems that are offline don't throw an exception + url = f"https://api.roboflow.com/depthai/{self.config['model']}/?api_key={self.config['key']}&device={mxid}" + response = requests.get(url) + + json_res = response.json() if "error" in json_res: raise Exception(json_res['error']) From c252143a0fb4d6854d999b3d168c6749c6ce3295 Mon Sep 17 00:00:00 2001 From: Riccardo Grieco Date: Tue, 9 Apr 2024 17:48:05 +0200 Subject: [PATCH 11/12] Fix reference to StereoDepth node in docs --- depthai_sdk/docs/source/components/stereo_component.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/depthai_sdk/docs/source/components/stereo_component.rst b/depthai_sdk/docs/source/components/stereo_component.rst index 9e8cddedb..12817acfb 100644 --- a/depthai_sdk/docs/source/components/stereo_component.rst +++ b/depthai_sdk/docs/source/components/stereo_component.rst @@ -1,7 +1,7 @@ StereoComponent =============== -:class:`StereoComponent ` abstracts `StereoDepth `__ node, its configuration, +:class:`StereoComponent ` abstracts `StereoDepth `__ node, its configuration, filtering (eg. `WLS filter `__), and disparity/depth viewing. Usage @@ -35,4 +35,4 @@ Reference .. autoclass:: depthai_sdk.components.StereoComponent :members: - :undoc-members: \ No newline at end of file + :undoc-members: From 933d57580e41d07aabf5e16748206264a39b867d Mon Sep 17 00:00:00 2001 From: Filip Jenko <130547420+FilipJenko@users.noreply.github.com> Date: Wed, 5 Jun 2024 14:40:00 +0200 Subject: [PATCH 12/12] Launcher update (#1178) * removed the option for choosing demo, instead running the viewer directly * removed the option for choosing demo, instead running the viewer directly * reverting changes in choose_app_dialog.py --- launcher/launcher.py | 74 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 72 insertions(+), 2 deletions(-) diff --git a/launcher/launcher.py b/launcher/launcher.py index c967be123..1498c9427 100644 --- a/launcher/launcher.py +++ b/launcher/launcher.py @@ -123,7 +123,8 @@ def showCritical(self, title, message): def __init__(self, parent = None): QtCore.QThread.__init__(self, parent) self.signalUpdateQuestion[str, str].connect(self.updateQuestion, QtCore.Qt.BlockingQueuedConnection) - self.signalChooseApp.connect(self.chooseApp, QtCore.Qt.BlockingQueuedConnection) + # Commented out for running the viewer directly, without the option of choosing demo + #self.signalChooseApp.connect(self.chooseApp, QtCore.Qt.BlockingQueuedConnection) self.signalCloseSplash.connect(self.closeSplash, QtCore.Qt.BlockingQueuedConnection) self.sigInfo[str, str].connect(self.showInformation, QtCore.Qt.BlockingQueuedConnection) self.sigCritical[str, str].connect(self.showCritical, QtCore.Qt.BlockingQueuedConnection) @@ -324,7 +325,7 @@ def run(self): print(f'Message Box ({title}): {message}') # TODO(themarpe) - could be made optional, if the following raise and message self.sigWarning.emit(title, message) - + ''' try: self.signalChooseApp.emit() # Set to quit splash screen a little after subprocess is ran @@ -434,7 +435,76 @@ def removeSplash(): pass finally: quitThread.join() + ''' + ### Replaced above commented code with below code unitl ### + # No option of choosing demo, running the viewer directly + try: + # Set to quit splash screen a little after subprocess is ran + def removeSplash(): + time.sleep(2.5) + self.signalCloseSplash.emit() + quitThread = threading.Thread(target=removeSplash) + quitThread.start() + + print("Launching DepthAI Viewer.") + # Check if depthai-viewer is installed + is_viewer_installed_cmd = [sys.executable, "-m", "pip", "show", "depthai-viewer"] + viewer_available_ret = subprocess.run(is_viewer_installed_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + if viewer_available_ret.returncode != 0: + splashScreen.updateSplashMessage('Installing DepthAI Viewer ...') + splashScreen.enableHeartbeat(True) + print("DepthAI Viewer not installed, installing...") + # DepthAI Viewer isn't installed, install it + # First upgrade pip + subprocess.run([sys.executable, "-m", "pip", "install", "-U", "pip"], check=True) + # Install depthai-viewer - Don't check, it can error out because of dependency conflicts but still install successfully + subprocess.run([sys.executable, "-m", "pip", "install", "depthai-viewer"]) + # Check again if depthai-viewer is installed + viewer_available_ret = subprocess.run(is_viewer_installed_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + if viewer_available_ret.returncode != 0: + raise RuntimeError("DepthAI Viewer failed to install.") + splashScreen.updateSplashMessage('') + splashScreen.enableHeartbeat(False) + viewer_version = version.parse(viewer_available_ret.stdout.decode().splitlines()[1].split(" ")[1].strip()) + print(f"Installed DepthAI Viewer version: {viewer_version}") + # Get latest depthai-viewer version + latest_ret = subprocess.run([sys.executable, "-m", "pip", "index", "versions", "depthai-viewer"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + if latest_ret.returncode != 0: + raise RuntimeError("Couldn't get latest depthai-viewer version.") + latest_viewer_version = version.parse(latest_ret.stdout.decode().split("LATEST:")[1].strip()) + print(f"Latest DepthAI Viewer version: {latest_viewer_version}") + if latest_viewer_version > viewer_version: + # Update is available, ask user if they want to update + title = 'DepthAI Viewer update available' + message = f'Version {str(latest_viewer_version)} of depthai-viewer is available, current version {str(viewer_version)}. Would you like to update?' + self.signalUpdateQuestion.emit(title, message) + if self.shouldUpdate: + splashScreen.updateSplashMessage(f'Updating DepthAI Viewer to version {latest_viewer_version} ...') + splashScreen.enableHeartbeat(True) + # Update depthai-viewer + subprocess.run([sys.executable, "-m", "pip", "install", "-U", "depthai-viewer"]) + # Test again to see if viewer is installed and updated + viewer_available_ret = subprocess.run(is_viewer_installed_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + if viewer_available_ret.returncode != 0: + raise RuntimeError(f"Installing version {latest_viewer_version} failed.") + viewer_version = version.parse(viewer_available_ret.stdout.decode().splitlines()[1].split(" ")[1].strip()) + if latest_viewer_version > viewer_version: + raise RuntimeError("DepthAI Viewer failed to update.") + splashScreen.updateSplashMessage('') + splashScreen.enableHeartbeat(False) + + # All ready, run the depthai-viewer as a seperate process + ret = subprocess.run([sys.executable, "-m", "depthai_viewer"]) + except Exception as ex: + print(f'Exception: {ex}') + title = 'Exception' + message = f'Unable to start the DepthAI Viewer.\nException: {ex}' + print(f'Message Box ({title}): {message}') + self.sigCritical.emit(title, message) + finally: + quitThread.join() + ### except Exception as ex: # Catch all for any kind of an error print(f'Unknown error occured ({ex}), exiting...')