Google MediaPipe:提供手势识别器 (Gesture Recognizer) 任务 DEMO实现

📅 2026/8/16 22:26:18
Google MediaPipe:提供手势识别器 (Gesture Recognizer) 任务 DEMO实现
以下是使用 Google MediaPipe Gesture Recognizer 在Python、Web (JavaScript) 和 Android三个平台上的完整 DEMO 实现。 Python 实现这是一个使用本地摄像头进行实时手势识别的 Python 脚本。1. 环境准备首先安装 MediaPipe 库pip install mediapipe2. 下载模型从 MediaPipe 官方下载训练好的手势识别模型 (gesture_recognizer.task)。你可以从 MediaPipe 官方模型页面 获取。3. 完整代码import cv2 import mediapipe as mp from mediapipe.tasks import python from mediapipe.tasks.python import vision # 模型文件路径 MODEL_PATH gesture_recognizer.task # 创建手势识别器 def create_recognizer(): base_options python.BaseOptions(model_asset_pathMODEL_PATH) options vision.GestureRecognizerOptions( base_optionsbase_options, running_modevision.RunningMode.IMAGE, # 处理单帧图像 num_hands1 # 最多检测1只手 ) return vision.GestureRecognizer.create_from_options(options) # 主函数 def main(): recognizer create_recognizer() cap cv2.VideoCapture(0) # 打开摄像头 if not cap.isOpened(): print(无法打开摄像头) return print(按 q 键退出) while True: success, frame cap.read() if not success: break # 将 OpenCV 的 BGR 图像转换为 RGB rgb_frame cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # 转换为 MediaPipe Image 对象 mp_image mp.Image(image_formatmp.ImageFormat.SRGB, datargb_frame) # 执行手势识别 recognition_result recognizer.recognize(mp_image) # 在图像上绘制结果 if recognition_result.gestures: # 获取第一个手势结果 top_gesture recognition_result.gestures[0][0] gesture_name top_gesture.category_name score top_gesture.score # 显示手势名称和置信度 cv2.putText(frame, f{gesture_name} ({score:.2f}), (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) # 绘制手部关键点 if recognition_result.hand_landmarks: for landmark in recognition_result.hand_landmarks[0]: # 将归一化坐标转换为像素坐标 x int(landmark.x * frame.shape[1]) y int(landmark.y * frame.shape[0]) cv2.circle(frame, (x, y), 5, (0, 255, 0), -1) # 显示图像 cv2.imshow(Gesture Recognizer, frame) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows() if __name__ __main__: main()官方参考完整的 Python 示例代码可在 Google Colab 上直接运行。 Web (JavaScript) 实现这是一个在浏览器中通过摄像头进行实时手势识别的 HTML 文件。1. 完整 HTML 代码创建一个index.html文件复制以下内容!DOCTYPE html html head meta charsetUTF-8 titleMediaPipe 手势识别/title !-- 引入 MediaPipe 视觉任务库 -- script srchttps://cdn.jsdelivr.net/npm/mediapipe/tasks-vision/vision_bundle.mjs crossoriginanonymous/script style body { font-family: Arial, sans-serif; text-align: center; background: #1a1a2e; color: white; padding: 20px; } video, canvas { border-radius: 12px; margin: 10px 0; max-width: 100%; } #gesture-status { font-size: 24px; font-weight: bold; padding: 16px; background: #16213e; border-radius: 12px; margin: 10px auto; display: inline-block; } #gesture-status .gesture-name { color: #a78bfa; } #gesture-status .confidence { color: #94a3b8; font-size: 18px; } #loading { color: #94a3b8; font-size: 18px; } .container { max-width: 800px; margin: 0 auto; } /style /head body div classcontainer h1✋ 手势识别演示/h1 div idloading⏳ 加载模型中.../div div idgesture-status 手势: span classgesture-name idgesture-name等待识别/span span classconfidence idconfidence/span /div div styleposition: relative; display: inline-block; video idwebcam autoplay playsinline styledisplay: none;/video canvas idoutput-canvas/canvas /div /div script // // 使用 MediaPipe Gesture Recognizer 进行实时手势识别 // 参考: https://developers.google.com/mediapipe/solutions/vision/gesture_recognizer // const video document.getElementById(webcam); const canvas document.getElementById(output-canvas); const ctx canvas.getContext(2d); const gestureNameEl document.getElementById(gesture-name); const confidenceEl document.getElementById(confidence); const loadingEl document.getElementById(loading); let gestureRecognizer null; let runningMode IMAGE; // ----- 1. 初始化手势识别器 ----- async function initGestureRecognizer() { // 使用 FilesetResolver 加载 WASM 文件 const vision await FilesetResolver.forVisionTasks( https://cdn.jsdelivr.net/npm/mediapipe/tasks-visionlatest/wasm ); gestureRecognizer await GestureRecognizer.createFromOptions( vision, { baseOptions: { // 使用官方推荐的模型文件 modelAssetPath: https://storage.googleapis.com/mediapipe-models/gesture_recognizer/gesture_recognizer/float16/1/gesture_recognizer.task }, runningMode: runningMode, numHands: 1, minHandDetectionConfidence: 0.5, minHandPresenceConfidence: 0.5, minTrackingConfidence: 0.5 } ); loadingEl.style.display none; console.log(✅ 手势识别器已加载); // 加载完成后启动摄像头 startCamera(); } // ----- 2. 启动摄像头 ----- async function startCamera() { try { const stream await navigator.mediaDevices.getUserMedia({ video: { facingMode: user, width: 640, height: 480 } }); video.srcObject stream; await video.play(); // 设置 Canvas 尺寸 canvas.width video.videoWidth; canvas.height video.videoHeight; // 开始识别循环 predictLoop(); } catch (err) { console.error(❌ 无法访问摄像头:, err); loadingEl.textContent ❌ 无法访问摄像头请检查权限; } } // ----- 3. 实时识别循环 ----- let lastTime 0; async function predictLoop() { if (!gestureRecognizer || video.readyState 2) { requestAnimationFrame(predictLoop); return; } // 每帧执行识别 const startTimeMs performance.now(); const result gestureRecognizer.recognizeForVideo(video, startTimeMs); // 绘制结果 drawResults(result); // 更新 UI updateUI(result); requestAnimationFrame(predictLoop); } // ----- 4. 绘制手部关键点 ----- function drawResults(result) { ctx.clearRect(0, 0, canvas.width, canvas.height); // 在 Canvas 上绘制视频帧作为背景 ctx.drawImage(video, 0, 0, canvas.width, canvas.height); if (!result || !result.landmarks || result.landmarks.length 0) { return; } // 绘制手部关键点和连线 const landmarks result.landmarks[0]; const connections [ [0,1], [1,2], [2,3], [3,4], // 拇指 [0,5], [5,6], [6,7], [7,8], // 食指 [0,9], [9,10], [10,11], [11,12], // 中指 [0,13], [13,14], [14,15], [15,16], // 无名指 [0,17], [17,18], [18,19], [19,20] // 小指 ]; // 绘制连线 ctx.strokeStyle #a78bfa; ctx.lineWidth 2; for (const [i, j] of connections) { const p1 landmarks[i]; const p2 landmarks[j]; ctx.beginPath(); ctx.moveTo(p1.x * canvas.width, p1.y * canvas.height); ctx.lineTo(p2.x * canvas.width, p2.y * canvas.height); ctx.stroke(); } // 绘制关键点 for (const landmark of landmarks) { ctx.beginPath(); ctx.arc( landmark.x * canvas.width, landmark.y * canvas.height, 6, 0, 2 * Math.PI ); ctx.fillStyle #8b5cf6; ctx.fill(); ctx.strokeStyle #ffffff; ctx.lineWidth 1; ctx.stroke(); } } // ----- 5. 更新 UI 显示 ----- function updateUI(result) { if (result result.gestures result.gestures.length 0) { const topGesture result.gestures[0][0]; const name topGesture.categoryName || 未知; const score (topGesture.score || 0) * 100; // 映射为更友好的名称 const displayName { None: 无手势, Closed_Fist: ✊ 拳头, Open_Palm: 张开手掌, Pointing_Up: ☝️ 食指指上, Thumb_Down: 拇指朝下, Thumb_Up: 拇指朝上, Victory: ✌️ 胜利手势, ILoveYou: 我爱你 }[name] || name; gestureNameEl.textContent displayName; confidenceEl.textContent (${score.toFixed(1)}%); } else { gestureNameEl.textContent 未检测到手势; confidenceEl.textContent ; } } // ----- 6. 启动 ----- initGestureRecognizer(); /script /body /html官方参考完整的 Web 示例代码可在 StackBlitz 上直接运行。 Android 实现Android 平台的实现需要 Android Studio 环境。1. 克隆官方示例代码git clone https://github.com/google-ai-edge/mediapipe-samples cd mediapipe-samples2. 导入项目使用 Android Studio 打开examples/gesture_recognizer/android目录。3. 核心组件官方示例包含以下关键文件文件作用GestureRecognizerHelper.kt初始化手势识别器处理模型加载和代理选择MainActivity.kt应用主入口调用识别器和结果适配器GestureRecognizerResultsAdapter.kt处理和格式化识别结果4. Gradle 依赖在build.gradle中添加以下依赖dependencies { implementation com.google.mediapipe:tasks-vision:latest.release } 支持的手势类型MediaPipe Gesture Recognizer 默认支持以下 8 种手势手势类别说明None无手势Closed_Fist✊ 拳头Open_Palm 张开手掌Pointing_Up☝️ 食指指向上方Thumb_Down 拇指朝下Thumb_Up 拇指朝上Victory✌️ 胜利手势ILoveYou 我爱你 关键配置参数在初始化识别器时可以调整以下参数参数说明默认值running_mode运行模式IMAGE(单图)、VIDEO(视频帧)、LIVE_STREAM(实时流)IMAGEnum_hands最多检测的手部数量1min_hand_detection_confidence手部检测最低置信度0.5min_tracking_confidence手部追踪最低置信度0.5 更多资源官方在线演示MediaPipe Gesture Recognizer Web Demo官方 Python ColabGesture Recognizer Python 示例官方 GitHubmediapipe-samples-手势识别任务总览Gesture Recognizer Overview