简体   繁体   中英

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. In the task manager I can see the memory usage almost continually growing taking all available system memory till the crash. The crash seems to be happening at the python level and is not being caught in my code.

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. 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.

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:

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.

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.

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))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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