简体   繁体   English

使用 mediapipe 进行人脸/手部追踪的应用程序出现资源泄漏问题和 python 崩溃

[英]Issue with leaked resources and python crash in application that uses mediapipe for face / hand tracking

I have a simple face and hand tracking python application using the mediapipe library that crashes after it has been running a few minutes.我有一个使用 mediapipe 库的简单面部和手部跟踪 python 应用程序,它在运行几分钟后崩溃。 In the task manager I can see the memory usage almost continually growing taking all available system memory till the crash.在任务管理器中,我可以看到 memory 的使用率几乎持续增长,所有可用系统 memory 直到崩溃。 The crash seems to be happening at the python level and is not being caught in my code.崩溃似乎发生在 python 级别,并没有被我的代码捕获。

While troubleshooting I noticed that there are hundreds of Dummy-### threads in the VS Code call stack with 2 new dummy threads being created every loop.在进行故障排除时,我注意到 VS 代码调用堆栈中有数百个 Dummy-### 线程,每个循环都会创建 2 个新的虚拟线程。 Is this a red herring or should these be getting cleaned up?这是一条红鲱鱼还是应该清理干净?

I have spent a lot of time searching for memory or thread issues with mediapipe and haven't turned up any hints.我花了很多时间搜索 memory 或 mediapipe 的线程问题,但没有找到任何提示。

Here is a simplified version of my code which replicates the "problem" with the threads (assuming that is really the issue)...Any ideas what I can do to troubleshoot this further?这是我的代码的简化版本,它复制了线程的“问题”(假设这确实是问题所在)......我可以做些什么来进一步解决这个问题?

import cv2
import mediapipe as mp
import os
import time

mp_drawing = mp.solutions.drawing_utils
mp_drawing_styles = mp.solutions.drawing_styles
mp_face_mesh = mp.solutions.face_mesh
mp_hands=mp.solutions.hands
counter = 0
try:
    cap = cv2.VideoCapture(0)
    loopStart = time.time()
    while True:               
        success, imageOriginal = cap.read()
        if not success:
            print("Ignoring empty camera frame.")

            continue
        if True:
            image = cv2.flip(imageOriginal, 1)
        else:
            image = imageOriginal.copy()
        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)               
        
        results = mp_face_mesh.FaceMesh(max_num_faces=1, refine_landmarks=True, min_detection_confidence=0.5, min_tracking_confidence=0.5).process(image)
        handresults = mp_hands.Hands(static_image_mode=False, max_num_hands=2, min_detection_confidence=0.5, min_tracking_confidence=0.5).process(image)
        print("Counter: " + str(counter) + " Loop Time: " + str(round((time.time() - loopStart), 2)))
        counter = counter + 1
        loopStart = time.time()


except Exception as e:
    import sys
    exc_type, exc_obj, exc_tb = sys.exc_info()
    fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]   # type: ignore
    print("Error in start_session: " + str(e) + " " + str(exc_type) + " " + str(fname) + " " + str(exc_tb.tb_lineno))

In Windows Event Viewer I see that Python is crashing with this error:在 Windows 事件查看器中,我看到 Python 因以下错误而崩溃:

Faulting application name: python.exe, version: 3.10.2150.1013, time stamp: 0x61e579fe
Faulting module name: ucrtbase.dll, version: 10.0.22621.608, time stamp: 0xf5fc15a3
Exception code: 0xc0000409
Fault offset: 0x000000000007f61e
Faulting process id: 0x0x1269C
Faulting application start time: 0x0x1D922268C3678F3
Faulting application path: C:\Program Files\Python310\python.exe
Faulting module path: C:\WINDOWS\System32\ucrtbase.dll
Report Id: efd4c79f-e52e-4050-9f95-b326e4dd2339
Faulting package full name: 
Faulting package-relative application ID: 

I was able to use trial and error to trace the issue to these two lines of code:我能够通过反复试验将问题追溯到这两行代码:

results = mp_face_mesh.FaceMesh(max_num_faces=1, refine_landmarks=True, min_detection_confidence=0.5, min_tracking_confidence=0.5).process(image)
handresults = mp_hands.Hands(static_image_mode=False, max_num_hands=2, min_detection_confidence=0.5, min_tracking_confidence=0.5).process(image)

Whenever these are executed they permanently leave a Dummy-XXX thread in the call stack.每当执行这些时,它们都会在调用堆栈中永久留下一个 Dummy-XXX 线程。

To fix the issue I moved everything but the processing up to the initial declaration as shown below.为了解决这个问题,我将除处理之外的所有内容都移到了初始声明,如下所示。 With this change the number of Dummy threads stabilizes at 45 and the application does not crash.通过此更改,虚拟线程数稳定在 45,并且应用程序不会崩溃。

import cv2
import mediapipe as mp
import os
import time

mp_drawing = mp.solutions.drawing_utils
mp_drawing_styles = mp.solutions.drawing_styles
mp_face_mesh = mp.solutions.face_mesh.FaceMesh(max_num_faces=1, refine_landmarks=True, min_detection_confidence=0.5, min_tracking_confidence=0.5)
mp_hands=mp.solutions.hands.Hands(static_image_mode=False, max_num_hands=2, min_detection_confidence=0.5, min_tracking_confidence=0.5)
counter = 0
try:
    cap = cv2.VideoCapture(0)
    loopStart = time.time()
    while True:               
        success, imageOriginal = cap.read()
        if not success:
            print("Ignoring empty camera frame.")

            continue
        if True:
            image = cv2.flip(imageOriginal, 1)
        else:
            image = imageOriginal.copy()
        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)               
        
        results = mp_face_mesh.process(image)
        handresults = mp_hands.process(image)
        print("Counter: " + str(counter) + " Loop Time: " + str(round((time.time() - loopStart), 2)))
        counter = counter + 1
        loopStart = time.time()


except Exception as e:
    import sys
    exc_type, exc_obj, exc_tb = sys.exc_info()
    fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]   # type: ignore
    print("Error in start_session: " + str(e) + " " + str(exc_type) + " " + str(fname) + " " + str(exc_tb.tb_lineno))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM