要使用 OpenCV 和 MediaPipe 识别摄像头中人物的手指数量,可以结合 MediaPipe 的手部关键点检测模型和 OpenCV 的图像处理能力。
MediaPipe 提供了高效的手部关键点检测算法,能定位 21 个手部关键点(包括手指关节和手掌位置),通过分析这些关键点的位置关系即可判断手指是否伸直。以下是具体实现步骤和代码示例:
1. 核心原理MediaPipe 手部关键点检测:
MediaPipe 的 hands 模块可以实时检测手部的 21 个关键点(如下图),包括手指关节和手掌位置。通过关键点的坐标关系,可以判断每个手指是否伸直。
手指伸直判断逻辑:
对于每个手指(如食指、中指等),检查其指尖点(如第 8、12、16、20 号关键点)是否高于其他关节点的位置。例如:如果食指的指尖(第 8 号点)的 y 坐标小于中关节(第 6 号点)的 y 坐标,则认为食指是伸直的。
2. 实现步骤(1) 安装依赖库
pip install opencv-python mediapipe(2) 完整代码
import cv2 import mediapipe as mp # 初始化 MediaPipe 手部模型 mp_hands = mp.solutions.hands hands = mp_hands.Hands( static_image_mode=False, # 视频流模式(非静态图像) max_num_hands=2, # 最多检测 2 只手 min_detection_confidence=0.5, # 检测置信度阈值 min_tracking_confidence=0.5 # 跟踪置信度阈值 ) mp_draw = mp.solutions.drawing_utils # 绘制关键点的工具 # 打开摄像头 cap = cv2.VideoCapture(0) while cap.isOpened(): ret, frame = cap.read() if not ret: break # 将图像转换为 RGB 格式(MediaPipe 要求) rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) results = hands.process(rgb_frame) if results.multi_hand_landmarks: for hand_landmarks in results.multi_hand_landmarks: # 绘制手部关键点和连线 mp_draw.draw_landmarks( frame, hand_landmarks, mp_hands.HAND_CONNECTIONS) # 提取关键点坐标 landmarks = hand_landmarks.landmark height, width, _ = frame.shape # 定义手指关键点索引(MediaPipe 的 21 个关键点) finger_tips = [4, 8, 12, 16, 20] # 指尖:大拇指、食指、中指、无名指、小指 finger_bases = [2, 6, 10, 14, 18] # 对应的基关节 count = 0 # 记录伸直的手指数量 # 遍历每个手指(大拇指单独处理) for i in range(1, 5): # 只处理食指、中指、无名指、小指 tip_y = landmarks[finger_tips[i]].y * height base_y = landmarks[finger_bases[i]].y * height # 如果指尖的 y 坐标小于基关节的 y 坐标,则认为手指伸直 if tip_y < base_y: count += 1 # 处理大拇指(判断横向位置) thumb_tip_x = landmarks[finger_tips[0]].x * width thumb_base_x = landmarks[finger_bases[0]].x * width # 根据左右手调整判断逻辑(假设检测到的是右手) if thumb_tip_x < thumb_base_x: count += 1 # 在画面中显示手指数量 cv2.putText(frame, f"Fingers: {count}", (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) # 显示画面 cv2.imshow('Finger Count', frame) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows()
3. 代码解释
初始化 MediaPipe 手部模型:
static_image_mode=False 表示处理视频流。max_num_hands=2 允许同时检测两只手。
关键点检测与绘制:
hands.process() 返回检测到的手部关键点坐标。mp_draw.draw_landmarks() 绘制关键点和手部连线。
判断手指伸直的逻辑:
对于食指、中指、无名指、小指:通过比较指尖(如第 8 号点)与基关节(如第 6 号点)的 y 坐标。对于大拇指:通过比较指尖(第 4 号点)与基关节(第 2 号点)的 x 坐标(需根据左右手调整方向)。显示结果:
在画面左上角实时显示伸直的手指数量。
4. 优化方向左右手区分:通过 results.multi_handedness 判断检测到的是左手还是右手,调整大拇指的判断逻辑。
动态阈值调整:根据手部距离摄像头的远近动态调整判断阈值。抗抖动:通过历史帧平滑手指数量结果,避免快速变化。
3D 空间判断:利用 MediaPipe 的 3D 坐标信息(landmark.z)更精确判断手指状态。
5. 效果示例
运行代码后,摄像头画面会实时显示手部关键点和伸直的手指数量:
通过这种方法,可以快速实现基于手势的交互功能(如手势控制、游戏操作等)。
网友回复
腾讯混元模型广场里都是混元模型的垂直小模型,如何api调用?
为啥所有的照片分辨率提升工具都会修改照片上的图案细节?
js如何在浏览器中将webm视频的声音分离为单独音频?
微信小程序如何播放第三方域名url的mp4视频?
ai多模态大模型能实时识别视频中的手语为文字吗?
如何远程调试别人的chrome浏览器获取调试信息?
为啥js打开新网页window.open设置窗口宽高无效?
浏览器中js的navigator.mediaDevices.getDisplayMedia屏幕录像无法录制SpeechSynthesisUtterance产生的说话声音?
js中mediaRecorder如何录制window.speechSynthesis声音音频并下载?
python如何直接获取抖音短视频的音频文件url?