From aa781a7a2a493b1c7d5b3cf19d5c60e4065653e1 Mon Sep 17 00:00:00 2001 From: ykcheungab Date: Wed, 11 Mar 2026 10:40:04 +0800 Subject: [PATCH] improve 480p support and opencv print log --- config/prototype_of3_480p.json | 2 +- src/orisys/sensor.py | 85 +++++++++++++++++++++------------- 2 files changed, 54 insertions(+), 33 deletions(-) diff --git a/config/prototype_of3_480p.json b/config/prototype_of3_480p.json index 4e87d44..52bb939 100644 --- a/config/prototype_of3_480p.json +++ b/config/prototype_of3_480p.json @@ -11,7 +11,7 @@ }, "stitcher": { "min_area_frac": 0.01, - "max_area_frac": 0.04, + "max_area_frac": 0.06, "max_aspect_ratio": 100, "index": [1,2,3,6,7,8,11,12,13], "margin": 4, diff --git a/src/orisys/sensor.py b/src/orisys/sensor.py index 5f65bd8..610e8d4 100644 --- a/src/orisys/sensor.py +++ b/src/orisys/sensor.py @@ -472,54 +472,75 @@ class Sensor: def _open_video_source(self, override, box): """Initialize video capture and calibration.""" - _is_camera_index = isinstance(self.vid_src, int) - _is_v4l2_path = isinstance(self.vid_src, str) and self.vid_src.startswith("/dev/video") - use_linux_camera_pyav = ( - platform.system() == "Linux" - and (_is_camera_index or _is_v4l2_path) - and av is not None - ) + # _is_camera_index = isinstance(self.vid_src, int) + # _is_v4l2_path = isinstance(self.vid_src, str) and self.vid_src.startswith("/dev/video") + # use_linux_camera_pyav = ( + # platform.system() == "Linux" + # and (_is_camera_index or _is_v4l2_path) + # and av is not None + # ) - if use_linux_camera_pyav: - device = self.vid_src if _is_v4l2_path else f"/dev/video{self.vid_src}" - if self.verbose: - print(f"Using PyAV Linux camera backend: {device}") - try: - self._av_container = av.open( - device, - format="v4l2", - options={ - "input_format": "mjpeg", - "video_size": f"{self._config_resolution_raw[0]}x{self._config_resolution_raw[1]}", - "framerate": str(self._config_fps), - }, - ) - self._av_stream = self._av_container.streams.video[0] - self._av_decoder = self._av_container.decode(self._av_stream) - self._use_pyav = True - except Exception as exc: - if self.verbose: - print(f"PyAV camera open failed ({exc}), fallback to OpenCV backend.") - self._use_pyav = False + # if use_linux_camera_pyav: + # device = self.vid_src if _is_v4l2_path else f"/dev/video{self.vid_src}" + # if self.verbose: + # print(f"Using PyAV Linux camera backend: {device}") + # try: + # self._av_container = av.open( + # device, + # format="v4l2", + # options={ + # "input_format": "mjpeg", + # "video_size": f"{self._config_resolution_raw[0]}x{self._config_resolution_raw[1]}", + # "framerate": str(self._config_fps), + # }, + # ) + # self._av_stream = self._av_container.streams.video[0] + # self._av_decoder = self._av_container.decode(self._av_stream) + # self._use_pyav = True + # except Exception as exc: + # if self.verbose: + # print(f"PyAV camera open failed ({exc}), fallback to OpenCV backend.") + # self._use_pyav = False + self.use_pyav = False if not self._use_pyav: self.cap = cv2.VideoCapture(self.vid_src) # Set buffer size to 1 to reduce latency and avoid frame accumulation # Note: Not all backends support this, but it helps when available - try: - self.cap.set(cv2.CAP_PROP_BUFFERSIZE, 1) - except Exception: - pass # Some backends don't support this property + # try: + # self.cap.set(cv2.CAP_PROP_BUFFERSIZE, 1) + # except Exception: + # pass # Some backends don't support this property self.cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter.fourcc('M', 'J', 'P', 'G')) self.cap.set(cv2.CAP_PROP_FPS, self._config_fps) self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, self._config_resolution_raw[0]) self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, self._config_resolution_raw[1]) + if self.verbose: print("Connecting to video source...") + if not self._is_source_open(): raise Exception("Failed to open video source.") + + if self.verbose and not self._use_pyav and self.cap is not None: + fourcc_int = int(self.cap.get(cv2.CAP_PROP_FOURCC)) + fourcc_bytes = [(fourcc_int >> (8 * i)) & 0xFF for i in range(4)] + # Show printable FOURCC only; some backends return 0 or non-printable bytes. + if fourcc_int <= 0: + fourcc = "N/A" + else: + fourcc = "".join(chr(b) if 32 <= b <= 126 else "." for b in fourcc_bytes) + width = int(self.cap.get(cv2.CAP_PROP_FRAME_WIDTH)) + height = int(self.cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) + fps = self.cap.get(cv2.CAP_PROP_FPS) + backend_id = int(self.cap.get(cv2.CAP_PROP_BACKEND)) + print( + f"OpenCV negotiated stream: FOURCC='{fourcc}' " + f"(int={fourcc_int}, hex=0x{fourcc_int:08X}), " + f"size={width}x{height}, fps={fps:.2f}, backend_id={backend_id}" + ) # Wait for first valid frame frame = None