Pygrabber only for Windows
parent
c72582506d
commit
a9e8f27360
|
@ -27,6 +27,7 @@ from modules.utilities import (
|
||||||
has_image_extension,
|
has_image_extension,
|
||||||
)
|
)
|
||||||
from modules.video_capture import VideoCapturer
|
from modules.video_capture import VideoCapturer
|
||||||
|
import platform
|
||||||
|
|
||||||
ROOT = None
|
ROOT = None
|
||||||
POPUP = None
|
POPUP = None
|
||||||
|
@ -771,39 +772,57 @@ def webcam_preview(root: ctk.CTk, camera_index: int):
|
||||||
|
|
||||||
def get_available_cameras():
|
def get_available_cameras():
|
||||||
"""Returns a list of available camera names and indices."""
|
"""Returns a list of available camera names and indices."""
|
||||||
try:
|
if platform.system() == "Windows":
|
||||||
graph = FilterGraph()
|
try:
|
||||||
devices = graph.get_input_devices()
|
graph = FilterGraph()
|
||||||
|
devices = graph.get_input_devices()
|
||||||
|
|
||||||
# Create list of indices and names
|
# Create list of indices and names
|
||||||
camera_indices = list(range(len(devices)))
|
camera_indices = list(range(len(devices)))
|
||||||
camera_names = devices
|
camera_names = devices
|
||||||
|
|
||||||
# If no cameras found through DirectShow, try OpenCV fallback
|
# If no cameras found through DirectShow, try OpenCV fallback
|
||||||
if not camera_names:
|
if not camera_names:
|
||||||
# Try to open camera with index -1 and 0
|
# Try to open camera with index -1 and 0
|
||||||
test_indices = [-1, 0]
|
test_indices = [-1, 0]
|
||||||
working_cameras = []
|
working_cameras = []
|
||||||
|
|
||||||
for idx in test_indices:
|
for idx in test_indices:
|
||||||
cap = cv2.VideoCapture(idx)
|
cap = cv2.VideoCapture(idx)
|
||||||
if cap.isOpened():
|
if cap.isOpened():
|
||||||
working_cameras.append(f"Camera {idx}")
|
working_cameras.append(f"Camera {idx}")
|
||||||
cap.release()
|
cap.release()
|
||||||
|
|
||||||
if working_cameras:
|
if working_cameras:
|
||||||
return test_indices[: len(working_cameras)], working_cameras
|
return test_indices[: len(working_cameras)], working_cameras
|
||||||
|
|
||||||
|
# If still no cameras found, return empty lists
|
||||||
|
if not camera_names:
|
||||||
|
return [], ["No cameras found"]
|
||||||
|
|
||||||
|
return camera_indices, camera_names
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error detecting cameras: {str(e)}")
|
||||||
|
return [], ["No cameras found"]
|
||||||
|
else:
|
||||||
|
# Unix-like systems (Linux/Mac) camera detection
|
||||||
|
camera_indices = []
|
||||||
|
camera_names = []
|
||||||
|
|
||||||
|
# Test the first 10 indices
|
||||||
|
for i in range(10):
|
||||||
|
cap = cv2.VideoCapture(i)
|
||||||
|
if cap.isOpened():
|
||||||
|
camera_indices.append(i)
|
||||||
|
camera_names.append(f"Camera {i}")
|
||||||
|
cap.release()
|
||||||
|
|
||||||
# If still no cameras found, return empty lists
|
|
||||||
if not camera_names:
|
if not camera_names:
|
||||||
return [], ["No cameras found"]
|
return [], ["No cameras found"]
|
||||||
|
|
||||||
return camera_indices, camera_names
|
return camera_indices, camera_names
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error detecting cameras: {str(e)}")
|
|
||||||
return [], ["No cameras found"]
|
|
||||||
|
|
||||||
|
|
||||||
def create_webcam_preview(camera_index: int):
|
def create_webcam_preview(camera_index: int):
|
||||||
global preview_label, PREVIEW
|
global preview_label, PREVIEW
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
import cv2
|
import cv2
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from pygrabber.dshow_graph import FilterGraph
|
|
||||||
import threading
|
|
||||||
from typing import Optional, Tuple, Callable
|
from typing import Optional, Tuple, Callable
|
||||||
|
import platform
|
||||||
|
import threading
|
||||||
|
|
||||||
|
# Only import Windows-specific library if on Windows
|
||||||
|
if platform.system() == "Windows":
|
||||||
|
from pygrabber.dshow_graph import FilterGraph
|
||||||
|
|
||||||
|
|
||||||
class VideoCapturer:
|
class VideoCapturer:
|
||||||
def __init__(self, device_index: int):
|
def __init__(self, device_index: int):
|
||||||
self.graph = FilterGraph()
|
|
||||||
self.device_index = device_index
|
self.device_index = device_index
|
||||||
self.frame_callback = None
|
self.frame_callback = None
|
||||||
self._current_frame = None
|
self._current_frame = None
|
||||||
|
@ -15,35 +18,42 @@ class VideoCapturer:
|
||||||
self.is_running = False
|
self.is_running = False
|
||||||
self.cap = None
|
self.cap = None
|
||||||
|
|
||||||
# Verify device exists
|
# Initialize Windows-specific components if on Windows
|
||||||
devices = self.graph.get_input_devices()
|
if platform.system() == "Windows":
|
||||||
if self.device_index >= len(devices):
|
self.graph = FilterGraph()
|
||||||
raise ValueError(
|
# Verify device exists
|
||||||
f"Invalid device index {device_index}. Available devices: {len(devices)}"
|
devices = self.graph.get_input_devices()
|
||||||
)
|
if self.device_index >= len(devices):
|
||||||
|
raise ValueError(
|
||||||
|
f"Invalid device index {device_index}. Available devices: {len(devices)}"
|
||||||
|
)
|
||||||
|
|
||||||
def start(self, width: int = 960, height: int = 540, fps: int = 60) -> bool:
|
def start(self, width: int = 960, height: int = 540, fps: int = 60) -> bool:
|
||||||
"""Initialize and start video capture"""
|
"""Initialize and start video capture"""
|
||||||
try:
|
try:
|
||||||
# Try different capture methods in order
|
if platform.system() == "Windows":
|
||||||
capture_methods = [
|
# Windows-specific capture methods
|
||||||
(self.device_index, cv2.CAP_DSHOW), # Try DirectShow first
|
capture_methods = [
|
||||||
(self.device_index, cv2.CAP_ANY), # Then try default backend
|
(self.device_index, cv2.CAP_DSHOW), # Try DirectShow first
|
||||||
(-1, cv2.CAP_ANY), # Try -1 as fallback
|
(self.device_index, cv2.CAP_ANY), # Then try default backend
|
||||||
(0, cv2.CAP_ANY), # Finally try 0 without specific backend
|
(-1, cv2.CAP_ANY), # Try -1 as fallback
|
||||||
]
|
(0, cv2.CAP_ANY), # Finally try 0 without specific backend
|
||||||
|
]
|
||||||
|
|
||||||
for dev_id, backend in capture_methods:
|
for dev_id, backend in capture_methods:
|
||||||
try:
|
try:
|
||||||
self.cap = cv2.VideoCapture(dev_id, backend)
|
self.cap = cv2.VideoCapture(dev_id, backend)
|
||||||
if self.cap.isOpened():
|
if self.cap.isOpened():
|
||||||
break
|
break
|
||||||
self.cap.release()
|
self.cap.release()
|
||||||
except Exception:
|
except Exception:
|
||||||
continue
|
continue
|
||||||
|
else:
|
||||||
|
# Unix-like systems (Linux/Mac) capture method
|
||||||
|
self.cap = cv2.VideoCapture(self.device_index)
|
||||||
|
|
||||||
if not self.cap or not self.cap.isOpened():
|
if not self.cap or not self.cap.isOpened():
|
||||||
raise RuntimeError("Failed to open camera with all available methods")
|
raise RuntimeError("Failed to open camera")
|
||||||
|
|
||||||
# Configure format
|
# Configure format
|
||||||
self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
|
self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
|
||||||
|
|
Loading…
Reference in New Issue