快速截图Winapi和Opencv

时间:2016-10-18 01:31:11

标签: python opencv numpy winapi

我需要为我正在开发的OpenCV项目拍摄非常快速的游戏截图。我可以轻松地使用PIL,例如:

int

但它平均需要0.05秒,这对于实时捕捉来说还不够快。

我可以使用here发布的答案,但这只会将位图保存到文件中。这比使用PIL快10倍,但我不确定OpenCV中的任何方法将其转换为bgr / hsv图像。

def take_screenshot1(hwnd):
    rect = win32gui.GetWindowRect(hwnd)
    img = ImageGrab.grab(bbox=rect)
    img_np = np.array(img)
    return cv2.cvtColor(img_np, cv2.COLOR_RGB2BGR)

编辑:窗口大小为500x500,因此在两个示例中都保存了相同的区域。

即使我保存图像,然后使用OpenCV重新打开它,它仍然比PIL快,但肯定有更简单的方法吗?

编辑:好的,所以使用评论并对winapi进行一些研究我现在可以直接访问位图数据,如下所示:

def take_screenshot(hwnd):
    wDC = win32gui.GetWindowDC(hwnd)
    dcObj=win32ui.CreateDCFromHandle(wDC)
    cDC=dcObj.CreateCompatibleDC()
    dataBitMap = win32ui.CreateBitmap()
    dataBitMap.CreateCompatibleBitmap(dcObj, 500, 500)
    cDC.SelectObject(dataBitMap)
    cDC.BitBlt((0, 0), (500, 500), dcObj, (0, 0), win32con.SRCCOPY)

    dataBitMap.SaveBitmapFile(cDC, "foo.png")

    dcObj.DeleteDC()
    cDC.DeleteDC()
    win32gui.ReleaseDC(hwnd, wDC)
    win32gui.DeleteObject(dataBitMap.GetHandle())
    im = cv2.imread("foo.png")
    return cv2.cvtColor(im, cv2.COLOR_RGB2BGR)

但是我不知道如何将返回的位图转换为OpenCV可以理解的形式,因为没有方法可以将位图转换为OpenCV中的rgb / bgr

1 个答案:

答案 0 :(得分:0)

我只会展示对我有用的代码。

import time
import win32gui
import win32ui
import win32con
import win32api
import numpy as np
import cv2


def window_capture():
    hwnd = 0
    hwndDC = win32gui.GetWindowDC(hwnd)
    mfcDC = win32ui.CreateDCFromHandle(hwndDC)
    saveDC = mfcDC.CreateCompatibleDC()
    saveBitMap = win32ui.CreateBitmap()

    MoniterDev = win32api.EnumDisplayMonitors(None, None)
    w = MoniterDev[0][2][2]
    h = MoniterDev[0][2][3]

    saveBitMap.CreateCompatibleBitmap(mfcDC, w, h)
    saveDC.SelectObject(saveBitMap)
    saveDC.BitBlt((0, 0), (w, h), mfcDC, (0, 0), win32con.SRCCOPY)
    im = saveBitMap.GetBitmapBits(True)  # Tried False also
    img = np.frombuffer(im, dtype=np.uint8).reshape((h, w, 4))

    cv2.imshow("demo", img)
    cv2.waitKey(100)


beg = time.time()
for i in range(100):
    window_capture()
end = time.time()
print(end - beg)

cv2.destroyAllWindows()