Python新手求助:Mediapipe手部检测失效,仅摄像头启动无检测
Mediapipe手部检测无响应问题修复
问题描述
启动摄像头后仅显示画面,无法检测手部或执行计数功能,控制台仅输出正常初始化日志:
INFO: Created TensorFlow Lite XNNPACK delegate for CPU.
用户实现代码:
import cv2 import mediapipe as mp cap = cv2.VideoCapture(0) mp_hands = mp.solutions.hands mp_drawing = mp.solutions.drawing_utils hands = mp_hands.Hands(min_detection_confidence=0.8, min_tracking_confidence=0.5) tipIds = [4, 8, 12, 16, 20] def countFingers(image, hand_landmarks, handNo=0): if hand_landmarks: # Get all Landmarks of the FIRST Hand VISIBLE landmarks = hand_landmarks[handNo].landmark # print(landmarks) # Count Fingers fingers = [] for lm_index in tipIds: # Get Finger Tip and Bottom y Position Value finger_tip_y = landmarks[lm_index].y finger_bottom_y = landmarks[lm_index - 2].y # Check if ANY FINGER is OPEN or CLOSED if lm_index !=4: if finger_tip_y < finger_bottom_y: fingers.append(1) print("FINGER with id ",lm_index," is Open") if finger_tip_y > finger_bottom_y: fingers.append(0) print("FINGER with id ",lm_index," is Closed") # print(fingers) totalFingers = fingers.count(1) # Display Text text = f'Fingers: {totalFingers}' cv2.putText(image, text, (50,50), cv2.FONT_HERSHEY_SIMPLEX, 1, (255,0,0), 2) def drawHandLanmarks(image, hand_landmarks): # Darw connections between landmark points if hand_landmarks: for landmarks in hand_landmarks: mp_drawing.draw_landmarks(image, landmarks, mp_hands.HAND_CONNECTIONS) while True: success, image = cap.read() image = cv2.flip(image, 1) # Detect the Hands Landmarks results = hands.process(image) # Get landmark position from the processed result hand_landmarks = results.multi_hand_landmarks # Draw Landmarks drawHandLanmarks(image, hand_landmarks) # Get Hand Fingers Position countFingers(image, hand_landmarks) cv2.imshow("Media Controller", image) key = cv2.waitKey(1) if key == 32: break cv2.destroyAllWindows()
问题根源与修复步骤
1. 颜色空间不匹配(核心问题)
Mediapipe手部检测模型要求输入RGB格式图像,但OpenCV默认读取的是BGR格式,直接传入会导致检测完全失效。
修复:调用hands.process()前,将图像从BGR转为RGB:
# 转换颜色空间 image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) results = hands.process(image_rgb)
2. 拇指判断逻辑缺失
原代码跳过了拇指(id=4)的判断,且拇指的张开/闭合判断逻辑与其他手指不同,需对比x坐标而非y坐标(镜像后左手拇指张开时x值更小)。
修复:在countFingers函数中补充拇指判断逻辑:
for lm_index in tipIds: if lm_index == 4: # 拇指:对比指尖和指根的x坐标 finger_tip_x = landmarks[lm_index].x finger_bottom_x = landmarks[lm_index - 2].x if finger_tip_x < finger_bottom_x: fingers.append(1) print("拇指 已张开") else: fingers.append(0) print("拇指 已闭合") else: # 其他手指:对比y坐标 finger_tip_y = landmarks[lm_index].y finger_bottom_y = landmarks[lm_index - 2].y if finger_tip_y < finger_bottom_y: fingers.append(1) print(f"手指id {lm_index} 已张开") else: fingers.append(0) print(f"手指id {lm_index} 已闭合")
3. 手部索引越界防护
当仅检测到1只手时,若handNo设置为1会触发索引错误,需先判断手的数量。
修复:在获取landmarks前添加判断:
if hand_landmarks: # 检查指定的手是否存在 if handNo >= len(hand_landmarks): return landmarks = hand_landmarks[handNo].landmark
修复后完整代码
import cv2 import mediapipe as mp cap = cv2.VideoCapture(0) mp_hands = mp.solutions.hands mp_drawing = mp.solutions.drawing_utils hands = mp_hands.Hands(min_detection_confidence=0.8, min_tracking_confidence=0.5) tipIds = [4, 8, 12, 16, 20] def countFingers(image, hand_landmarks, handNo=0): if hand_landmarks: # 检查指定的手是否存在 if handNo >= len(hand_landmarks): return landmarks = hand_landmarks[handNo].landmark fingers = [] for lm_index in tipIds: if lm_index == 4: # 拇指判断逻辑:对比x坐标 finger_tip_x = landmarks[lm_index].x finger_bottom_x = landmarks[lm_index - 2].x if finger_tip_x < finger_bottom_x: fingers.append(1) print("拇指 已张开") else: fingers.append(0) print("拇指 已闭合") else: # 其他手指判断逻辑:对比y坐标 finger_tip_y = landmarks[lm_index].y finger_bottom_y = landmarks[lm_index - 2].y if finger_tip_y < finger_bottom_y: fingers.append(1) print(f"手指id {lm_index} 已张开") else: fingers.append(0) print(f"手指id {lm_index} 已闭合") totalFingers = fingers.count(1) text = f'手指数量: {totalFingers}' cv2.putText(image, text, (50,50), cv2.FONT_HERSHEY_SIMPLEX, 1, (255,0,0), 2) def drawHandLanmarks(image, hand_landmarks): if hand_landmarks: for landmarks in hand_landmarks: mp_drawing.draw_landmarks(image, landmarks, mp_hands.HAND_CONNECTIONS) while True: success, image = cap.read() if not success: break image = cv2.flip(image, 1) # 转换为RGB格式后再传入Mediapipe image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) results = hands.process(image_rgb) hand_landmarks = results.multi_hand_landmarks drawHandLanmarks(image, hand_landmarks) countFingers(image, hand_landmarks) cv2.imshow("手部检测", image) key = cv2.waitKey(1) if key == 32: # 按空格键退出 break cap.release() # 释放摄像头资源 cv2.destroyAllWindows()
补充说明
- 控制台输出的
INFO: Created TensorFlow Lite XNNPACK delegate for CPU是正常日志,说明TensorFlow Lite已成功初始化加速组件,不是错误。 - 若仍无法检测,可适当降低
min_detection_confidence和min_tracking_confidence的值(比如调到0.5),提升检测灵敏度。
内容的提问来源于stack exchange,提问作者Ditto Prior
相关产品推荐
相关产品推荐

