目录

3. 实现屏幕的实时截图

有两种方式

win32api

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import cv2
import numpy as np
import win32gui
import win32ui
import win32con
import win32api


def grab_screen(region=None):
    hwin = win32gui.GetDesktopWindow()

    if region:
        left, top, width, height = region
    else:
        width = win32api.GetSystemMetrics(win32con.SM_CXVIRTUALSCREEN)
        height = win32api.GetSystemMetrics(win32con.SM_CYVIRTUALSCREEN)
        left = win32api.GetSystemMetrics(win32con.SM_XVIRTUALSCREEN)
        top = win32api.GetSystemMetrics(win32con.SM_YVIRTUALSCREEN)

    hwindc = win32gui.GetWindowDC(hwin)
    srcdc = win32ui.CreateDCFromHandle(hwindc)
    memdc = srcdc.CreateCompatibleDC()
    bmp = win32ui.CreateBitmap()
    bmp.CreateCompatibleBitmap(srcdc, width, height)
    memdc.SelectObject(bmp)
    memdc.BitBlt((0, 0), (width, height), srcdc, (left, top), win32con.SRCCOPY)

    signedIntsArray = bmp.GetBitmapBits(True)
    img = np.fromstring(signedIntsArray, dtype='uint8')
    img.shape = (height, width, 4)

    srcdc.DeleteDC()
    memdc.DeleteDC()
    win32gui.ReleaseDC(hwin, hwindc)
    win32gui.DeleteObject(bmp.GetHandle())

    return cv2.cvtColor(img, cv2.COLOR_BGRA2BGR)

mss

1
pip install mss
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import mss
import numpy as np
import cv2

sct = mss.mss()
screen_width = 1920  # 屏幕的宽
screen_height = 1080  # 屏幕的高
GAME_LEFT, GAME_TOP, GAME_WIDTH, GAME_HEIGHT = screen_width // 3, screen_height // 3, screen_width // 3, screen_height // 3  # 游戏内截图区域
RESIZE_WIN_WIDTH, RESIZE_WIN_HEIGHT = screen_width // 5, screen_height // 5  # 显示窗口大小
monitor = {
    'left': GAME_LEFT,
    'top': GAME_TOP,
    'width': GAME_WIDTH,
    'height': GAME_HEIGHT
}
window_name = 'test'
while True:
    img = sct.grab(monitor=monitor)
    img = np.array(img)
    cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)  # cv2.WINDOW_NORMAL 根据窗口大小设置我们的图片大小
    cv2.resizeWindow(window_name, RESIZE_WIN_WIDTH, RESIZE_WIN_HEIGHT)
    cv2.imshow(window_name, img)
    k = cv2.waitKey(1)
    if k % 256 == 27:  # ESC
        cv2.destroyAllWindows()
        exit('ESC ...')

waitKey()函数

  1. waitKey()–这个函数是在一个给定的时间内(单位ms)等待用户按键触发;如果用户没有按下 键,则接续等待(循环)

  2. 如下所示: while(1){ if(waitKey(100)==27)break; } 在这个程序中,我们告诉OpenCv等待用户触发事件,等待时间为100ms,如果在这个时间段内, 用户按下ESC(ASCII码为27),则跳出循环,否则,则继续循环

  3. 如果设置waitKey(0),则表示程序会无限制的等待用户的按键事件

注意:python下cv.waitKey无响应原因

按下键的时候,焦点要落在窗口上,不能落在cmd窗口上。

另外,一般在imshow()后要使用waitKey(),给图像绘制留下时间,不然窗口会出现无响应情况,并且图像无法显示出来。

int waitKey(int delay=0)

- 延时delay = 0 函数则延时无限长,必须有键按下才继续执行。

- 延时delay > 0 函数返回值为按下的键的ASCII码值,超时则返回-1。

也就是说必须在有窗口显示的情况下,waitKey才有作用,否则无效。

比如调用cv.waitKey(0),如果此时没有活动的窗口,该函数立刻返回-1

namedWindow()函数

用法:cv2.namedWindow(‘窗口标题’,默认参数)

默认参数:

cv2.WINDOW_AUTOSIZE+cv2.WINDOW_KEEPRATIO+cv2.WINDOW_GUI_EXPANDED)

参数:

(1)cv2.WINDOW_NORMAL:窗口大小可改变。

(2)cv2.WINDOW_AUTOSIZE:窗口大小不可改变。

(3)cv2.WINDOW_FREERATIO:自适应比例。

(4)cv2.WINDOW_KEEPRATIO:保持比例。