求Win32gui屏幕截图代码的Linux/Mac OS替代库方案
Hey there! I understand you're migrating your Windows-specific screenshot code (using win32gui/win32api) to Linux and macOS for an external project. Below are practical, Python-based solutions that mirror your original functionality—including cross-platform options and platform-specific tools tailored for better performance or native integration.
1. Cross-Platform Universal Option: PyQt5/PySide2
If you want a single codebase that works on all three platforms (Windows, Linux, macOS), using Qt's screen-grabbing APIs is a solid choice. It supports both full-screen and region-specific captures, just like your original code.
Example Code:
from PyQt5.QtWidgets import QApplication from PyQt5.QtGui import QScreen import sys import numpy as np import cv2 def grab_screen(region=None): # Ensure we have a valid QApplication instance app = QApplication(sys.argv) if not QApplication.instance() else QApplication.instance() screen = QApplication.primaryScreen() if region: left, top, x2, y2 = region width = x2 - left + 1 height = y2 - top + 1 # Capture specified region pixmap = screen.grabWindow(0, left, top, width, height) else: # Capture entire screen pixmap = screen.grabWindow(0) # Convert Qt pixmap to OpenCV-compatible format img = pixmap.toImage() img_buffer = img.bits().asstring(img.byteCount()) img_np = np.frombuffer(img_buffer, dtype=np.uint8).reshape(img.height(), img.width(), 4) # Convert BGRA to RGB (matches your original code's output) return cv2.cvtColor(img_np, cv2.COLOR_BGRA2RGB)
Setup:
Install the Qt bindings with:
pip install pyqt5 # Or use PySide2 if you prefer: pip install pyside2
2. Linux-Specific Solutions
For Linux, you can use lightweight system tools or Python wrappers that integrate seamlessly with desktop environments.
Option A: Use Scrot (System Command)
Scrot is a fast, command-line screenshot tool that's pre-installed on many Linux distros. You can call it directly from Python:
import subprocess import numpy as np import cv2 import os def grab_screen(region=None): temp_file = "/tmp/screenshot_temp.png" if region: left, top, x2, y2 = region width = x2 - left + 1 height = y2 - top + 1 # Capture specified region with scrot subprocess.run(["scrot", "-a", f"{left},{top},{width},{height}", temp_file], check=True) else: # Capture full screen subprocess.run(["scrot", temp_file], check=True) # Read and convert the image img = cv2.imread(temp_file) os.remove(temp_file) return cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
Setup:
Install Scrot if it's not already present:
# Debian/Ubuntu-based systems sudo apt install scrot # Fedora/RHEL-based systems sudo dnf install scrot
Option B: PyScrot (Python Wrapper)
If you prefer a Python-native interface for Scrot, use pyscrot:
from pyscrot import screenshot import numpy as np import cv2 def grab_screen(region=None): if region: left, top, x2, y2 = region width = x2 - left + 1 height = y2 - top + 1 img = screenshot(region=(left, top, width, height)) else: img = screenshot() # Convert to RGB format return cv2.cvtColor(np.array(img), cv2.COLOR_BGR2RGB)
Setup:
pip install pyscrot
3. macOS-Specific Solution: Quartz (Native Framework)
On macOS, using the native Quartz framework via pyobjc gives you the best performance and system integration. Note that macOS uses a bottom-left origin for coordinates, so we'll flip the image to match your original code's output.
Example Code:
import Quartz import numpy as np import cv2 def grab_screen(region=None): main_display = Quartz.CGMainDisplayID() if region: left, top, x2, y2 = region width = x2 - left + 1 height = y2 - top + 1 # Define capture region rect = Quartz.CGRectMake(left, top, width, height) else: # Get full screen bounds display_rect = Quartz.CGDisplayBounds(main_display) rect = display_rect # Capture the screen image_ref = Quartz.CGDisplayCreateImageWithRect(main_display, rect) # Extract pixel data width = int(Quartz.CGImageGetWidth(image_ref)) height = int(Quartz.CGImageGetHeight(image_ref)) pixel_data = Quartz.CGDataProviderCopyData(Quartz.CGImageGetDataProvider(image_ref)) img_np = np.frombuffer(pixel_data, dtype=np.uint8).reshape(height, width, 4) # Clean up resources Quartz.CGImageRelease(image_ref) # Flip image to match top-left origin (like Windows) and convert to RGB img_np = np.flipud(img_np) return cv2.cvtColor(img_np, cv2.COLOR_BGRA2RGB)
Setup:
Install pyobjc to access Quartz:
pip install pyobjc
4. Bonus: High-Performance Cross-Platform Option - MSS
If speed is a priority, mss is a dedicated cross-platform screenshot library optimized for fast captures. It's lightweight and has no external dependencies beyond Python.
Example Code:
import mss import numpy as np import cv2 def grab_screen(region=None): with mss.mss() as sct: if region: left, top, x2, y2 = region # Define monitor region (MSS uses top-left origin) monitor = {"top": top, "left": left, "width": x2 - left + 1, "height": y2 - top + 1} else: # Use the primary monitor (index 1; index 0 is all monitors combined) monitor = sct.monitors[1] # Capture the screen img = sct.grab(monitor) # Convert to OpenCV-compatible RGB format img_np = np.array(img) return cv2.cvtColor(img_np, cv2.COLOR_BGRA2RGB)
Setup:
pip install mss
内容的提问来源于stack exchange,提问作者Gurifisu




