【发布时间】:2021-11-24 06:23:49
【问题描述】:
我正在使用下面这个特定的窗口屏幕捕获例程循环提供一个 opencv 窗口。
问题:经过数百次循环后,它突然在代码中标记的两个 FAIL POINTS 中的任何一个处失败。
我怀疑可能存在内存泄漏,但如果我没记错的话,我会删除并释放所需的内容以及我在删除之前(重新)选择对象它。
(我使用这种方法的原因,因为它即使特定窗口处于非活动状态并且在后台也能捕获它对我来说很重要而且我没有找到任何其他模块/method 确实有效。)
我忽略了什么?
import win32gui
import win32ui
from PIL import Image
import numpy as np
import cv2
while True:
target_window = win32gui.FindWindow(None, ("Analytics dashboard - Google Chrome"))
hwndDC = win32gui.GetWindowDC(target_window)
mfcDC = win32ui.CreateDCFromHandle(hwndDC)
saveDC = mfcDC.CreateCompatibleDC() #### <-- RANDOM FAIL POINT 1: win32ui.error: CreateCompatibleDC failed
saveBitMap = win32ui.CreateBitmap()
saveBitMap.CreateCompatibleBitmap(mfcDC, screen_width, screen_height)
saveDC.SelectObject(saveBitMap)
result = windll.user32.PrintWindow(target_window, saveDC.GetSafeHdc(), 3)
bmpinfo = saveBitMap.GetInfo()
bmpstr = saveBitMap.GetBitmapBits(True)
screen_image = Image.frombuffer('RGB', (bmpinfo['bmWidth'], bmpinfo['bmHeight']), bmpstr, 'raw', 'BGRX', 0, 1)
mfcDC.DeleteDC() #### <-- RANDOM FAIL POINT 2: win32ui.error: DeleteDC failed
saveDC.DeleteDC()
win32gui.DeleteObject(saveBitMap.GetHandle())
win32gui.ReleaseDC(target_window, hwndDC)
image = cv2.cvtColor(np.array(screen_image), cv2.IMREAD_ANYCOLOR)
【问题讨论】:
-
确保
target_window不是0。进入任务管理器并监控“GDI使用情况”(默认不显示,您必须进入“详细信息”,然后选择GDI。看看GDI对象是否在增加。如果超过1000或2000个句柄就会有问题。 -
@Barmak Shemirani:感谢您的快速回复!检查,target_window 永远不会为 0,总是正确地得到它。,当它崩溃时也是如此。我还检查了 GDI 对象,并且确实增加了,因为您指示运行上面的代码。问题是为什么,因为在我看来,我正确地删除、释放和选择对象。请问您是否可以获取代码并在您身边进行测试以查看是否可以发现问题?
-
我没有
windll和cv2扩展名,我将它们注释掉并运行您的代码,看不到 GDI 泄漏。它不会超过 3。也许你在其他地方有 GDI 泄漏。 -
@Barmak Shemirani:再次感谢您的回答。根据您的评论,我也做了一些额外的测试,现在我可以确认,CreateCompatibleDC 或 DeleteDC 只有在添加 PrintWindow 行时才会失败。所以,不,我们可以将问题缩小到 printwindow。我试图在这里研究任何解决方案,但我找不到任何东西。请问您是否知道如何解决这个问题?
标签: python memory-leaks pywin32 win32gui win32-process