diff --git a/core/camera/base_camera.py b/core/camera/base_camera.py index 8c2f5b1..fb8961d 100644 --- a/core/camera/base_camera.py +++ b/core/camera/base_camera.py @@ -26,11 +26,11 @@ class BaseCamera(ABC): raise NotImplementedError @abstractmethod - def set_config_by_id(self, id: int, value: str): + def set_config_by_id(self, id: int, value) -> None: raise NotImplementedError @abstractmethod - def set_config_by_name(self, name: str, value: str): + def set_config_by_name(self, name: str, value) -> None: raise NotImplementedError def get_error_msg(self): diff --git a/core/camera/gphoto_camera.py b/core/camera/gphoto_camera.py index adb2c22..84fa640 100644 --- a/core/camera/gphoto_camera.py +++ b/core/camera/gphoto_camera.py @@ -32,13 +32,6 @@ class GPhotoCamera(BaseCamera): self.camera.init() config = self.camera.get_config() self.read_config(config) - for config in self.configs: - print(config) - config_iso = self.get_config_by_name("iso") - self.set_config_by_id(config_iso['id'], "400") - self.set_config_by_id(config_iso['id'], "100") - self.set_config_by_id(config_iso['id'], "1600") - return True except Exception as e: self.error_msg = f"[GPHOTO2] {e}" diff --git a/core/camera/opencv_camera.py b/core/camera/opencv_camera.py new file mode 100644 index 0000000..07816c5 --- /dev/null +++ b/core/camera/opencv_camera.py @@ -0,0 +1,98 @@ +import cv2 +from typing import List + +from .base_camera import BaseCamera + + + + +class CvCamera(BaseCamera): + """Kamera oparta na cv2.VideoCapture""" + + config_map = { + 0: {"name": "frame_width", "cv_prop": cv2.CAP_PROP_FRAME_WIDTH, "default": 640}, + 1: {"name": "frame_height", "cv_prop": cv2.CAP_PROP_FRAME_HEIGHT, "default": 480}, + 2: {"name": "fps", "cv_prop": cv2.CAP_PROP_FPS, "default": 30}, + 3: {"name": "brightness", "cv_prop": cv2.CAP_PROP_BRIGHTNESS, "default": 0.5}, + 4: {"name": "contrast", "cv_prop": cv2.CAP_PROP_CONTRAST, "default": 0.5}, + 5: {"name": "saturation", "cv_prop": cv2.CAP_PROP_SATURATION, "default": 0.5}, + } + + def __init__(self, device_index: int = 0) -> None: + super().__init__() + self.device_index = device_index + self.cap = None + self.configs: List[dict] = [] + + def connect(self) -> bool: + self.error_msg = None + try: + self.cap = cv2.VideoCapture(self.device_index) + if not self.cap.isOpened(): + self.error_msg = f"[CV2] Could not open camera {self.device_index}" + return False + + self.configs.clear() + for id, conf in self.config_map.items(): + value = self.cap.get(conf["cv_prop"]) + self.configs.append( + { + "id": id, + "name": conf["name"], + "label": conf["name"].capitalize(), + "value": value, + "choices": None, # brak predefiniowanych wyborów + "cv_prop": conf["cv_prop"], + } + ) + return True + + except Exception as e: + self.error_msg = f"[CV2] {e}" + self.cap = None + return False + + def disconnect(self) -> None: + if self.cap: + self.cap.release() + self.cap = None + self.configs.clear() + + def get_frame(self): + self.error_msg = None + if self.cap is None or not self.cap.isOpened(): + self.error_msg = "[CV2] Camera is not initialized." + return (False, None) + + try: + ret, frame = self.cap.read() + if not ret: + self.error_msg = "[CV2] Failed to read frame." + return (False, None) + return (True, frame) + except Exception as e: + self.error_msg = f"[CV2] {e}" + return (False, None) + + def get_config_by_id(self, id: int): + return next(w for w in self.configs if w["id"] == id) + + def get_config_by_name(self, name: str): + return next(w for w in self.configs if w["name"] == name) + + def set_config(self, config, value: float): + if not self.cap: + return + try: + self.cap.set(config["cv_prop"], value) + config["value"] = self.cap.get(config["cv_prop"]) # sprawdz co ustawiło + except Exception as e: + self.error_msg = f"[CV2] {e}" + + def set_config_by_id(self, id: int, value: float): + config = self.get_config_by_id(id) + self.set_config(config, value) + + def set_config_by_name(self, name: str, value: float): + config = self.get_config_by_name(name) + self.set_config(config, value)