基于 MediaPipe 的“指尖命令”:用手势控制你的电脑

作者: GDragon-creator
发布时间: 2025年5月31日
GitHub 仓库: https://github.com/GDragon-creator/bug-free-memory
关键词: MediaPipe, 手势识别, PyAutoGUI, Python, 自动化控制, GUI

一、前言

在日常电脑操作中,频繁切换键盘和鼠标可能会打断你的工作流,尤其是在演示文稿、媒体播放或需要快速交互的场景中。为了解决这一痛点,我开发了“指尖命令”——一款基于 Google MediaPipe 手部追踪技术和 PyAutoGUI 自动化库的创新应用。通过简单的手势(伸出1至5根手指),你可以轻松控制键盘按键、组合键、鼠标滚动或点击,彻底解放双手,提升效率。

本文将详细介绍“指尖命令”的功能、架构、安装与使用方法,并分享其核心代码实现。如果你对计算机视觉、自动化控制或 Python 开发感兴趣,欢迎体验并为项目贡献代码!点击访问 GitHub 仓库


二、项目简介

“指尖命令”是一款通过摄像头捕捉手势,结合 MediaPipe 进行手部关键点检测,并通过 PyAutoGUI 执行用户定义的操作的应用程序。它支持以下核心功能:

  • 高度可定制:为1至5指手势绑定键盘按键、组合键、鼠标滚动或点击。
  • 多语言支持:支持简体中文、繁体中文和英文界面,自动适配系统语言。
  • 实时反馈:摄像头窗口显示手部关键点、指数字和左右手信息。
  • 防抖机制:通过0.25秒手势保持时间和0.4秒操作间隔避免误触发。
  • 便捷退出:双手举起3秒或按 ESC 键快速退出。
  • 配置管理:支持保存、导入、导出配置,方便备份和分享。

无论是用于媒体播放控制、PPT翻页,还是其他需要快捷操作的场景,“指尖命令”都能带来流畅的体验。


三、系统架构

“指尖命令”采用模块化设计,包含以下核心模块:

1. 图形界面模块(Tkinter)

  • 功能:提供直观的 GUI,用于配置手势绑定、语言切换和状态显示。
  • 实现:使用 Tkinter 创建主窗口,包含菜单栏(选项、语言、关于)、手势配置面板和状态栏。支持多语言动态切换,保存配置到 settings.json 和 config.ini。
1.def setup_gui():  
2.    global gui_root, status_label, action_labels, set_buttons, title_label, control_header, start_button, menubar, options_menu, about_menu, language_menu  
3.    # 初始化 config.ini 文件  
4.    config = configparser.ConfigParser()  
5.    if not os.path.exists("config.ini"):  
6.        config.add_section("Settings")  
7.        config.set("Settings", "language", "zh-CN")  
8.        with open("config.ini", "w", encoding="utf-8") as configfile:  
9.            config.write(configfile)  
10.    load_settings()  
11.    gui_root = tk.Tk()  
12.    gui_root.title(translations[current_language]["title"])  
13.    # 添加菜单栏  
14.    menubar = tk.Menu(gui_root)  
15.    gui_root.config(menu=menubar)  
16.    options_menu = tk.Menu(menubar, tearoff=0)  
17.    language_menu = tk.Menu(menubar, tearoff=0)  
18.    about_menu = tk.Menu(menubar, tearoff=0)  
19.    menubar.add_cascade(label=translations[current_language]["options_menu"], menu=options_menu)  
20.    # ... 菜单项配置 ...  
21.    # 设置窗口大小和背景颜色  
22.    gui_root.geometry("700x600")  
23.    gui_root.configure(bg=neutral_bg)  
24.    # 样式配置  
25.    style = ttk.Style()  
26.    style.theme_use('clam')  
27.    style.configure(".", font=("SimHei", 10), background=neutral_bg)  
28.    # ... 其他样式配置 ...  
29.    # 创建主框架和控件  
30.    main_frame = ttk.Frame(gui_root, padding="20")  
31.    main_frame.pack(fill=tk.BOTH, expand=True)  
32.    title_label = ttk.Label(title_frame, text=translations[current_language]["title"], style="Title.TLabel")  
33.    # ... 其他控件初始化 ...  

2. 手势识别模块(MediaPipe)

  • 功能:实时检测最多两只手,识别1-5根手指和左右手方向。
  • 实现:使用 MediaPipe Hands 模块处理摄像头帧,count_fingers 函数通过关键点坐标判断手指伸展状态,动态阈值确保准确性。
1.def count_fingers(lst, handedness_label="Unknown"):  
2.    cnt = 0  
3.    if not lst or not lst.landmark:  
4.        return 0  
5.    try:  
6.        vertical_thresh = abs(lst.landmark[0].y - lst.landmark[9].y) / 2.8  
7.        if (lst.landmark[5].y - lst.landmark[8].y) > vertical_thresh:  
8.            cnt += 1  # 食指  
9.        if (lst.landmark[9].y - lst.landmark[12].y) > vertical_thresh:  
10.            cnt += 1  # 中指  
11.        # ... 其他手指 ...  
12.        thumb_horizontal_ref_dist = abs(lst.landmark[5].x - lst.landmark[17].x)  
13.        thumb_thresh = thumb_horizontal_ref_dist * 0.3  
14.        if handedness_label == "Left":  
15.            if (lst.landmark[4].x - lst.landmark[2].x) > thumb_thresh:  
16.                cnt += 1  
17.        elif handedness_label == "Right":  
18.            if (lst.landmark[2].x - lst.landmark[4].x) > thumb_thresh:  
19.                cnt += 1  
20.    except Exception as e:  
21.        print(f"手指计数错误: {e}")  
22.        return 0  
23.    return cnt  
24.  
25.# 主循环中的手势检测  
26.cap = cv2.VideoCapture(0)  
27.hands_module = mp.solutions.hands  
28.hand_obj = hands_module.Hands(max_num_hands=2, min_detection_confidence=0.7, min_tracking_confidence=0.6)  
29.while True:  
30.    ret, frm = cap.read()  
31.    if not ret:  
32.        print(translations[current_language]["frame_error"])  
33.        break  
34.    frm = cv2.flip(frm, 1)  
35.    rgb_frm = cv2.cvtColor(frm, cv2.COLOR_BGR2RGB)  
36.    res = hand_obj.process(rgb_frm)  
37.    if res.multi_hand_landmarks:  
38.        num_hands_detected = len(res.multi_hand_landmarks)  
39.        for i, hand_landmarks in enumerate(res.multi_hand_landmarks):  
40.            drawing.draw_landmarks(frm, hand_landmarks, hands_module.HAND_CONNECTIONS)  
41.        if num_hands_detected == 1:  
42.            hand_keyPoints = res.multi_hand_landmarks[0]  
43.            handedness_info = res.multi_handedness[0].classification[0]  
44.            current_handedness_label = handedness_info.label  
            cnt = count_fingers(hand_keyPoints, current_handedness_label)

3. 操作执行模块(PyAutoGUI、Pynput)

  • 功能:根据手势执行绑定的键盘或鼠标操作,捕获用户输入用于配置。
  • 实现:PyAutoGUI 模拟按键、组合键、鼠标点击和滚动;Pynput 捕获键盘和鼠标输入,防抖机制确保操作精准。
1.def on_key_press(key_event):  
2.    global capturing_for_finger, current_keys  
3.    if capturing_for_finger is None:  
4.        return  
5.    try:  
6.        if hasattr(key_event, 'vk') and 65 <= key_event.vk <= 90:  
7.            key_name = chr(key_event.vk).lower()  
8.        # ... 其他按键处理 ...  
9.        current_keys.add(key_name)  
10.    except Exception as e:  
11.        print(f"键处理错误: {e}")  
12.  
13.def on_key_release(key_event):  
14.    global capturing_for_finger  
15.    if capturing_for_finger is None:  
16.        return  
17.    action_type = 'key' if len(current_keys) == 1 else 'combo'  
18.    action = {'type': action_type, 'value': format_keys(current_keys)}  
19.    update_action_display_and_clear_conflicts(capturing_for_finger, action)  
20.    stop_capture_mode()  
21.  
22.# 主循环中的操作执行  
23.if start_init and (current_time - action_gesture_start_time) > action_hold_time:  
24.    action_to_perform = finger_actions.get(cnt)  
25.    if action_to_perform:  
26.        if (current_time - last_action_time) > min_action_interval:  
27.            try:  
28.                if action_to_perform['type'] == 'key':  
29.                    pyautogui.press(action_to_perform['value'])  
30.                elif action_to_perform['type'] == 'combo':  
31.                    keys_to_press = action_to_perform['value'].split('+')  
32.                    for k_val in keys_to_press:  
33.                        pyautogui.keyDown(k_val)  
34.                    for k_val in reversed(keys_to_press):  
35.                        pyautogui.keyUp(k_val)  
36.                elif action_to_perform['type'] == 'mouse_scroll':  
37.                    if action_to_perform['value'] == 'scroll_up':  
38.                        pyautogui.scroll(120)  
39.                    elif action_to_perform['value'] == 'scroll_down':  
40.                        pyautogui.scroll(-120)  
41.                elif action_to_perform['type'] == 'mouse_click':  
42.                    button_val = action_to_perform['button'].replace('Button.', '')  
43.                    pyautogui.click(button=button_val)  
44.                last_action_time = current_time  
45.            except Exception as e:  
                print(f"使用 pyautogui 执行操作时出错: {e}")

4. 配置管理模块

  • 功能:管理手势绑定和语言设置,持久化到 settings.json 和 config.ini。
  • 实现:JSON 格式存储手势映射,configparser 管理语言偏好,支持导入/导出。
1.def save_settings():  
2.    global finger_actions  
3.    try:  
4.        settings = {str(i): finger_actions[i] for i in range(1, 6)}  
5.        with open("settings.json", "w", encoding="utf-8") as f:  
6.            json.dump(settings, f, indent=4, ensure_ascii=False)  
7.        print(translations[current_language]["export_success"].format("settings.json"))  
8.    except Exception as e:  
9.        print(translations[current_language]["export_failed"].format(e))  
10.        messagebox.showerror(translations[current_language]["error_title"],  
11.                             translations[current_language]["export_failed"].format(e))  
12.  
13.def load_settings():  
14.    global finger_actions, current_language  
15.    config = configparser.ConfigParser()  
16.    if os.path.exists("config.ini"):  
17.        config.read("config.ini", encoding="utf-8")  
18.        if "Settings" in config and "language" in config["Settings"]:  
19.            lang = config["Settings"]["language"]  
20.            language_map = {"auto": "auto", "zh-CN": "zh-CN", "zh-TW": "zh-TW", "en": "en"}  
21.            current_language = language_map.get(lang, "zh-CN")  
22.    try:  
23.        if os.path.exists("settings.json"):  
24.            with open("settings.json", "r", encoding="utf-8") as f:  
25.                settings = json.load(f)  
26.            for i in range(1, 6):  
27.                key = str(i)  
28.                if key in settings:  
29.                    action = settings[key]  
30.                    if action is None or (  
31.                            isinstance(action, dict) and  
32.                            "type" in action and  
33.                            action["type"] in ["key", "combo", "mouse_scroll", "mouse_click"]):  
34.                        finger_actions[i] = action  
35.                    else:  
36.                        print(f"无效的设置项,手指 {i}: {action}")  
37.                        finger_actions[i] = None  
38.            print(translations[current_language]["import_success"].format("settings.json"))  
39.    except Exception as e:  
40.        print(f"加载设置失败: {e}")  
        finger_actions = {i: None for i in range(1, 6)}

5. 文本渲染模块(PIL、OpenCV)

  • 功能:在摄像头画面上显示多语言提示(手指数量、左右手、退出倒计时)。
  • 实现:PIL 渲染中文(simhei.ttf),OpenCV 显示关键点和文本,支持字体回退。
1.def draw_chinese_text(img_cv, text, pos, font_size=30, color=(255, 0, 0)):  
2.    img_pil = Image.fromarray(cv2.cvtColor(img_cv, cv2.COLOR_BGR2RGB))  
3.    draw = ImageDraw.Draw(img_pil)  
4.    try:  
5.        font = ImageFont.truetype("./fonts/simhei.ttf", font_size)  
6.    except IOError:  
7.        try:  
8.            font = ImageFont.truetype("arial.ttf", font_size)  
9.            if text != translations[current_language]["font_fallback"]:  
10.                print(translations[current_language]["font_fallback"])  
11.        except IOError:  
12.            print(translations[current_language]["font_missing"])  
13.            cv2.putText(img_cv, translations[current_language]["font_error"], (pos[0], pos[1] + font_size // 2),  
14.                        cv2.FONT_HERSHEY_SIMPLEX, font_size / 30, color, 2)  
15.            return img_cv  
16.    draw.text(pos, text, font=font, fill=color)  
17.    return cv2.cvtColor(np.array(img_pil), cv2.COLOR_RGB2BGR)

四、安装与运行

“指尖命令”提供两种使用方式:源码版本(适合开发者或需要自定义的用户)和打包版本(适合快速部署的用户)。以下分别说明安装步骤。

1. 系统需求

  • 操作系统:Windows 10/11 64位(Windows 10 版本1803或更高)

  • 硬件

                最低配置

                        Intel Core i3-1115G4或AMD Ryzen 3 5300U

                        4GB RAM

                        640x480 30FPS摄像头

                        3GB磁盘空间

                推荐配置

                        Intel Core i5-1235U或AMD Ryzen 5 5600U

                        8GB RAM

                        720p摄像头

                        4GB SSD空间

  • 软件

                Python 3.8+(仅源码版本需要)

                Microsoft Visual C++ Redistributable 2015-2022 (x64)

  • 权限:摄像头访问权限,运行目录写入权限(用于生成settings.json和config.ini)

2. 源码版本安装

适合开发者或需要修改代码的用户,需安装 Python 环境和依赖。

  1. 安装 Python

    • 下载并安装 Python 3.8+(推荐3.10)从 python.org。

    • 确保勾选“Add Python to PATH”。

  2. 克隆仓库

    git clone https://github.com/GDragon-creator/bug-free-memory.git
    cd bug-free-memory
  3. 安装依赖

    • 确保网络连接,运行以下命令安装必要库:

      pip install -r requirements.txt
    • 依赖包括:opencv-python, mediapipe, pyautogui, pynput, pillow, numpy。

  4. 准备文件

    • 确保 languages.json 与 automated_mediaplayer.py 在同一目录。

    • (推荐)创建 fonts/ 目录,放入 simhei.ttf(或系统自带中文字体)。

    • (可选)创建 images/ 目录,放入 wechat.png 用于“联系我们”界面。

  5. 运行程序

    python automated_mediaplayer.py
    • 首次运行可能需要下载 MediaPipe 模型,请保持网络畅通。

3. 打包版本安装

适合希望快速使用的用户,无需配置 Python 环境。

  1. 下载打包版本

  1. 解压文件

    • 将 Fingertip_command.zip 解压到全英文路径的目录(如 C:\FingertipCommand)。

    • 确保目录包含以下文件:

      • 基于MediaPipe:指尖命令.exe

      • languages.json

      • (推荐)fonts/simhei.ttf

      • (可选)images/wechat.png

  2. 安装运行时依赖

    • 确保系统已安装 Microsoft Visual C++ Redistributable 2015-2022 (x64),可从 Microsoft 官网 下载。

  3. 运行程序

    • 双击 基于MediaPipe:指尖命令.exe。

    • 首次运行可能会请求摄像头权限,点击“允许”。

  4. 注意事项

    • 若中文显示异常,请将 simhei.ttf 放入 fonts/ 目录。

    • 确保 languages.json 存在,否则程序无法启动。


五、使用指南

1. 配置界面

启动程序后,进入 GUI 界面:

  • 语言切换:通过“语言”菜单选择简体中文、繁体中文或英文。
  • 绑定手势

                点击“设置动作”按钮,进入捕获模式。

                执行键盘按键(单键/组合键)、鼠标滚动或点击。

                绑定成功后,动作显示为绿色,按钮变为“取消设定”。

                如果需要更换/取消绑定,再次点击“取消设定”按钮即可清除配置。

  • 配置管理:保存到 settings.json,支持导入/导出。
  • 启动识别:点击“完成配置并开始识别”,进入手势控制模式。

2. 手势控制

  • 摄像头窗口:显示手部关键点、指数字和左右手信息。
  • 执行动作:伸出1-5根手指,保持0.25秒触发绑定操作。
  • 退出程序:双手举起3秒或按 ESC 键。
  • 重新配置:按 R 键返回 GUI 界面。

3. 注意事项

  • 确保光线充足,背景简洁。
  • 放置 simhei.ttf 以正确显示中文。
  • 检查 languages.json 是否存在。


六、核心特性与优势

  • 灵活性:支持多种操作类型,满足不同场景需求。
  • 易用性:直观的 GUI 和多语言支持,适合全球用户。
  • 稳定性:防抖机制和错误处理确保流畅体验。
  • 扩展性:模块化设计便于功能扩展。


七、未来改进方向

  • 录制宏:支持录制和回放复杂操作序列,如多步键盘和鼠标操作,提升自动化能力。

  • 单个按键长按:允许绑定长按键操作,例如持续按住某个键以实现音量渐增或窗口切换。

  • 预定动作:内置常用媒体控制动作(如播放、暂停、音量+、音量-),简化配置过程。


八、结语

“指尖命令”将手势识别与自动化控制无缝结合,为用户提供了一种新颖的交互方式。无论是简化日常操作还是探索计算机视觉的乐趣,这款工具都能带来惊喜。欢迎体验并在 GitHub 上提出宝贵建议!

项目地址: GitHub - GDragon-creator/fingertip-commands: 基于MediaPipe:指尖命令

声明:本文基于“指尖命令”项目文档整理,代码已开源,欢迎 star 和 fork!如果您有任何问题或建议,请在 GitHub Issues 或本文评论区留言。


参考资料

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值