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