visiongraph.input.BaseDepthCamera
1from abc import ABC, abstractmethod 2from argparse import ArgumentParser, Namespace, ArgumentError 3from typing import Tuple, Optional 4 5import cv2 6import numpy as np 7 8from visiongraph.input.BaseCamera import BaseCamera 9from visiongraph.input.BaseDepthInput import BaseDepthInput 10from visiongraph.model.CameraStreamType import CameraStreamType 11from visiongraph.util import MathUtils 12 13 14class BaseDepthCamera(BaseCamera, BaseDepthInput, ABC): 15 """ 16 Abstract base class for depth cameras that handle both color and depth input streams. 17 """ 18 19 def __init__(self): 20 """ 21 Initializes the BaseDepthCamera with default settings. 22 """ 23 super().__init__() 24 self.use_infrared = False 25 26 def configure(self, args: Namespace): 27 """ 28 Configures the camera settings based on command line arguments. 29 30 :param args: The command line arguments namespace. 31 """ 32 super().configure(args) 33 self.use_infrared = args.infrared 34 35 def _calculate_depth_coordinates(self, x: float, y: float, width: int, height: int) -> Tuple[int, int]: 36 """ 37 Calculates depth coordinates from given normalized coordinates. 38 39 :param x: The x coordinate (normalized). 40 :param y: The y coordinate (normalized). 41 :param width: The width of the image. 42 :param height: The height of the image. 43 44 :return: The calculated pixel coordinates (ix, iy). 45 """ 46 x, y = MathUtils.transform_coordinates(x, y, self.rotate, self.flip) 47 48 if self.crop is not None: 49 norm_crop = self.crop.scale(1.0 / width, 1.0 / height) 50 x = MathUtils.map_value(x, 0.0, 1.0, norm_crop.x_min, norm_crop.x_max) 51 y = MathUtils.map_value(y, 0.0, 1.0, norm_crop.y_min, norm_crop.y_max) 52 53 ix, iy = width * x, height * y 54 55 ix = round(MathUtils.constrain(ix, upper=width - 1)) 56 iy = round(MathUtils.constrain(iy, upper=height - 1)) 57 58 return ix, iy 59 60 @staticmethod 61 def _colorize( 62 image: np.ndarray, 63 clipping_range: Tuple[Optional[int], Optional[int]] = (None, None), 64 colormap: Optional[int] = None, 65 ) -> np.ndarray: 66 """ 67 Colorizes a depth image within a specified clipping range. 68 69 :param image: The image to colorize. 70 :param clipping_range: The clipping range for normalization. 71 :param colormap: The OpenCV colormap to apply. 72 73 :return: The colorized image. 74 """ 75 if clipping_range[0] is not None and clipping_range[1] is not None: 76 low, high = clipping_range 77 delta = high - low 78 79 img = image.clip(low, high) 80 img = (((img - low) / delta) * 255).astype(np.uint8) 81 else: 82 img = image 83 img = cv2.normalize(img, None, 0, 255, cv2.NORM_MINMAX, dtype=cv2.CV_8U) 84 85 if colormap is not None: 86 img = cv2.applyColorMap(img, colormap) 87 return img 88 89 @abstractmethod 90 def pre_process_image( 91 self, image: np.ndarray, stream_type: CameraStreamType = CameraStreamType.Color 92 ) -> Optional[np.ndarray]: 93 """ 94 Pre-processes the input image based on the stream type. 95 96 :param image: The image to be pre-processed. 97 :param stream_type: The type of the camera stream (default is CameraStreamType.Color). 98 99 :return: The pre-processed image or None if unprocessable. 100 """ 101 return image 102 103 @abstractmethod 104 def get_raw_image(self, stream_type: CameraStreamType = CameraStreamType.Color) -> Optional[np.ndarray]: 105 """ 106 Retrieves the raw image from the camera based on the stream type. 107 108 :param stream_type: The type of the camera stream (default is CameraStreamType.Color). 109 110 :return: The raw image or None if unavailable. 111 """ 112 pass 113 114 def get_image( 115 self, 116 stream_type: CameraStreamType = CameraStreamType.Color, 117 pre_processed: bool = True, 118 post_processed: bool = True, 119 ) -> Optional[np.ndarray]: 120 """ 121 Retrieves and processes the image from the camera stream. 122 123 :param stream_type: The type of the camera stream (default is CameraStreamType.Color). 124 :param pre_processed: Whether to pre-process the image (default is True). 125 :param post_processed: Whether to post-process the image (default is True). 126 127 :return: The processed image or None if unavailable. 128 """ 129 frame = self.get_raw_image(stream_type) 130 131 if frame is None: 132 return None 133 134 # apply camera pre-processing 135 if pre_processed: 136 frame = self.pre_process_image(frame, stream_type) 137 138 # apply base camera post-processing 139 if post_processed: 140 _, frame = self._post_process(0, frame) 141 return frame 142 143 return frame 144 145 @property 146 def color_image(self) -> Optional[np.ndarray]: 147 """ 148 Returns the processed color image. 149 150 :return: The processed color image or None if unavailable. 151 """ 152 return self.get_image(CameraStreamType.Color, True, True) 153 154 @property 155 def depth_image(self) -> Optional[np.ndarray]: 156 """ 157 Returns the processed depth image. 158 159 :return: The processed depth image or None if unavailable. 160 """ 161 return self.get_image(CameraStreamType.Depth, True, True) 162 163 @property 164 def infrared_image(self) -> Optional[np.ndarray]: 165 """ 166 Returns the processed infrared image. 167 168 :return: The processed infrared image or None if unavailable. 169 """ 170 return self.get_image(CameraStreamType.Infrared, True, True) 171 172 @property 173 def raw_color_image(self) -> Optional[np.ndarray]: 174 """ 175 Returns the raw color image from the camera. 176 177 :return: The raw color image or None if unavailable. 178 """ 179 return self.get_raw_image(CameraStreamType.Color) 180 181 @property 182 def raw_depth_image(self) -> Optional[np.ndarray]: 183 """ 184 Returns the raw depth image from the camera. 185 186 :return: The raw depth image or None if unavailable. 187 """ 188 return self.get_raw_image(CameraStreamType.Depth) 189 190 @property 191 def raw_infrared_image(self) -> Optional[np.ndarray]: 192 """ 193 Returns the raw infrared image from the camera. 194 195 :return: The raw infrared image or None if unavailable. 196 """ 197 return self.get_raw_image(CameraStreamType.Infrared) 198 199 @staticmethod 200 def add_params(parser: ArgumentParser): 201 """ 202 Adds camera-specific parameters to the argument parser. 203 204 :param parser: The argument parser instance. 205 """ 206 super(BaseDepthCamera, BaseDepthCamera).add_params(parser) 207 BaseDepthInput.add_params(parser) 208 209 try: 210 parser.add_argument("-ir", "--infrared", action="store_true", help="Use infrared as input stream.") 211 except ArgumentError as ex: 212 if ex.message.startswith("conflicting"): 213 return 214 raise ex 215 216 @property 217 def is_playback(self) -> bool: 218 """ 219 Indicates whether the camera is in playback mode. 220 221 :return: False since this is a real-time camera. 222 """ 223 return False
15class BaseDepthCamera(BaseCamera, BaseDepthInput, ABC): 16 """ 17 Abstract base class for depth cameras that handle both color and depth input streams. 18 """ 19 20 def __init__(self): 21 """ 22 Initializes the BaseDepthCamera with default settings. 23 """ 24 super().__init__() 25 self.use_infrared = False 26 27 def configure(self, args: Namespace): 28 """ 29 Configures the camera settings based on command line arguments. 30 31 :param args: The command line arguments namespace. 32 """ 33 super().configure(args) 34 self.use_infrared = args.infrared 35 36 def _calculate_depth_coordinates(self, x: float, y: float, width: int, height: int) -> Tuple[int, int]: 37 """ 38 Calculates depth coordinates from given normalized coordinates. 39 40 :param x: The x coordinate (normalized). 41 :param y: The y coordinate (normalized). 42 :param width: The width of the image. 43 :param height: The height of the image. 44 45 :return: The calculated pixel coordinates (ix, iy). 46 """ 47 x, y = MathUtils.transform_coordinates(x, y, self.rotate, self.flip) 48 49 if self.crop is not None: 50 norm_crop = self.crop.scale(1.0 / width, 1.0 / height) 51 x = MathUtils.map_value(x, 0.0, 1.0, norm_crop.x_min, norm_crop.x_max) 52 y = MathUtils.map_value(y, 0.0, 1.0, norm_crop.y_min, norm_crop.y_max) 53 54 ix, iy = width * x, height * y 55 56 ix = round(MathUtils.constrain(ix, upper=width - 1)) 57 iy = round(MathUtils.constrain(iy, upper=height - 1)) 58 59 return ix, iy 60 61 @staticmethod 62 def _colorize( 63 image: np.ndarray, 64 clipping_range: Tuple[Optional[int], Optional[int]] = (None, None), 65 colormap: Optional[int] = None, 66 ) -> np.ndarray: 67 """ 68 Colorizes a depth image within a specified clipping range. 69 70 :param image: The image to colorize. 71 :param clipping_range: The clipping range for normalization. 72 :param colormap: The OpenCV colormap to apply. 73 74 :return: The colorized image. 75 """ 76 if clipping_range[0] is not None and clipping_range[1] is not None: 77 low, high = clipping_range 78 delta = high - low 79 80 img = image.clip(low, high) 81 img = (((img - low) / delta) * 255).astype(np.uint8) 82 else: 83 img = image 84 img = cv2.normalize(img, None, 0, 255, cv2.NORM_MINMAX, dtype=cv2.CV_8U) 85 86 if colormap is not None: 87 img = cv2.applyColorMap(img, colormap) 88 return img 89 90 @abstractmethod 91 def pre_process_image( 92 self, image: np.ndarray, stream_type: CameraStreamType = CameraStreamType.Color 93 ) -> Optional[np.ndarray]: 94 """ 95 Pre-processes the input image based on the stream type. 96 97 :param image: The image to be pre-processed. 98 :param stream_type: The type of the camera stream (default is CameraStreamType.Color). 99 100 :return: The pre-processed image or None if unprocessable. 101 """ 102 return image 103 104 @abstractmethod 105 def get_raw_image(self, stream_type: CameraStreamType = CameraStreamType.Color) -> Optional[np.ndarray]: 106 """ 107 Retrieves the raw image from the camera based on the stream type. 108 109 :param stream_type: The type of the camera stream (default is CameraStreamType.Color). 110 111 :return: The raw image or None if unavailable. 112 """ 113 pass 114 115 def get_image( 116 self, 117 stream_type: CameraStreamType = CameraStreamType.Color, 118 pre_processed: bool = True, 119 post_processed: bool = True, 120 ) -> Optional[np.ndarray]: 121 """ 122 Retrieves and processes the image from the camera stream. 123 124 :param stream_type: The type of the camera stream (default is CameraStreamType.Color). 125 :param pre_processed: Whether to pre-process the image (default is True). 126 :param post_processed: Whether to post-process the image (default is True). 127 128 :return: The processed image or None if unavailable. 129 """ 130 frame = self.get_raw_image(stream_type) 131 132 if frame is None: 133 return None 134 135 # apply camera pre-processing 136 if pre_processed: 137 frame = self.pre_process_image(frame, stream_type) 138 139 # apply base camera post-processing 140 if post_processed: 141 _, frame = self._post_process(0, frame) 142 return frame 143 144 return frame 145 146 @property 147 def color_image(self) -> Optional[np.ndarray]: 148 """ 149 Returns the processed color image. 150 151 :return: The processed color image or None if unavailable. 152 """ 153 return self.get_image(CameraStreamType.Color, True, True) 154 155 @property 156 def depth_image(self) -> Optional[np.ndarray]: 157 """ 158 Returns the processed depth image. 159 160 :return: The processed depth image or None if unavailable. 161 """ 162 return self.get_image(CameraStreamType.Depth, True, True) 163 164 @property 165 def infrared_image(self) -> Optional[np.ndarray]: 166 """ 167 Returns the processed infrared image. 168 169 :return: The processed infrared image or None if unavailable. 170 """ 171 return self.get_image(CameraStreamType.Infrared, True, True) 172 173 @property 174 def raw_color_image(self) -> Optional[np.ndarray]: 175 """ 176 Returns the raw color image from the camera. 177 178 :return: The raw color image or None if unavailable. 179 """ 180 return self.get_raw_image(CameraStreamType.Color) 181 182 @property 183 def raw_depth_image(self) -> Optional[np.ndarray]: 184 """ 185 Returns the raw depth image from the camera. 186 187 :return: The raw depth image or None if unavailable. 188 """ 189 return self.get_raw_image(CameraStreamType.Depth) 190 191 @property 192 def raw_infrared_image(self) -> Optional[np.ndarray]: 193 """ 194 Returns the raw infrared image from the camera. 195 196 :return: The raw infrared image or None if unavailable. 197 """ 198 return self.get_raw_image(CameraStreamType.Infrared) 199 200 @staticmethod 201 def add_params(parser: ArgumentParser): 202 """ 203 Adds camera-specific parameters to the argument parser. 204 205 :param parser: The argument parser instance. 206 """ 207 super(BaseDepthCamera, BaseDepthCamera).add_params(parser) 208 BaseDepthInput.add_params(parser) 209 210 try: 211 parser.add_argument("-ir", "--infrared", action="store_true", help="Use infrared as input stream.") 212 except ArgumentError as ex: 213 if ex.message.startswith("conflicting"): 214 return 215 raise ex 216 217 @property 218 def is_playback(self) -> bool: 219 """ 220 Indicates whether the camera is in playback mode. 221 222 :return: False since this is a real-time camera. 223 """ 224 return False
Abstract base class for depth cameras that handle both color and depth input streams.
20 def __init__(self): 21 """ 22 Initializes the BaseDepthCamera with default settings. 23 """ 24 super().__init__() 25 self.use_infrared = False
Initializes the BaseDepthCamera with default settings.
27 def configure(self, args: Namespace): 28 """ 29 Configures the camera settings based on command line arguments. 30 31 :param args: The command line arguments namespace. 32 """ 33 super().configure(args) 34 self.use_infrared = args.infrared
Configures the camera settings based on command line arguments.
Parameters
- args: The command line arguments namespace.
90 @abstractmethod 91 def pre_process_image( 92 self, image: np.ndarray, stream_type: CameraStreamType = CameraStreamType.Color 93 ) -> Optional[np.ndarray]: 94 """ 95 Pre-processes the input image based on the stream type. 96 97 :param image: The image to be pre-processed. 98 :param stream_type: The type of the camera stream (default is CameraStreamType.Color). 99 100 :return: The pre-processed image or None if unprocessable. 101 """ 102 return image
Pre-processes the input image based on the stream type.
Parameters
- image: The image to be pre-processed.
- stream_type: The type of the camera stream (default is CameraStreamType.Color).
Returns
The pre-processed image or None if unprocessable.
104 @abstractmethod 105 def get_raw_image(self, stream_type: CameraStreamType = CameraStreamType.Color) -> Optional[np.ndarray]: 106 """ 107 Retrieves the raw image from the camera based on the stream type. 108 109 :param stream_type: The type of the camera stream (default is CameraStreamType.Color). 110 111 :return: The raw image or None if unavailable. 112 """ 113 pass
Retrieves the raw image from the camera based on the stream type.
Parameters
- stream_type: The type of the camera stream (default is CameraStreamType.Color).
Returns
The raw image or None if unavailable.
115 def get_image( 116 self, 117 stream_type: CameraStreamType = CameraStreamType.Color, 118 pre_processed: bool = True, 119 post_processed: bool = True, 120 ) -> Optional[np.ndarray]: 121 """ 122 Retrieves and processes the image from the camera stream. 123 124 :param stream_type: The type of the camera stream (default is CameraStreamType.Color). 125 :param pre_processed: Whether to pre-process the image (default is True). 126 :param post_processed: Whether to post-process the image (default is True). 127 128 :return: The processed image or None if unavailable. 129 """ 130 frame = self.get_raw_image(stream_type) 131 132 if frame is None: 133 return None 134 135 # apply camera pre-processing 136 if pre_processed: 137 frame = self.pre_process_image(frame, stream_type) 138 139 # apply base camera post-processing 140 if post_processed: 141 _, frame = self._post_process(0, frame) 142 return frame 143 144 return frame
Retrieves and processes the image from the camera stream.
Parameters
- stream_type: The type of the camera stream (default is CameraStreamType.Color).
- pre_processed: Whether to pre-process the image (default is True).
- post_processed: Whether to post-process the image (default is True).
Returns
The processed image or None if unavailable.
146 @property 147 def color_image(self) -> Optional[np.ndarray]: 148 """ 149 Returns the processed color image. 150 151 :return: The processed color image or None if unavailable. 152 """ 153 return self.get_image(CameraStreamType.Color, True, True)
Returns the processed color image.
Returns
The processed color image or None if unavailable.
155 @property 156 def depth_image(self) -> Optional[np.ndarray]: 157 """ 158 Returns the processed depth image. 159 160 :return: The processed depth image or None if unavailable. 161 """ 162 return self.get_image(CameraStreamType.Depth, True, True)
Returns the processed depth image.
Returns
The processed depth image or None if unavailable.
164 @property 165 def infrared_image(self) -> Optional[np.ndarray]: 166 """ 167 Returns the processed infrared image. 168 169 :return: The processed infrared image or None if unavailable. 170 """ 171 return self.get_image(CameraStreamType.Infrared, True, True)
Returns the processed infrared image.
Returns
The processed infrared image or None if unavailable.
173 @property 174 def raw_color_image(self) -> Optional[np.ndarray]: 175 """ 176 Returns the raw color image from the camera. 177 178 :return: The raw color image or None if unavailable. 179 """ 180 return self.get_raw_image(CameraStreamType.Color)
Returns the raw color image from the camera.
Returns
The raw color image or None if unavailable.
182 @property 183 def raw_depth_image(self) -> Optional[np.ndarray]: 184 """ 185 Returns the raw depth image from the camera. 186 187 :return: The raw depth image or None if unavailable. 188 """ 189 return self.get_raw_image(CameraStreamType.Depth)
Returns the raw depth image from the camera.
Returns
The raw depth image or None if unavailable.
191 @property 192 def raw_infrared_image(self) -> Optional[np.ndarray]: 193 """ 194 Returns the raw infrared image from the camera. 195 196 :return: The raw infrared image or None if unavailable. 197 """ 198 return self.get_raw_image(CameraStreamType.Infrared)
Returns the raw infrared image from the camera.
Returns
The raw infrared image or None if unavailable.
200 @staticmethod 201 def add_params(parser: ArgumentParser): 202 """ 203 Adds camera-specific parameters to the argument parser. 204 205 :param parser: The argument parser instance. 206 """ 207 super(BaseDepthCamera, BaseDepthCamera).add_params(parser) 208 BaseDepthInput.add_params(parser) 209 210 try: 211 parser.add_argument("-ir", "--infrared", action="store_true", help="Use infrared as input stream.") 212 except ArgumentError as ex: 213 if ex.message.startswith("conflicting"): 214 return 215 raise ex
Adds camera-specific parameters to the argument parser.
Parameters
- parser: The argument parser instance.
217 @property 218 def is_playback(self) -> bool: 219 """ 220 Indicates whether the camera is in playback mode. 221 222 :return: False since this is a real-time camera. 223 """ 224 return False
Indicates whether the camera is in playback mode.
Returns
False since this is a real-time camera.
Inherited Members
- visiongraph.input.BaseCamera.BaseCamera
- gain
- exposure
- enable_auto_exposure
- enable_auto_white_balance
- white_balance
- camera_matrix
- fisheye_distortion
- intrinsics
- get_camera_matrix
- get_fisheye_distortion
- get_intrinsics
- serial
- visiongraph.input.BaseDepthInput.BaseDepthInput
- enable_depth
- use_depth_as_input
- depth_width
- depth_height