Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 快速截图Winapi和Opencv_Python_Opencv_Numpy_Winapi - Fatal编程技术网

Python 快速截图Winapi和Opencv

Python 快速截图Winapi和Opencv,python,opencv,numpy,winapi,Python,Opencv,Numpy,Winapi,我需要采取非常快速的截图游戏的OpenCV项目,我正在工作。我可以轻松使用PIL,例如: 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) 但是它平均需要0.05秒,这对于实时捕获来说

我需要采取非常快速的截图游戏的OpenCV项目,我正在工作。我可以轻松使用PIL,例如:

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)
但是它平均需要0.05秒,这对于实时捕获来说还不够快

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

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)
编辑:窗口的大小为500x500,因此在两个示例中保存相同的区域

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

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

def take_screenshot1(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)

im = dataBitMap.GetBitmapBits(True)  # Tried False also
img = np.array(im)
cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
print(img)

dcObj.DeleteDC()
cDC.DeleteDC()
win32gui.ReleaseDC(hwnd, wDC)
win32gui.DeleteObject(dataBitMap.GetHandle())

但我不知道如何将返回的位图转换为OpenCV可以理解的格式,因为在OpenCV中没有将位图转换为rgb/bgr的方法在第一个版本中,您正在读取窗口的整个区域。在第二个版本中,您正在读取500x500像素的区域。除非两个区域相同,否则无法比较速度。
BitBlt
有一个瓶颈,你真的无能为力。@Barmak Shermirana啊,我应该指定更好的。我从中捕获的窗口是500x500,因此大小相同。所以我想我可能只需要保存并打开img,看起来..你不需要保存图像数据。只要调用dataBitMap,就可以通过返回的结构直接访问像素数据。明显的优化包括:在屏幕截图函数之外创建位图和DC。现在还不完全清楚,为什么要调用
CreateBitmap
,然后再调用
CreateCompatibleBitmap
。我不明白为什么需要前者。@如果我调用:win32gui.GetObject(dataBitMap),我会得到错误“TypeError:对象不是PyHANDLE对象”,这是错误的
GetObject
调用。我指的是GDI功能(如文档所示)。或者,如果要存储位图数据的副本,可以调用。您所使用的所有操作都需要对。