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

使用MediaPipe实时手势识别报错:NameError: name 'mp_image' is not defined

问题分析与修复

核心错误原因

NameError 是因为 mp_image 仅在检测到手部特征的代码块内定义,当某一帧没有检测到手时,这个变量未被初始化,后续调用 cv2.putText 就会报错。除此之外,代码还有几处逻辑问题需要修正:

修复步骤

  1. 提前初始化mp_image:将mp_image的创建移到手部检测逻辑之外,确保每一帧都能生成该变量,避免未定义问题。
  2. 修正cv2.putText的操作对象:cv2.putText只能处理OpenCV的numpy数组格式帧(即frame),不能直接操作MediaPipe的mp.Image对象。
  3. 补充recognize_async的时间戳参数:使用LIVE_STREAM模式时,必须传入timestamp_ms参数,可通过cap.get(cv2.CAP_PROP_POS_MSEC)获取当前帧的时间戳。
  4. 避免变量名冲突:将手部检测的结果变量名改为hand_results,防止覆盖手势识别相关数据。
  5. 异步结果的保存与读取:LIVE_STREAM模式下,手势识别结果通过回调函数返回,需要用全局变量保存最新结果,再在主循环中读取并显示。

修改后的完整代码

import cv2
import mediapipe as mp
from mediapipe.tasks import python
from mediapipe.tasks.python import vision

# 全局变量保存最新手势识别结果
latest_gesture_result = None

model_path = "gesture_recognizer.task"
GestureRecognizer = mp.tasks.vision.GestureRecognizer
GestureRecognizerOptions = mp.tasks.vision.GestureRecognizerOptions
GestureRecognizerResult = mp.tasks.vision.GestureRecognizerResult
VisionRunningMode = mp.tasks.vision.RunningMode

def print_result(result: GestureRecognizerResult, output_image: mp.Image, timestamp_ms: int):
    global latest_gesture_result
    latest_gesture_result = result
    print('gesture recognition result: {}'.format(result))

options = GestureRecognizerOptions(
    base_options=python.BaseOptions(model_asset_path=model_path),
    running_mode=VisionRunningMode.LIVE_STREAM,
    result_callback=print_result)
recognizer = GestureRecognizer.create_from_options(options)

mp_drawing = mp.solutions.drawing_utils
mp_hands = mp.solutions.hands
hands = mp_hands.Hands(
        static_image_mode=False,
        max_num_hands=2,
        min_detection_confidence=0.65,
        min_tracking_confidence=0.65)

cap = cv2.VideoCapture(0)

while True:
    ret, frame = cap.read()
    if not ret:
        break
        
    # 转换颜色空间,处理手部检测
    frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    hand_results = hands.process(frame_rgb)
    
    # 创建MediaPipe Image对象,确保每一帧都初始化
    mp_image = mp.Image(image_format=mp.ImageFormat.SRGB, data=frame_rgb)
    
    # 获取当前帧时间戳,传入异步识别函数
    timestamp = int(cap.get(cv2.CAP_PROP_POS_MSEC))
    recognizer.recognize_async(mp_image, timestamp)
    
    # 绘制手部特征点
    if hand_results.multi_hand_landmarks:
        for hand_landmarks in hand_results.multi_hand_landmarks:
            mp_drawing.draw_landmarks(frame, hand_landmarks, mp_hands.HAND_CONNECTIONS)
    
    # 显示手势识别结果
    if latest_gesture_result and latest_gesture_result.gestures:
        # 获取置信度最高的手势
        top_gesture = latest_gesture_result.gestures[0][0]
        gesture_text = f"{top_gesture.category_name} ({top_gesture.score:.2f})"
        cv2.putText(frame, gesture_text, (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 
                   1, (0,0,255), 2, cv2.LINE_AA)
    
    cv2.imshow('MediaPipe Hands', frame)

    if cv2.waitKey(1) & 0xFF == 27:
        break

cap.release()
cv2.destroyAllWindows()

额外说明

  • 全局变量latest_gesture_result用于存储回调函数返回的最新识别结果,确保主循环能获取到异步处理后的手势数据。
  • 显示结果时,取置信度最高的手势类别和分数,让显示内容更直观。
  • 最后调用cv2.destroyAllWindows()避免程序退出后残留窗口。

内容的提问来源于stack exchange,提问作者rajtilakjee

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 17:35:11