You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于MediaPipe的人脸/手部追踪Python应用资源泄漏及崩溃问题

问题描述

我开发了一个基于MediaPipe库的简单人脸与手部追踪Python应用,运行数分钟后会崩溃。任务管理器显示内存占用持续增长,直至耗尽系统可用内存后崩溃,且崩溃发生在Python层面,未被代码捕获。

排查时发现VS Code调用栈中有数百个Dummy-###线程,每次循环会生成2个新的Dummy线程,不确定这是否为问题诱因。我已花费大量时间查找MediaPipe相关的内存或线程问题,但未找到线索。以下是可复现线程问题的简化代码(假设线程问题是根源),请问进一步排查的方案有哪些?

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

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: 
排查方案

1. 修复MediaPipe实例重复创建问题

你的代码在循环内每次都创建FaceMesh和Hands实例,这是内存和线程泄漏的核心原因。MediaPipe的每个解决方案实例都会初始化内部线程池和资源,循环创建会导致资源无法回收,进而堆积大量线程和内存。

修改代码,将实例创建移到循环外:

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()
    # 移到循环外初始化实例
    with mp_face_mesh.FaceMesh(
        max_num_faces=1,
        refine_landmarks=True,
        min_detection_confidence=0.5,
        min_tracking_confidence=0.5) as face_mesh:
        with mp_hands.Hands(
            static_image_mode=False,
            max_num_hands=2,
            min_detection_confidence=0.5,
            min_tracking_confidence=0.5) as hands:
            while True:               
                success, imageOriginal = cap.read()
                if not success:
                    print("Ignoring empty camera frame.")
                    continue
                image = cv2.flip(imageOriginal, 1)
                image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)               
                # 使用已初始化的实例调用process
                results = face_mesh.process(image)
                handresults = 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))
finally:
    cap.release()
    cv2.destroyAllWindows()

2. 验证线程泄漏是否停止

修改后运行程序,通过VS Code调用栈或Process Explorer等工具观察Dummy-###线程数量:

  • 若线程不再持续增长,说明原问题已解决
  • 若仍有线程堆积,需进一步排查MediaPipe版本或环境兼容性问题

3. 排查ucrtbase.dll崩溃原因

事件查看器中的0xc0000409异常属于栈溢出或无效参数,结合内存泄漏场景,大概率是资源堆积导致内存耗尽引发的连锁错误。修复实例创建问题后若仍出现该异常:

  • 升级Python到3.10.x最新版本,或尝试3.9/3.11版本,排查Python与ucrtbase.dll的兼容性问题
  • 更新MediaPipe到最新稳定版,旧版本可能存在已知的资源泄漏bug
  • 启用tracemalloc追踪内存增长点:
    import tracemalloc
    tracemalloc.start()
    
    # 在循环中每100次打印内存快照
    if counter % 100 == 0:
        snapshot = tracemalloc.take_snapshot()
        top_stats = snapshot.statistics('lineno')
        print("[Top 10内存占用]")
        for stat in top_stats[:10]:
            print(stat)
    

4. 测试简化场景

  • 单独运行人脸追踪或手部追踪,排查是否某一个模块导致线程泄漏
  • 替换为静态图片输入,排除摄像头捕获环节的资源问题

内容的提问来源于stack exchange,提问作者AaronC

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 03:30:41