Python 快速截图Winapi和Opencv
我需要采取非常快速的截图游戏的OpenCV项目,我正在工作。我可以轻松使用PIL,例如: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秒,这对于实时捕获来说
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功能(如文档所示)。或者,如果要存储位图数据的副本,可以调用。您所使用的所有操作都需要对。