When using screencapture with win32gui, memory leak occurs
muhaha211 opened this issue · comments
muhaha211 commented
import numpy as np
import win32gui, win32ui, win32con
import time
import cv2
import psutil
def memory_usage(message: str = 'debug'):
# current process RAM usage
p = psutil.Process()
rss = p.memory_info().rss / 2 ** 20 # Bytes to MB
print(f"[{message}] memory usage: {rss: 10.5f} MB")
class ImageSearch:
# constructor
def __init__(self, windowx=0, windowy=0, windowr=0):
self.hwnd = win32gui.GetDesktopWindow() # Get the desktop window handle
def screencapture(self):
# Get the window size
window_rect = win32gui.GetWindowRect(self.hwnd)
self.left = window_rect[0]
self.top = window_rect[1]
self.weight = window_rect[2] - window_rect[0]
self.height = window_rect[3] - window_rect[1]
# Get the window image data
wDC = win32gui.GetWindowDC(self.hwnd)
dcObj = win32ui.CreateDCFromHandle(wDC)
cDC = dcObj.CreateCompatibleDC()
dataBitMap = win32ui.CreateBitmap()
dataBitMap.CreateCompatibleBitmap(dcObj, self.weight, self.height)
cDC.SelectObject(dataBitMap)
cDC.BitBlt((0, 0), (self.weight, self.height), dcObj, (self.left, self.top), win32con.SRCCOPY)
# Convert the raw data into a format OpenCV can read
signedIntsArray = dataBitMap.GetBitmapBits(True)
img = np.frombuffer(signedIntsArray, dtype='uint8')
img.shape = (self.height, self.weight, 4)
# Clean up resources
dcObj.DeleteDC()
cDC.DeleteDC()
win32gui.ReleaseDC(self.hwnd, wDC)
win32gui.DeleteObject(dataBitMap.GetHandle())
img = img[..., :3]
img = np.ascontiguousarray(img)
return img
a = ImageSearch()
while True:
memory_usage('#1')
abc = a.screencapture()
Python 3.10.11, pywin306 on windows10.
The code causes memory to keep increasing over time when executed. It appears that something in the win32 capture method is causing a leak, but I'm not sure of the exact cause or solution. Despite searching online, there doesn't seem to be an obvious issue with the code. Is there a solution available?
Mark Hammond commented
You'd need to narrow you code down even further and work out which pywin32 function is actually causing the leak. Once identified a fix should be fairly easy but will require a new build of pywin32.