)
前言利用摄像头实时捕捉手部动作通过MediaPipe提取21个关键点识别0~5个手指的抬起数量并映射为播放、暂停、继续等音乐控制指令。项目结合OpenCV图像处理、MediaPipe深度学习推理和PyGame音频播放实现零接触的趣味交互。适合作为AI入门、OpenCV实践或趣味小工具开发的学习案例。目录一、项目背景与功能二、技术选型三、实现原理1. 手部关键点提取2. 手势数字识别0~53. 音乐控制逻辑4. 冷却机制四、代码详解核心部分4.1 配置与初始化4.2 手势计数函数4.3 动作执行带冷却4.4 主循环 – 摄像头实时推理五、运行效果六、可优化与扩展方向七、总结一、项目背景与功能在智能家居、人机交互日益普及的今天手势控制成为一种自然、直观的交互方式。本项目实现了一个简单的手势音乐播放器举起2根手指→ 播放/切换歌曲拳头0根手指→ 暂停当前播放五指张开5根手指→ 继续播放取消暂停其他手势1、3、4仅显示数字可自由扩展。所有动作均带有冷却时间默认1秒防止误触发。二、技术选型库/框架作用OpenCV (cv2)摄像头调用、图像处理、界面显示MediaPipe手部关键点检测21个landmarksPyGame (mixer)音乐文件的加载、播放、暂停/继续控制Python标准库time, os冷却计时、文件路径检查三、实现原理import cv2 #图像处理 import mediapipe as mp #AI手部的关键监测点 import pygame #音乐视频媒体播放控制 import time #音频播放控制 import os #冷却时间路径 # 配置 SONG_PATH 我本将心向明月.mp3 # 可以修改为你的音乐存放的路径 COOLDOWN 1.0 # 动作冷却时间秒防止反复触发 # 初始化 Pygame 音乐播放器 pygame.mixer.init() if not os.path.exists(SONG_PATH): print(f警告歌曲文件不存在 - {SONG_PATH}) print(请将音乐文件放在脚本同目录下或修改 SONG_PATH 变量。) # 初始化 MediaPipe Hands mp_hands mp.solutions.hands hands mp_hands.Hands( static_image_modeFalse, max_num_hands1, min_detection_confidence0.5, min_tracking_confidence0.5 ) mp_drawing mp.solutions.drawing_utils # 手势识别函数 def count_fingers(landmarks): 通过手部关键点计算抬起的手指数量0~5 基于指尖与指根的相对位置y坐标或x坐标 # 手指索引(指尖, 指根, 是否拇指) finger_indices [ (4, 2, True), # 拇指 (8, 5, False), # 食指 (12, 9, False), # 中指 (16, 13, False),# 无名指 (20, 17, False) # 小指 ] count 0 for tip_idx, mcp_idx, is_thumb in finger_indices: tip landmarks[tip_idx] mcp landmarks[mcp_idx] if is_thumb: # 拇指判断横向位移伸直时与指根距离较大 if abs(tip.x - mcp.x) 0.05: count 1 else: # 其他手指指尖在上方y更小且纵向距离大于阈值 if tip.y mcp.y and (mcp.y - tip.y) 0.05: count 1 return count # 动作执行函数 def handle_gesture(gesture_num): global last_trigger_time now time.time() if now - last_trigger_time COOLDOWN: return last_trigger_time now if gesture_num 2: # 播放歌曲 if pygame.mixer.music.get_busy(): pygame.mixer.music.stop() try: pygame.mixer.music.load(SONG_PATH) pygame.mixer.music.play() print(f 正在播放歌曲{os.path.basename(SONG_PATH)}) except Exception as e: print(f播放失败{e}) elif gesture_num 0: # 拳头 → 暂停 if pygame.mixer.music.get_busy(): pygame.mixer.music.pause() print(⏸️ 暂停播放) else: print(当前没有播放的音乐) elif gesture_num 5: # 五指张开 → 继续播放 if pygame.mixer.music.get_busy(): pygame.mixer.music.unpause() print(▶️ 继续播放) else: print(没有暂停的音乐) else: # 其他手势可自定义如 1、3、4 print(f手势数字{gesture_num}未定义动作) # 主循环 cap cv2.VideoCapture(0) if not cap.isOpened(): print(无法打开摄像头) exit() last_gesture None last_trigger_time 0 print( 手势识别已启动请面对摄像头做手势0~5) print(指令映射2播放歌曲0暂停5继续) while cap.isOpened(): success, frame cap.read() if not success: continue # 镜像翻转便于操作 frame cv2.flip(frame, 1) rgb cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) result hands.process(rgb) gesture_num None if result.multi_hand_landmarks: for hand_landmarks in result.multi_hand_landmarks: # 绘制手部关键点 mp_drawing.draw_landmarks(frame, hand_landmarks, mp_hands.HAND_CONNECTIONS) # 识别手势 gesture_num count_fingers(hand_landmarks.landmark) # 显示当前手势数字 cv2.putText(frame, fGesture: {gesture_num}, (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) # 若手势变化且不为空触发动作 if gesture_num ! last_gesture: handle_gesture(gesture_num) last_gesture gesture_num cv2.imshow(Gesture Music Control, frame) if cv2.waitKey(1) 0xFF ord(q): break # 释放资源 cap.release() cv2.destroyAllWindows() hands.close() pygame.mixer.quit()实现效果如下1. 手部关键点提取MediaPipe Hands 模型会返回每只手的21个标准化坐标 (x, y, z)。我们利用这些坐标判断每根手指是否“抬起”。2. 手势数字识别0~5手指抬起判断规则拇指通过指尖landmark 4与指根landmark 2的横向距离x差值是否大于阈值0.05。其余四指指尖landmark 8,12,16,20的y坐标是否小于指根landmark 5,9,13,17的y坐标且纵向距离大于0.05。累计抬起的手指数量即为手势数字。3. 音乐控制逻辑通过pygame.mixer.music模块load()play()→ 开始播放pause()→ 暂停unpause()→ 继续stop()→ 停止用于切换歌曲时重置4. 冷却机制使用time.time()记录上次触发时间若当前时间与上次触发时间差小于COOLDOWN1秒则忽略重复触发避免频繁操作。四、代码详解核心部分4.1 配置与初始化SONG_PATH 我本将心向明月.mp3 # 你的音乐文件路径 COOLDOWN 1.0 pygame.mixer.init() mp_hands mp.solutions.hands hands mp_hands.Hands(static_image_modeFalse, max_num_hands1, min_detection_confidence0.5, min_tracking_confidence0.5)4.2 手势计数函数def count_fingers(landmarks): finger_indices [(4, 2, True), (8, 5, False), ...] # (指尖, 指根, 是否拇指) count 0 for tip_idx, mcp_idx, is_thumb in finger_indices: tip landmarks[tip_idx] mcp landmarks[mcp_idx] if is_thumb: if abs(tip.x - mcp.x) 0.05: count 1 else: if tip.y mcp.y and (mcp.y - tip.y) 0.05: count 1 return count4.3 动作执行带冷却def handle_gesture(gesture_num): global last_trigger_time if time.time() - last_trigger_time COOLDOWN: return last_trigger_time time.time() # 根据gesture_num分别处理 2、0、54.4 主循环 – 摄像头实时推理读取帧 → 镜像翻转 → 转RGB → 送入MediaPipe如果检测到手则绘制关键点并调用count_fingers若手势变化gesture_num ! last_gesture则触发动作在画面左上角显示当前手势数字按q退出五、运行效果运行脚本后摄像头窗口会实时显示手部骨架连线并标注当前手势数字。当你做出对应手势时控制台会输出操作日志音乐随之响应。注意请确保音乐文件与脚本在同一目录或修改SONG_PATH为绝对路径。若文件不存在程序会给出警告。六、可优化与扩展方向多手势自定义目前只用了0、2、5你可以将1、3、4映射为音量加减、上一首/下一首等。支持多首歌曲列表通过手势切换播放列表。提高鲁棒性增加手势稳定性过滤如连续多帧相同才触发。界面美化添加半透明GUI显示当前播放状态和歌曲名。打包成exe使用PyInstaller打包方便无Python环境的用户使用。七、总结本项目以极简代码不到150行实现了有趣的手势音乐控制涵盖了计算机视觉、深度学习推理和音频控制三大技术点非常适合初学者上手实践。你可以在此基础上加入更多创意功能打造属于自己的“隔空指挥”系统。