
MediaPipe 手势识别实战指南21 个手部关键点如何跑进你的项目【免费下载链接】mediapipeCross-platform, customizable ML solutions for live and streaming media.项目地址: https://gitcode.com/GitHub_Trending/med/mediapipe如果你的产品需要看懂用户的手——空中点按、虚拟键盘、手语辅助工具——MediaPipe 手势识别模块值得作为第一站它对单帧图像直接回归 21 个 3D 手部关键点单帧延迟足够低能在手机上实时跑通且默认就支持多手。读完这篇指南你会拿到四样东西一个 30 秒能跑起来的最小示例、一套为什么它这么快的原理拆解、三端Python / Web / Android接入时的参数差异以及按故障场景分组的问题排查表。最小可运行示例摄像头画出 21 个关键点结论先行Python 端十几行代码就能从摄像头拿到归一化关键点坐标剩下的都是调参。关键点索引是固定约定记一次终身受用索引含义0手腕1–4拇指5–8食指9–12中指13–16无名指17–20小指import cv2 import mediapipe as mp mp_hands mp.solutions.hands with mp_hands.Hands( static_image_modeFalse, # 视频流模式帧间复用不再每帧重检测 max_num_hands2, # 最多跟踪两只手默认值 model_complexity1, # 0 轻量 / 1 高精度默认 1 min_detection_confidence0.5, min_tracking_confidence0.5) as hands: cap cv2.VideoCapture(0) while cap.isOpened(): ok, frame cap.read() if not ok: continue # 输入前必须转成 RGB results hands.process(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)) if results.multi_hand_landmarks: # 每只手 21 个点x/y 已按宽高归一化到 [0,1] tip results.multi_hand_landmarks[0].landmark[8] # 8 号点 食指指尖 print(tip.x, tip.y)⚠️ 两个容易踩的坑一是hands.process()只吃 RGBOpenCV 读出来是 BGR二是z值的原点在手腕数值越小表示越靠近相机。原理拆解两段式流水线为什么快它快的核心不是单模型很强而是能偷懒就不重新检测。整条链路是两个模型协作手掌检测模型palm_detection_gpu.pbtxt对全图做单阶段检测输出带朝向的手部框。官方评测平均精度 95.7%朴素交叉熵基线只有 86.22%差距主要来自编码器-解码器结构带来的大场景上下文以及 focal loss 对大尺度差异手掌在画面中可差约 20 倍的容忍。手部关键点模型hand_landmark_gpu.pbtxt只处理裁剪后的小图直接回归 21 个 3D 坐标。裁剪对齐后网络几乎不用做旋转/平移/尺度补偿容量全部花在坐标精度上。帧间策略是关键画成时序更清楚训练数据也决定了它的鲁棒性约 3 万张真实图像由人工标注了 21 个 3D 坐标再叠加在多种背景上渲染的合成手模型对部分可见、手指自遮挡的手部姿态都有监督。移动端 GPU 版整张图hand_tracking_mobile.pbtxt里还串了一个FlowLimiterCalculator把在途图像压到约 1 张防止下游积压造成延迟和内存上涨——你在日志里看到的丢帧是它有意为之不是 bug。关键参数速查先懂这 5 个开关再调参参数默认值作用调法建议static_image_modefalsefalse按视频流处理跟踪优先true每帧都重检测批处理静态图才开truemax_num_hands2检测/跟踪上限多人场景按硬件预算上调model_complexity1关键点模型档位0快但略粗1精度高端侧吃紧降到0min_detection_confidence0.5检测结果生效的最低置信度误检多就调高漏检多就调低min_tracking_confidence0.5跟踪成功阈值低于它则触发重新检测抖动大调高代价是延迟static_image_modetrue时忽略输出端除了multi_hand_landmarks归一化坐标还有multi_hand_world_landmarks以手几何中心为原点、单位米的真实 3D 坐标和multi_handedness左/右手标签 概率。注意 handedness 默认假设输入是镜像自拍摄像头如果你喂的是原始未翻转画面需要自己把左右结果对调。跨平台接入差异Web 与 Android 怎么接三端参数命名基本对齐Web 用驼峰主要差别在输入管线和渲染路径。Web 端模型文件通过locateFile指定加载位置生产环境建议放本地或自建 CDN避免每次运行拉远端资源const hands new Hands({ locateFile: (file) ./hands/${file} // 指向本地模型目录 }); hands.setOptions({ maxNumHands: 2, modelComplexity: 1, minDetectionConfidence: 0.5, minTrackingConfidence: 0.5 }); hands.onResults((results) { // results.multiHandLandmarks每只手 21 个 {x, y, z} });Android 端核心是HandsOptionssend()送帧。GPU 渲染场景用CameraInput直接送TextureFrame省掉一次纹理到 Bitmap 的拷贝HandsOptions options HandsOptions.builder() .setStaticImageMode(false) // 视频流模式 .setMaxNumHands(2) .setRunOnGpu(true) // 移动端建议 GPU .build(); Hands hands new Hands(this, options); CameraInput cameraInput new CameraInput(this); cameraInput.setNewFrameListener(frame - hands.send(frame)); hands.setResultListener(result - { // 第 8 个点 食指指尖坐标已归一化 NormalizedLandmark tip result.multiHandLandmarks().get(0).getLandmarkList().get(8); Log.i(TAG, index tip: tip.getX() , tip.getY()); });Android 还区分图像输入Bitmap ImageView 绘制与视频输入VideoInput GLSurfaceView 渲染完整工程可参考仓库内 Android 手部示例 与 桌面端示例。桌面端若要本地构建git clone https://gitcode.com/GitHub_Trending/med/mediapipe cd mediapipe ./build_desktop_examples.sh hand_tracking常见问题速查按场景分组排查不是按十大问题罗列按你实际会遇到的场景对号入座。场景一帧率上不去 / 延迟高先把model_complexity降到0再降输入分辨率640×480 足够确认没有绕过FlowLimiterCalculator——自定义图里去掉限流节点会让延迟翻倍GPU 可用时优先 GPU 图hand_tracking_mobile.pbtxt这类CPU 图留给降级路径。场景二手指被遮就丢手遮挡时跟踪置信度会跌破阈值并触发重检测属正常行为把min_tracking_confidence适当调低可容忍更多遮挡代价是跟踪漂移风险上升关键点模型本身对部分可见的手有合成数据监督轻度自遮挡一般不丢丢的通常是手整只手出画。场景三双手交叉后左右标签乱跳输出里的multi_handedness自带左右判定别用哪只手在画面左边这种空间位置自己猜先确认镜像问题自拍摄像头喂原始画面时左右标签要自己对调。场景四强光/弱光下检测不稳检测阶段对低对比度敏感优先保证输入亮度均匀而不是在业务层堆阈值阈值别一个方向拧到底漏检调低min_detection_confidence误检调高两边同时压会两头不讨好。场景五静态图批量处理结果异常处理互不相关的图片批次时static_image_mode必须为true否则帧间跟踪状态会串到上一张图上。进阶训练你自己的手势分类器21 个关键点只是骨架要做比心OK石头剪刀布这类语义判断正确姿势是再叠一层分类器而不是手写一堆距离阈值。仓库里自带 Model Maker 的手势识别器训练样本直接可用训练入口在 gesture_recognizer 目录gesture_recognizer_demo.py是可跑通的示例脚本产出.tflite后走新的 Tasks API 推理比 Legacy Solutions 更轻量import mediapipe as mp base_options mp.tasks.BaseOptions( model_asset_pathgesture_recognizer.tflite) # 本地模型免下载 options mp.tasks.vision.GestureRecognizerOptions( base_optionsbase_options, num_hands2) with mp.tasks.vision.GestureRecognizer.create_from_options(options) as rec: result rec.detect(mp.Image.create_from_file(hand.jpg)) for hand in result.handedness: # 每只手的分类结果 print(hand[0].category_name, hand[0].score) 经验值分类器训练时每个手势至少准备几十个多样本不同光照、角度样本目录结构直接照抄 testdata 下rock/、four/的组织方式即可。资源索引与下一步想做什么去哪里查参数定义与三端 API官方文档Hands改检测/关键点子图hand_landmark 模块、palm_detection 模块改整张执行图限流/渲染hand_tracking 图目录调试计算图Visualizer 文档新 APIHandLandmarker / GestureRecognizertasks Python 包接下来建议做三件事在自己设备上量一次 P95 帧延迟把static_image_mode、model_complexity两档跑一遍对比精度损失最后把手势分类器接到你的业务手势上。这三步走完延迟、丢手、误判这三个最常见的坑基本就摸清了。【免费下载链接】mediapipeCross-platform, customizable ML solutions for live and streaming media.项目地址: https://gitcode.com/GitHub_Trending/med/mediapipe创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考