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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 03:57:05