MacOS:使用Python捕获特定窗口的屏幕截图

4

我正在使用MSS来捕获我的屏幕截图。(因为它可以更快地捕获截图)

但是我不确定如何在Mac上捕获特定窗口,我知道他们为Windows用户提供了win32...

我现在的代码只是一个不断循环捕获我的主屏幕。

main.py :

import cv2 as cv
import numpy as np
from time import time
from mss import mss


def window_capture():
    loop_time = time()

    with mss() as sct:
        monitor = {"top": 40, "left": 0, "width": 800, "height": 600}

        while(True):

            screenshot = np.array(sct.grab(monitor))
            screenshot = cv.cvtColor(screenshot, cv.COLOR_RGB2BGR)

            cv.imshow('Computer Vision', screenshot)

            print('FPS {}'.format(1 / (time() - loop_time)))
            loop_time = time()

            if cv.waitKey(1) == ord('q'):
                cv.destroyAllWindows()
                break


window_capture()

print('Done.')

你指的是特定的窗口是什么意思? - Md Shafiul Islam
查看Pillow文档中他们为截图提供的方法。 - Pritul Dave
@MdShafiulIslam 就像我现在打开了 Chrome,我只想捕捉 Chrome 窗口。 - Blue
3个回答

3

我写了下面这段 ObjectiveC 代码,可以获取macOS系统中所有窗口的名称、所有者、窗口ID和屏幕位置。我将它保存为 windowlist.m 文件并使用文件顶部注释中的命令进行编译:

////////////////////////////////////////////////////////////////////////////////
// windowlist.m
// Mark Setchell
//
// Get list of windows with their characteristics
//
// Compile with:
// clang windowlist.m -o windowlist -framework coregraphics -framework cocoa
//
// Run with:
// ./windowlist
//
////////////////////////////////////////////////////////////////////////////////
#include <Cocoa/Cocoa.h>
#include <CoreGraphics/CGWindow.h>

int main(int argc, char **argv)
{
   NSArray *windows = (NSArray *)CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly,kCGNullWindowID);
   for(NSDictionary *window in windows){
      int WindowNum = [[window objectForKey:(NSString *)kCGWindowNumber] intValue];
      NSString* OwnerName = [window objectForKey:(NSString *)kCGWindowOwnerName];
      int OwnerPID = [[window objectForKey:(NSString *) kCGWindowOwnerPID] intValue];
      NSString* WindowName= [window objectForKey:(NSString *)kCGWindowName];
      CFDictionaryRef bounds = (CFDictionaryRef)[window objectForKey:(NSString *)kCGWindowBounds];
      CGRect rect;
      CGRectMakeWithDictionaryRepresentation(bounds,&rect);
      printf("%s:%s:%d:%d:%f,%f,%f,%f\n",[OwnerName UTF8String],[WindowName UTF8String],WindowNum,OwnerPID,rect.origin.x,rect.origin.y,rect.size.height,rect.size.width);
   }
}

它会输出以下内容,每行的最后四个项目是窗口左上角的位置、高度和宽度。您可以使用 Python 的 subprocess.Popen() 运行此程序并获取窗口列表,或者您可以尝试使用 PyObjc Python 模块将其转换为 Python:
Location Menu:Item-0:4881:1886:1043.000000,0.000000,22.000000,28.000000
Backup and sync from Google:Item-0:1214:8771:1071.000000,0.000000,22.000000,30.000000
Dropbox:Item-0:451:1924:1101.000000,0.000000,22.000000,28.000000
NordVPN IKE:Item-0:447:1966:1129.000000,0.000000,22.000000,26.000000
PromiseUtilityDaemon:Item-0:395:1918:1155.000000,0.000000,22.000000,24.000000
SystemUIServer:AppleTimeMachineExtra:415:1836:1179.000000,0.000000,22.000000,40.000000
SystemUIServer:AppleBluetoothExtra:423:1836:1219.000000,0.000000,22.000000,30.000000
SystemUIServer:AirPortExtra:409:1836:1249.000000,0.000000,22.000000,30.000000
SystemUIServer:AppleVolumeExtra:427:1836:1279.000000,0.000000,22.000000,30.000000
SystemUIServer:BatteryExtra:405:1836:1309.000000,0.000000,22.000000,67.000000
SystemUIServer:AppleClockExtra:401:1836:1376.000000,0.000000,22.000000,123.000000
SystemUIServer:AppleUser:419:1836:1499.000000,0.000000,22.000000,99.000000
Spotlight:Item-0:432:1922:1598.000000,0.000000,22.000000,36.000000
SystemUIServer:NotificationCenter:391:1836:1634.000000,0.000000,22.000000,46.000000
Window Server:Menubar:353:253:0.000000,0.000000,22.000000,1680.000000
Dock:Dock:387:1835:0.000000,0.000000,1050.000000,1680.000000
Terminal:windowlist — -bash — 140×30:4105:6214:70.000000,285.000000,658.000000,1565.000000

3
import cv2 as cv
import numpy as np
from time import time
from mss import mss
from Quartz import CGWindowListCopyWindowInfo, kCGNullWindowID, kCGWindowListOptionAll
import Quartz

windowName = "Window Name like the name written on top of the window"


def get_window_dimensions(hwnd):
    window_info_list = Quartz.CGWindowListCopyWindowInfo(Quartz.kCGWindowListOptionIncludingWindow, hwnd)

    for window_info in window_info_list:
        window_id = window_info[Quartz.kCGWindowNumber]
        if window_id == hwnd:
            bounds = window_info[Quartz.kCGWindowBounds]
            width = bounds['Width']
            height = bounds['Height']
            left = bounds['X']
            top = bounds['Y']
            return {"top": top, "left": left, "width": width, "height": height}

    return None


def window_capture():
    loop_time = time()
    windowList = CGWindowListCopyWindowInfo(
        kCGWindowListOptionAll, kCGNullWindowID)

    for window in windowList:
        print(window.get('kCGWindowName', ''))
        if windowName.lower() in window.get('kCGWindowName', '').lower():
            hwnd = window['kCGWindowNumber']
            print('found window id %s' % hwnd)

    monitor = get_window_dimensions(hwnd)

    with mss() as sct:
        # monitor = {"top": 40, "left": 0, "width": 800, "height": 600}

        while (True):

            screenshot = np.array(sct.grab(monitor))
            screenshot = cv.cvtColor(screenshot, cv.COLOR_RGB2BGR)

            cv.imshow('Computer Vision', screenshot)

            print('FPS {}'.format(1 / (time() - loop_time)))
            loop_time = time()

            if cv.waitKey(1) == ord('q'):
                cv.destroyAllWindows()
                break


window_capture()

print('Done.')

解决macOS的问题,很容易找到Windows的答案,但对于mac来说就不那么简单了。所以这里是代码,伙计们。稳定的40fps...如果你用cv2或pyautogui做同样的事情,只能达到5fps。

0

如果你想打开Chrome浏览器,那么你可以使用Python内置的包webbrowser。你需要提供Chrome应用程序的路径,例如:webbrowser.get('open -a /Applications/Google\ Chrome.app %s').open('http://docs.python.org/')

一旦浏览器打开,应用程序位置将停留在离开时的位置。MSS不允许你选择应用程序。相反,你可以抓取整个屏幕或设置一个位置(如你指定的monitor = {"top": 40, "left": 0, "width": 800, "height": 600})。因此,你可能想要强制浏览器全屏显示。这可以使用pyautogui包输入热键来实现。

import webbrowser
import pyautogui

def openApp(url, appPath):
    webbrowser.get(appPath).open(url)

def fullScreen():    
    pyautogui.hotkey('command', 'ctrl', 'f') # hotKeys for full screen mode in MacOS

url = 'http://docs.python.org/'    
appPath = 'open -a /Applications/Google\ Chrome.app %s' #MacOS
#appPath = 'C:/Program Files (x86)/Google/Chrome/Application/chrome.exe %s' # Windows
#appPath = ' /usr/bin/google-chrome %s' #Linux
openApp(url, appPath)
fullScreen()
# here you can add logic to take screenshots

(注意:我只在Windows上测试过,但应该也可以在MacOS上运行)


我喜欢这个,但我正在尝试打开一个应用程序,如果你好奇是什么应用程序,那就是runescape。 - Blue
我会将这标记为答案,因为它给了我一个更好的大致方向。我认为我可以使用类似于import OS的东西,然后os.startfile? - Blue
1
OS.startfile可能仅适用于Windows。这应该可以使用os.system('C:\dev\HelloWorld.exe')来解决。请参见https://dev59.com/0GYs5IYBdhLWcg3wDfp5#13222809。 - Greg
这并没有回答问题,那为什么标记为正确答案? - Iron Attorney

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接