Python结合Mediapipe开发手部检测类代码出现内存无法释放占满问题
Python+Mediapipe手部检测内存泄漏问题解决
问题原因
- 核心泄漏点:你将
handDetector类的实例化逻辑放在了while循环内部,每轮循环都会创建一个新的mp.solutions.hands.Hands模型实例。Mediapipe的模型底层由C实现,你手动删除Python层的handDtc对象、调用gc.collect()仅能回收Python层分配的内存,无法释放C层申请的模型内存,每轮循环遗留的C++层内存持续累积,最终导致内存被占满。 - 附加问题:代码存在语法错误(
draw_landmarks方法调用后多了冗余的cv.FILLED参数)、无用赋值语句,会额外引发运行异常。
修复方案
- 将
handDetector的实例化移到while循环外部,整个程序运行周期仅初始化一次Mediapipe手部检测模型,避免重复创建实例占用内存。 - 移除所有gc相关操作,gc无法管理Mediapipe底层C++内存,手动调用完全无效。
- 程序退出时新增摄像头资源、OpenCV窗口资源的释放逻辑。
- 修正现有代码的语法错误和无用语句。
修复后完整代码
import cv2 as cv import mediapipe as mp import time class handDetector(): def __init__(self, mode=False, maxHands=2, detectionCon=0.5, trackCon=0.5): self.mode = mode self.maxHands = maxHands self.detectionCon = detectionCon self.trackCon = trackCon self.mpHands = mp.solutions.hands self.hands = self.mpHands.Hands(self.mode, self.maxHands, 1, self.detectionCon, self.trackCon) self.mpDraw = mp.solutions.drawing_utils def findHands(self, image, draw=True): imgRGB = cv.cvtColor(image, cv.COLOR_BGR2RGB) self.result = self.hands.process(imgRGB) if self.result.multi_hand_landmarks: for hand in self.result.multi_hand_landmarks: if draw: self.mpDraw.draw_landmarks(image, hand, self.mpHands.HAND_CONNECTIONS) return image def findPosition(self, image, handNo=0, draw=True): lmList = [] h, w, c = image.shape if self.result.multi_hand_landmarks: myHand = self.result.multi_hand_landmarks[handNo] for id, land in enumerate(myHand.landmark): cx, cy = int(land.x * w), int(land.y * h) lmList.append([id, cx, cy]) if draw: cv.circle(image, (cx,cy), 15, (0,0,255), cv.FILLED) return lmList def main(): cap = cv.VideoCapture(0) ret = True pre_time = time.time() # 模型实例化移到循环外,仅初始化一次 handDtc = handDetector() while ret: ret, frame = cap.read() if not ret: break crt_time = time.time() fps = int(1/(crt_time-pre_time)) image = handDtc.findHands(frame) lmList = handDtc.findPosition(image) cv.putText(image, str(fps), (50,50), cv.FONT_HERSHEY_COMPLEX, 1, (255,255,0)) cv.imshow('image', image) pre_time = time.time() if cv.waitKey(1) == ord('q'): break # 释放资源 cap.release() cv.destroyAllWindows() if __name__ == "__main__": main()
内容的提问来源于stack exchange,提问作者Wreza Shafaghi
相关产品推荐
相关产品推荐

