关于python:python简单实现对桌面进行实时捕捉画面

2次阅读

共计 3955 个字符,预计需要花费 10 分钟才能阅读完成。

介绍

最近在钻研指标检测方面的小东西,须要到对桌面进行实时捕获画面,获取画面后再检测,达到实时桌面指标检测的目标,所以写了一段小代码来实现该性能,实测速度很快,合乎我的需要。特此记录一下。

代码

import argparse
import time
import cv2
import keyboard
import mss
import numpy as np
import win32com.client
import win32con
import win32gui


class ScreenCapture:
    """
    parameters
    ----------
        screen_frame : Tuple[int, int]
            屏幕宽高,别离为 x,y
        region : Tuple[float, float]
            理论截图范畴,别离为 x,y,(1.0, 1.0) 示意全屏检测,越低检测范畴越小 (始终保持屏幕核心为核心)
        window_name : str
            显示窗口名
        exit_key : int
            完结窗口的退出键值,为键盘各键对应的 ASCII 码值,默认是 ESC 键
    """def __init__(self, screen_frame=(1920, 1080), region=(0.5, 0.5), window_name='test', exit_key=0x1B):
        self.parser = argparse.ArgumentParser()
        self.parser.add_argument('--region', type=tuple, default=region,
                                 help='截图范畴;别离为 x,y,(1.0, 1.0) 示意全屏检测,越低检测范畴越小 (始终保持屏幕核心为核心)')
        self.parser_args = self.parser.parse_args()

        self.cap = mss.mss(mon=-1, optimize=True)  # 实例化 mss,并应用高效模式

        self.screen_width = screen_frame[0]  # 屏幕的宽
        self.screen_height = screen_frame[1]  # 屏幕的高
        self.mouse_x, self.mouse_y = self.screen_width // 2, self.screen_height // 2  # 屏幕中心点坐标

        # 截图区域
        self.GAME_WIDTH, self.GAME_HEIGHT = int(self.screen_width * self.parser_args.region[0]), int(self.screen_height * self.parser_args.region[1])  # 宽高
        self.GAME_LEFT, self.GAME_TOP = int(0 + self.screen_width // 2 * (1. - self.parser_args.region[0])), int(0 + 1080 // 2 * (1. - self.parser_args.region[1]))  # 原点

        self.RESZIE_WIN_WIDTH, self.RESIZE_WIN_HEIGHT = self.screen_width // 4, self.screen_height // 4  # 显示窗口大小
        self.mointor = {
            'left': self.GAME_LEFT,
            'top': self.GAME_TOP,
            'width': self.GAME_WIDTH,
            'height': self.GAME_HEIGHT
        }

        self.window_name = window_name
        self.Exit_key = exit_key

    def grab_screen_mss(self, monitor):
        # cap.grab 截取图片,np.array 将图片转为数组,cvtColor 将 BRGA 转为 BRG, 去掉了通明通道
        return cv2.cvtColor(np.array(self.cap.grab(monitor)), cv2.COLOR_BGRA2BGR)

    def run(self):
        SetForegroundWindow_f = 0  # 判断是否须要置顶窗口
        while True:
            # 判断是否按下 ctrl+U 窗口始终置顶
            if keyboard.is_pressed('ctrl+U'):
                while keyboard.is_pressed('ctrl+U'):
                    continue
                if SetForegroundWindow_f == 0:
                    SetForegroundWindow_f = 1
                    time.sleep(1)
                    continue
                else:
                    SetForegroundWindow_f = 0

            img = self.grab_screen_mss(self.mointor)

            cv2.namedWindow(self.window_name, cv2.WINDOW_NORMAL)  # cv2.WINDOW_NORMAL 依据窗口大小设置图片大小
            cv2.resizeWindow(self.window_name, self.RESZIE_WIN_WIDTH, self.RESIZE_WIN_HEIGHT)
            cv2.imshow(self.window_name, img)

            if SetForegroundWindow_f == 1:
                shell = win32com.client.Dispatch("WScript.Shell")
                shell.SendKeys('%')
                win32gui.SetForegroundWindow(win32gui.FindWindow(None, self.window_name))
                win32gui.ShowWindow(win32gui.FindWindow(None, self.window_name), win32con.SW_SHOW)

            if cv2.waitKey(1) & 0XFF == self.Exit_key:  # 默认:ESC
                cv2.destroyAllWindows()
                exit("完结")

代码解说

性能实现思路次要是应用 mss 库进行截图,并应用 opencv 库进行图像显示和解决。

首先,应用 argparse 库解析传入的参数,设置检测范畴的大小。

而后,应用 mss 库实例化一个截图对象 cap。

接着,设置屏幕的宽和高,并计算屏幕中心点的坐标。

之后,依据传入的参数计算游戏内截图区域的宽高和原点坐标,并将其保留在变量 mointor 中。

定义了一个函数 grab_screen_mss,应用 cap.grab 截取图片,并用 np.array 将图片转为数组,而后用 cvtColor 将 BRGA 转为 BRG , 去掉了通明通道。

定义了一个 run 函数,在其中一直循环,判断是否按下 ctrl+U,若按下,则窗口始终置顶。

而后调用 grab_screen_mss 函数获取截图,应用 cv2 库进行图像显示,并设置显示窗口的大小。

如果窗口须要置顶,则应用 win32com 库和 win32gui 库置顶窗口。

最初,应用 cv2 库的 waitKey 函数期待用户操作,按下 ESC 键退出程序。

调用示例

    sc = ScreenCapture()
    sc.run()

参数解释:

   screen_frame : Tuple[int, int]
        屏幕宽高,别离为 x,y
    region : Tuple[float, float]
        理论截图范畴,别离为 x,y,(1.0, 1.0) 示意全屏检测,越低检测范畴越小 (始终保持屏幕核心为核心)
    window_name : str
        显示窗口名
    exit_key : int
        完结窗口的退出键值,为键盘各键对应的 ASCII 码值,默认是 ESC 键
        

其余

键盘各键对应的 ASCII 码值(0x 指 16 进制,delete 键的 ascii 码值是 0x2e,也即十进制的 46)

0x1 鼠标左键
0x2 鼠标右键
0x3 CANCEL 键
0x4 鼠标中键
0x8 BACKSPACE 键
0x9 TAB 键
0xC CLEAR 键
0xD ENTER 键
0x10 SHIFT 键
0x11 CTRL 键
0x12 MENU 键
0x13 PAUSE 键
0x14 CAPS LOCK 键
0x1B ESC 键
0x20 SPACEBAR 键
0x21 PAGE UP 键
0x22 PAGE DOWN 键
0x23 END 键
0x24 HOME 键
0x25 LEFT ARROW 键
0x26 UP ARROW 键
0x27 RIGHT ARROW 键
0x28 DOWN ARROW 键
0x29 SELECT 键
0x2A PRINT SCREEN 键
0x2B EXECUTE 键
0x2C SNAPSHOT 键
0x2D INSERT 键
0x2E DELETE 键
0x2F HELP 键
0x90 NUM LOCK 键

A 至 Z 键与 A – Z 字母的 ASCII 码雷同:

值 形容
65 A 键
66 B 键
67 C 键
68 D 键
69 E 键
70 F 键
71 G 键
72 H 键
73 I 键
74 J 键
75 K 键
76 L 键
77 M 键
78 N 键
79 O 键
80 P 键
81 Q 键
82 R 键
83 S 键
84 T 键
85 U 键
86 V 键
87 W 键
88 X 键
89 Y 键
90 Z 键

0 至 9 键与数字 0 – 9 的 ASCII 码雷同:

值 形容
48 0 键
49 1 键
50 2 键
51 3 键
52 4 键
53 5 键
54 6 键
55 7 键
56 8 键
57 9 键

下列常数代表数字键盘上的键:

值 形容
0x60 0 键
0x61 1 键
0x62 2 键
0x63 3 键
0x64 4 键
0x65 5 键
0x66 6 键
0x67 7 键
0x68 8 键
0x69 9 键
0x6A MULTIPLICATION SIGN (*) 键
0x6B PLUS SIGN (+) 键
0x6C ENTER 键
0x6D MINUS SIGN (–) 键
0x6E DECIMAL POINT (.) 键
0x6F DIVISION SIGN (/) 键

下列常数代表功能键:

值 形容
0x70 F1 键
0x71 F2 键
0x72 F3 键
0x73 F4 键
0x74 F5 键
0x75 F6 键
0x76 F7 键
0x77 F8 键
0x78 F9 键
0x79 F10 键
0x7A F11 键
0x7B F12 键
0x7C F13 键
0x7D F14 键
0x7E F15 键
0x7F F16 键

正文完
 0