使用MediaPipe与OpenCV构建手部检测模块时遇异常错误求助
我尝试用MediaPipe和OpenCV编写手部检测模块,代码如下:
import cv2 import mediapipe as mp import time class handDetector(): def __init__(self, mode=False, model_complexity=1, maxHands=2, detectionCon=0.5, trackingCon=0.5): self.mode = mode self.maxHands = maxHands self.model_complexity = model_complexity self.detectionCon = detectionCon self.trackingCon = trackingCon self.mpHands = mp.solutions.hands self.hands = self.mpHands.Hands(self.mode, self.model_complexity, self.maxHands, self.detectionCon, self.trackingCon) self.mpDraw = mp.solutions.drawing_utils def findHands(self, img, draw=True): imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) self.results = self.hands.process(imgRGB) # print(results.multi_hand_landmarks) if self.results.multi_hand_landmarks: for handLms in self.results.multi_hand_landmarks: if draw: self.mpDraw.draw_landmarks(img, handLms, self.mpHands.HAND_CONNECTIONS) return img def findPosition(self, img, handNo=0, draw=True): lmList = [] if self.results.multi_hand_landmarks: myHand = self.results.multi_hand_landmarks[handNo] for id, lm in enumerate(myHand.landmark): # print(id, lm) h, w, c = img.shape cx, cy = int(lm.x * w), int(lm.y * h) # print(id, cx, cy) lmList.append([id, cx, cy]) if id == 8: cv2.circle(img, (cx, cy), 10, (255, 0, 255), cv2.FILLED) if id == 12: cv2.circle(img, (cx, cy), 10, (255, 0, 255), cv2.FILLED) if id == 16: cv2.circle(img, (cx, cy), 10, (255, 0, 255), cv2.FILLED) if id == 20: cv2.circle(img, (cx, cy), 10, (255, 0, 255), cv2.FILLED) if id == 4: cv2.circle(img, (cx, cy), 10, (255, 0, 255), cv2.FILLED) return lmList def main(): ctime = 0 ptime = 0 cap = cv2.VideoCapture(0) detector = handDetector() while True: success, img = cap.read() img = detector.findHands(img) lmList = detector.findposition(img) if len(lmList != 0): print(lmList[4]) ctime = time.time() fps = 1 / (ctime - ptime) ptime = ctime cv2.putText(img, str(int(fps)), (10, 70), cv2.FONT_HERSHEY_PLAIN, 3, (255, 0, 255), 3) cv2.imshow("Image", img) cv2.waitKey(1) if __name__ == "__main__": main()
运行时出现以下错误:
WARNING: Logging before InitGoogleLogging() is written to STDERR
F20230316 09:19:51.302183 3056 collection.h:55] Failed to get tag "C2__PACKET" index 0
*** Check failure stack trace: ***
F20230316 09:19:51.302183 7892 collection.h:55] Failed to get tag "C2__PACKET" index 0
*** Check failure stack trace: ***
我已经尝试搜索解决方案并将MediaPipe降级到3.8.0,但问题仍未解决,请求帮助。
第一步:修复代码中的语法错误
你的代码存在两处明显逻辑/语法错误,先修正它们再排查其他问题:
- 方法名大小写错误:Python是大小写敏感语言,
detector.findposition(img)应改为detector.findPosition(img) - 判断逻辑错误:
if len(lmList != 0):应改为if len(lmList) != 0:(原写法会先判断lmList !=0得到布尔值,再取长度,逻辑完全错误)
同时补充摄像头异常处理和退出逻辑,修正后的main函数:
def main(): ctime = 0 ptime = 0 cap = cv2.VideoCapture(0) detector = handDetector() while True: success, img = cap.read() if not success: break # 处理摄像头读取失败的情况 img = detector.findHands(img) lmList = detector.findPosition(img) if len(lmList) != 0: print(lmList[4]) ctime = time.time() fps = 1 / (ctime - ptime) if (ctime - ptime) !=0 else 0 # 避免除以0的异常 ptime = ctime cv2.putText(img, str(int(fps)), (10, 70), cv2.FONT_HERSHEY_PLAIN, 3, (255, 0, 255), 3) cv2.imshow("Image", img) if cv2.waitKey(1) & 0xFF == ord('q'): # 按q键退出程序 break cap.release() cv2.destroyAllWindows()
第二步:解决MediaPipe的C2__PACKET错误
这个错误通常和底层依赖兼容性、系统环境或模型加载问题有关,尝试以下方案:
方案1:匹配MediaPipe和OpenCV的兼容版本
MediaPipe不同版本对OpenCV有明确版本要求,建议使用经过验证的组合:
- MediaPipe 0.8.10 + OpenCV 4.5.5.62
- 或MediaPipe 0.9.0 + OpenCV 4.6.0.66
执行命令重新安装指定版本:
pip uninstall -y mediapipe opencv-python pip install mediapipe==0.8.10 opencv-python==4.5.5.62
方案2:降低模型复杂度(针对Windows环境)
Windows环境下,model_complexity=1可能触发底层兼容性问题,尝试将初始化参数中的模型复杂度改为0:
detector = handDetector(model_complexity=0)
或者直接修改类的默认参数:
def __init__(self, mode=False, model_complexity=0, maxHands=2, detectionCon=0.5, trackingCon=0.5):
方案3:检查摄像头状态
- 确保摄像头没有被其他程序占用
- 尝试更换摄像头设备,或修改
cv2.VideoCapture的设备索引,比如cap = cv2.VideoCapture(1) - Windows用户请确保已安装摄像头的最新驱动
方案4:清理MediaPipe模型缓存
删除MediaPipe的本地模型缓存,让程序重新下载适配的模型文件:
- Windows路径:
C:\Users\<你的用户名>\AppData\Roaming\Python\Python<版本号>\site-packages\mediapipe\modules - 删除该目录下的手部检测相关模型文件,重新运行程序
内容的提问来源于stack exchange,提问作者VANZARA RAJAT

