|
1 | | -from __future__ import annotations |
2 | 1 | import os |
3 | | -import signal |
4 | | -import subprocess |
5 | | -import time |
6 | | -import platform |
7 | | -import cv2 |
8 | 2 | import sys |
| 3 | +import cv2 |
| 4 | +import threading |
9 | 5 | from enum import Enum |
10 | 6 | from typing import Any, Optional |
11 | | -import subprocess |
12 | | -from .defines import UDEV_CMD, CAMERA_RESOLUTION_MAP |
| 7 | + |
| 8 | +from .defines import CAMERA_RESOLUTION_MAP |
13 | 9 | from .hailo_logger import get_logger |
14 | 10 |
|
15 | 11 | hailo_logger = get_logger(__name__) |
16 | 12 |
|
17 | | -# if udevadm is not installed, install it using the following command: |
18 | | -# sudo apt-get install udev |
19 | 13 |
|
20 | 14 | class PiCamera2CaptureAdapter: |
21 | 15 | """ |
@@ -224,89 +218,8 @@ def _apply_resolution_and_validate( |
224 | 218 |
|
225 | 219 |
|
226 | 220 | def open_usb_camera(input_src: str, resolution: Optional[str]): |
227 | | - """ |
228 | | - USB camera open . |
229 | | -
|
230 | | - Supported values: |
231 | | - - "usb" : Auto-select the first available USB camera |
232 | | - - "/dev/videoX" : Explicit Linux camera device |
233 | | - - "0"/"1"/... : Explicit Windows camera index |
234 | | -
|
235 | | - The function: |
236 | | - - opens the requested source |
237 | | - - applies optional resolution |
238 | | - - vali |
239 | | - """ |
240 | | - system_name = platform.system() |
241 | | - |
242 | | - # --------------------------------------------------------- |
243 | | - # 1) Explicit Linux device path: /dev/videoX |
244 | | - # --------------------------------------------------------- |
245 | | - if str(input_src).startswith("/dev/video"): |
246 | | - if system_name == "Windows": |
247 | | - hailo_logger.error( |
248 | | - "On Windows, '/dev/videoX' is not supported. Use '-i 0' or '-i usb'." |
249 | | - ) |
250 | | - sys.exit(1) |
251 | | - |
252 | | - try: |
253 | | - cap = open_cv_capture(str(input_src), "USB camera index") |
254 | | - except SystemExit: |
255 | | - available_cameras = get_usb_video_devices() |
256 | | - if available_cameras: |
257 | | - hailo_logger.error(f"Available camera indices detected: {available_cameras}") |
258 | | - else: |
259 | | - hailo_logger.error("No cameras detected on Linux.") |
260 | | - raise |
261 | | - |
262 | | - return _apply_resolution_and_validate(cap, resolution) |
263 | | - |
264 | | - # --------------------------------------------------------- |
265 | | - # 2) Explicit Windows numeric index: 0/1/2... |
266 | | - # --------------------------------------------------------- |
267 | | - if str(input_src).isdigit(): |
268 | | - if system_name == "Linux": |
269 | | - hailo_logger.error( |
270 | | - "On Linux, numeric camera index is not supported. " |
271 | | - "Use '-i /dev/videoX' or '-i usb'." |
272 | | - ) |
273 | | - sys.exit(1) |
274 | | - |
275 | | - camera_index = int(str(input_src)) |
276 | | - try: |
277 | | - cap = open_cv_capture(camera_index, "USB camera index") |
278 | | - except SystemExit: |
279 | | - available_cameras = get_usb_video_devices() |
280 | | - if available_cameras: |
281 | | - hailo_logger.error(f"Available camera indices detected: {available_cameras}") |
282 | | - else: |
283 | | - hailo_logger.error("No cameras detected on Windows.") |
284 | | - raise |
285 | | - |
286 | | - return _apply_resolution_and_validate(cap, resolution) |
287 | | - |
288 | | - |
289 | | - # --------------------------------------------------------- |
290 | | - # 3) Auto USB selection: "usb" |
291 | | - # --------------------------------------------------------- |
292 | | - if input_src != "usb": |
293 | | - hailo_logger.error(f"open_usb_camera received invalid camera input: '{input_src}'") |
294 | | - sys.exit(1) |
295 | | - |
296 | | - available_cameras = get_usb_video_devices() |
297 | | - if not available_cameras: |
298 | | - hailo_logger.error(f"USB mode requested, but no cameras detected on {system_name}.") |
299 | | - sys.exit(1) |
300 | | - |
301 | | - selected_camera = available_cameras[0] |
302 | | - |
303 | | - try: |
304 | | - source_label = "USB camera index" if system_name == "Windows" else "USB camera device" |
305 | | - cap = open_cv_capture(selected_camera, source_label) |
306 | | - except SystemExit: |
307 | | - hailo_logger.error(f"Failed to open auto-selected USB camera: {selected_camera}") |
308 | | - raise |
309 | | - |
| 221 | + camera_index = int(str(input_src)) |
| 222 | + cap = open_cv_capture(camera_index, "USB camera index") |
310 | 223 | return _apply_resolution_and_validate(cap, resolution) |
311 | 224 |
|
312 | 225 |
|
@@ -361,143 +274,3 @@ def is_stream_url(src: str) -> bool: |
361 | 274 | or src_lower.startswith("http://") |
362 | 275 | or src_lower.startswith("https://") |
363 | 276 | ) |
364 | | - |
365 | | - |
366 | | -# Checks if a Raspberry Pi camera is connected and responsive. |
367 | | -def is_rpi_camera_available(): |
368 | | - """Returns True if the RPi camera is connected.""" |
369 | | - hailo_logger.debug("Checking if Raspberry Pi camera is available...") |
370 | | - try: |
371 | | - process = subprocess.Popen( |
372 | | - ["rpicam-hello", "-t", "0"], stdout=subprocess.PIPE, stderr=subprocess.PIPE |
373 | | - ) |
374 | | - hailo_logger.debug("Started rpicam-hello process.") |
375 | | - time.sleep(5) |
376 | | - process.send_signal(signal.SIGTERM) |
377 | | - hailo_logger.debug("Sent SIGTERM to rpicam-hello process.") |
378 | | - process.wait(timeout=2) |
379 | | - stdout, stderr = process.communicate() |
380 | | - stderr_str = stderr.decode().lower() |
381 | | - hailo_logger.debug(f"rpicam-hello stderr: {stderr_str}") |
382 | | - if "no cameras available" in stderr_str: |
383 | | - hailo_logger.info("No Raspberry Pi cameras detected.") |
384 | | - return False |
385 | | - hailo_logger.info("Raspberry Pi camera is available.") |
386 | | - return True |
387 | | - except Exception as e: |
388 | | - hailo_logger.error(f"Error checking Raspberry Pi camera: {e}") |
389 | | - return False |
390 | | - |
391 | | - |
392 | | -def get_usb_video_devices(): |
393 | | - """ |
394 | | - Return a list of available USB video devices for the current platform. |
395 | | -
|
396 | | - Returns: |
397 | | - list[str | int]: |
398 | | - - On Linux: list of device paths such as ['/dev/video0', '/dev/video2'] |
399 | | - - On Windows: list of OpenCV-compatible camera indices such as [0, 1] |
400 | | -
|
401 | | - Notes: |
402 | | - - Linux detection is based on `udevadm` and filters devices that: |
403 | | - 1. are connected via USB |
404 | | - 2. expose capture capability |
405 | | - - Windows detection relies on DirectShow device enumeration via `pygrabber`. |
406 | | - The returned indices follow the enumeration order and are intended for use |
407 | | - with OpenCV / DirectShow. |
408 | | - """ |
409 | | - system = platform.system() |
410 | | - hailo_logger.debug(f"Detecting USB video devices on {system}...") |
411 | | - |
412 | | - if system == "Linux": |
413 | | - return _get_usb_video_devices_linux() |
414 | | - |
415 | | - if system == "Windows": |
416 | | - return _get_usb_video_devices_windows() |
417 | | - |
418 | | - hailo_logger.warning(f"Unsupported platform: {system}") |
419 | | - return [] |
420 | | - |
421 | | -# Checks if a USB camera is connected and responsive. |
422 | | -def _get_usb_video_devices_linux(): |
423 | | - """Detect USB video capture devices on Linux.""" |
424 | | - hailo_logger.debug("Scanning /dev for video devices...") |
425 | | - video_devices = [ |
426 | | - f"/dev/{device}" for device in os.listdir("/dev") if device.startswith("video") |
427 | | - ] |
428 | | - usb_video_devices = [] |
429 | | - hailo_logger.debug(f"Found video devices: {video_devices}") |
430 | | - |
431 | | - for device in video_devices: |
432 | | - try: |
433 | | - hailo_logger.debug(f"Checking device: {device}") |
434 | | - # Use udevadm to get detailed information about the device |
435 | | - udevadm_cmd = [UDEV_CMD, "info", "--query=all", "--name=" + device] |
436 | | - hailo_logger.debug(f"Running command: {' '.join(udevadm_cmd)}") |
437 | | - result = subprocess.run(udevadm_cmd, check=False, capture_output=True) |
438 | | - output = result.stdout.decode("utf-8") |
439 | | - hailo_logger.debug(f"udevadm output for {device}: {output}") |
440 | | - |
441 | | - # Check if the device is connected via USB and has video capture capabilities |
442 | | - if "ID_BUS=usb" in output and ":capture:" in output: |
443 | | - hailo_logger.info(f"USB camera detected: {device}") |
444 | | - usb_video_devices.append(device) |
445 | | - except Exception as e: |
446 | | - hailo_logger.error(f"Error checking device {device}: {e}") |
447 | | - |
448 | | - hailo_logger.debug(f"USB video devices found on Linux: {usb_video_devices}") |
449 | | - return usb_video_devices |
450 | | - |
451 | | -def _get_usb_video_devices_windows(): |
452 | | - """ |
453 | | - Detect USB video devices on Windows using DirectShow enumeration. |
454 | | -
|
455 | | - Returns: |
456 | | - list[int]: Camera indices compatible with OpenCV / DirectShow. |
457 | | - """ |
458 | | - usb_video_devices = [] |
459 | | - |
460 | | - try: |
461 | | - from pygrabber.dshow_graph import FilterGraph |
462 | | - except ImportError as e: |
463 | | - msg = ( |
464 | | - "Missing dependency 'pygrabber'.\n" |
465 | | - "Install it using:\n" |
466 | | - " pip install pygrabber\n" |
467 | | - "Note: This dependency is required for Windows camera support." |
468 | | - ) |
469 | | - hailo_logger.error(msg) |
470 | | - raise ImportError(msg) from e |
471 | | - |
472 | | - try: |
473 | | - hailo_logger.debug("Enumerating DirectShow input devices...") |
474 | | - graph = FilterGraph() |
475 | | - devices = graph.get_input_devices() |
476 | | - hailo_logger.debug(f"Found DirectShow devices: {devices}") |
477 | | - |
478 | | - for index, name in enumerate(devices): |
479 | | - hailo_logger.info(f"USB camera detected: index={index}, name='{name}'") |
480 | | - usb_video_devices.append(index) |
481 | | - |
482 | | - except Exception as e: |
483 | | - hailo_logger.error(f"Failed to enumerate Windows video devices: {e}") |
484 | | - return [] |
485 | | - |
486 | | - hailo_logger.debug(f"USB video devices found on Windows: {usb_video_devices}") |
487 | | - return usb_video_devices |
488 | | - |
489 | | - |
490 | | -def main(): |
491 | | - hailo_logger.debug("Running main() to check for USB cameras.") |
492 | | - usb_video_devices = get_usb_video_devices() |
493 | | - |
494 | | - if usb_video_devices: |
495 | | - hailo_logger.info(f"USB cameras found on: {', '.join(usb_video_devices)}") |
496 | | - print(f"USB cameras found on: {', '.join(usb_video_devices)}") |
497 | | - else: |
498 | | - hailo_logger.info("No available USB cameras found.") |
499 | | - print("No available USB cameras found.") |
500 | | - |
501 | | - |
502 | | -if __name__ == "__main__": |
503 | | - main() |
0 commit comments