基于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
相关产品推荐
相关产品推荐

