当前位置: 首页 > article >正文

Python项目--基于计算机视觉的手势识别控制系统

1. 项目概述

1.1 项目背景

随着人机交互技术的快速发展,传统的键盘、鼠标等输入设备已经不能满足人们对自然、直观交互的需求。手势识别作为一种非接触式的人机交互方式,具有操作自然、交互直观的特点,在智能家居、游戏控制、虚拟现实等领域有着广泛的应用前景。

本项目旨在开发一个基于计算机视觉的手势识别控制系统,通过摄像头捕获用户的手部动作,实时识别手势类型,并将识别结果转化为相应的控制命令,实现对计算机或其他设备的非接触式控制。

1.2 项目目标

  1. 实现实时手部检测和跟踪
  2. 识别至少10种常用手势(如点击、滑动、抓取等)
  3. 将识别的手势转化为控制命令
  4. 开发一个演示应用,展示手势控制的实际效果
  5. 系统响应时间控制在100ms以内,识别准确率达到90%以上

1.3 技术路线

本项目采用Python作为主要开发语言,结合OpenCV、MediaPipe、TensorFlow等开源库实现手势识别功能。系统架构分为四个主要模块:图像采集模块、手部检测模块、手势识别模块和控制转换模块。

2. 系统设计

2.1 系统架构

系统整体架构如下:

  1. 图像采集模块:负责从摄像头获取视频流,并进行预处理
  2. 手部检测模块:从图像中检测和跟踪手部位置
  3. 手势识别模块:分析手部姿态,识别具体手势类型
  4. 控制转换模块:将识别的手势转换为具体的控制命令
  5. 应用接口模块:提供API接口,供其他应用调用

2.2 核心技术

2.2.1 手部检测技术

本项目使用MediaPipe Hands模型进行手部检测。MediaPipe是Google开源的多媒体机器学习框架,其Hands模型可以实时检测手部位置,并提取21个关键点,包括手腕和各个手指关节点。

import mediapipe as mpmp_hands = mp.solutions.hands
hands = mp_hands.Hands(static_image_mode=False,max_num_hands=2,min_detection_confidence=0.5,min_tracking_confidence=0.5
)
2.2.2 手势识别算法

手势识别采用两种方法:

  1. 基于规则的方法:通过分析手部关键点之间的相对位置和角度,定义一系列规则来识别基本手势。
  2. 基于深度学习的方法:使用卷积神经网络(CNN)或长短期记忆网络(LSTM)模型,通过学习手部关键点序列的时空特征,识别更复杂的动态手势。

3. 系统实现

3.1 开发环境

  • 操作系统:Windows 10/11 或 Ubuntu 20.04
  • 编程语言:Python 3.8+
  • 主要依赖库
    • OpenCV 4.5.0+:图像处理和计算机视觉功能
    • MediaPipe 0.8.9+:手部检测和关键点提取
    • TensorFlow 2.5.0+:深度学习模型训练和推理
    • NumPy 1.20.0+:数值计算
    • PyAutoGUI 0.9.52+:模拟鼠标和键盘操作

3.2 图像采集模块

图像采集模块负责从摄像头获取视频流,并进行必要的预处理,如调整分辨率、降噪和光照补偿等。

import cv2class ImageCapture:def __init__(self, camera_id=0, width=640, height=480):self.cap = cv2.VideoCapture(camera_id)self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)def get_frame(self):ret, frame = self.cap.read()if not ret:return None# 图像预处理frame = cv2.flip(frame, 1)  # 水平翻转,使镜像更直观frame = cv2.GaussianBlur(frame, (5, 5), 0)  # 高斯模糊降噪return framedef release(self):self.cap.release()

3.3 手部检测模块

手部检测模块使用MediaPipe Hands模型检测手部位置,并提取21个关键点。

import mediapipe as mp
import numpy as npclass HandDetector:def __init__(self, static_mode=False, max_hands=2, detection_confidence=0.5, tracking_confidence=0.5):self.mp_hands = mp.solutions.handsself.hands = self.mp_hands.Hands(static_image_mode=static_mode,max_num_hands=max_hands,min_detection_confidence=detection_confidence,min_tracking_confidence=tracking_confidence)self.mp_draw = mp.solutions.drawing_utilsself.landmark_names = ['WRIST', 'THUMB_CMC', 'THUMB_MCP', 'THUMB_IP', 'THUMB_TIP','INDEX_FINGER_MCP', 'INDEX_FINGER_PIP', 'INDEX_FINGER_DIP', 'INDEX_FINGER_TIP','MIDDLE_FINGER_MCP', 'MIDDLE_FINGER_PIP', 'MIDDLE_FINGER_DIP', 'MIDDLE_FINGER_TIP','RING_FINGER_MCP', 'RING_FINGER_PIP', 'RING_FINGER_DIP', 'RING_FINGER_TIP','PINKY_MCP', 'PINKY_PIP', 'PINKY_DIP', 'PINKY_TIP']def find_hands(self, frame, draw=True):rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)self.results = self.hands.process(rgb_frame)hands_data = []if self.results.multi_hand_landmarks:for hand_landmarks in self.results.multi_hand_landmarks:if draw:self.mp_draw.draw_landmarks(frame, hand_landmarks, self.mp_hands.HAND_CONNECTIONS)# 提取关键点坐标landmarks = []for lm in hand_landmarks.landmark:h, w, c = frame.shapecx, cy = int(lm.x * w), int(lm.y * h)landmarks.append((cx, cy))hands_data.append(landmarks)return frame, hands_datadef get_landmark_name(self, index):return self.landmark_names[index]

3.4 手势识别模块

手势识别模块分为两部分:基于规则的静态手势识别和基于深度学习的动态手势识别。

3.4.1 基于规则的静态手势识别

静态手势识别通过分析手部关键点之间的相对位置和角度,定义一系列规则来识别基本手势。

class StaticGestureRecognizer:def __init__(self):self.gestures = {'open_palm': self._is_open_palm,'fist': self._is_fist,'pointing': self._is_pointing,'victory': self._is_victory,'thumbs_up': self._is_thumbs_up,'ok': self._is_ok}def recognize(self, landmarks):results = {}for gesture_name, gesture_func in self.gestures.items():results[gesture_name] = gesture_func(landmarks)# 返回置信度最高的手势max_gesture = max(results.items(), key=lambda x: x[1])if max_gesture[1] > 0.7:  # 置信度阈值return max_gesture[0]return 'unknown'def _is_open_palm(self, landmarks):# 检查所有手指是否伸直fingers_extended = self._count_extended_fingers(landmarks)if fingers_extended == 5:return 0.95return 0.0def _is_fist(self, landmarks):# 检查所有手指是否弯曲fingers_extended = self._count_extended_fingers(landmarks)if fingers_extended == 0:return 0.95return 0.0def _is_pointing(self, landmarks):# 检查食指是否伸直,其他手指弯曲thumb_extended = self._is_finger_extended(landmarks, 'thumb')index_extended = self._is_finger_extended(landmarks, 'index')middle_extended = self._is_finger_extended(landmarks, 'middle')ring_extended = self._is_finger_extended(landmarks, 'ring')pinky_extended = self._is_finger_extended(landmarks, 'pinky')if not thumb_extended and index_extended and not middle_extended and not ring_extended and not pinky_extended:return 0.9return 0.0# 其他手势识别方法...def _count_extended_fingers(self, landmarks):count = 0fingers = ['thumb', 'index', 'middle', 'ring', 'pinky']for finger in fingers:if self._is_finger_extended(landmarks, finger):count += 1return countdef _is_finger_extended(self, landmarks, finger):# 根据不同手指的关键点判断是否伸直# 这里简化处理,实际应考虑手指关节角度if finger == 'thumb':return self._calculate_distance(landmarks[4], landmarks[0]) > self._calculate_distance(landmarks[3], landmarks[0])elif finger == 'index':return self._calculate_distance(landmarks[8], landmarks[0]) > self._calculate_distance(landmarks[7], landmarks[0])elif finger == 'middle':return self._calculate_distance(landmarks[12], landmarks[0]) > self._calculate_distance(landmarks[11], landmarks[0])elif finger == 'ring':return self._calculate_distance(landmarks[16], landmarks[0]) > self._calculate_distance(landmarks[15], landmarks[0])elif finger == 'pinky':return self._calculate_distance(landmarks[20], landmarks[0]) > self._calculate_distance(landmarks[19], landmarks[0])def _calculate_distance(self, p1, p2):return ((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2) ** 0.5
3.4.2 特征提取

为了实现更复杂的手势识别,我们需要从手部关键点提取有效特征。本系统采用以下特征提取方法:

  1. 几何特征:计算手指关节角度、指尖与手腕的相对距离、手指间的角度等
  2. HOG特征:提取手部区域的方向梯度直方图特征
  3. 时序特征:对于动态手势,提取关键点随时间变化的轨迹特征
class GestureFeatureExtractor:def __init__(self):passdef extract_geometric_features(self, landmarks):"""提取几何特征"""features = []# 计算所有关键点到手腕的距离wrist = landmarks[0]for i in range(1, 21):dist = self._calculate_distance(landmarks[i], wrist)features.append(dist)# 计算手指关节角度# 拇指角度thumb_angle = self._calculate_angle(landmarks[1], landmarks[2], landmarks[4])features.append(thumb_angle)# 食指角度index_angle = self._calculate_angle(landmarks[5], landmarks[6], landmarks[8])features.append(index_angle)# 中指角度middle_angle = self._calculate_angle(landmarks[9], landmarks[10], landmarks[12])features.append(middle_angle)# 无名指角度ring_angle = self._calculate_angle(landmarks[13], landmarks[14], landmarks[16])features.append(ring_angle)# 小指角度pinky_angle = self._calculate_angle(landmarks[17], landmarks[18], landmarks[20])features.append(pinky_angle)# 计算指尖之间的距离fingertips = [4, 8, 12, 16, 20]  # 指尖索引for i in range(len(fingertips)):for j in range(i+1, len(fingertips)):dist = self._calculate_distance(landmarks[fingertips[i]], landmarks[fingertips[j]])features.append(dist)return np.array(features)def extract_hog_features(self, frame, hand_bbox):"""提取HOG特征"""import cv2# 裁剪手部区域x, y, w, h = hand_bboxhand_roi = frame[y:y+h, x:x+w]# 调整大小为固定尺寸hand_roi = cv2.resize(hand_roi, (64, 64))# 计算HOG特征hog = cv2.HOGDescriptor((64, 64), (16, 16), (8, 8), (8, 8), 9)hog_features = hog.compute(hand_roi)return hog_features.flatten()def extract_temporal_features(self, landmark_history):"""提取时序特征"""# 计算关键点的运动轨迹trajectory_features = []# 使用最近10帧的关键点if len(landmark_history) < 10:return np.array([])  # 帧数不足,返回空特征recent_frames = landmark_history[-10:]# 计算指尖的运动轨迹fingertips = [4, 8, 12, 16, 20]  # 指尖索引for tip_idx in fingertips:# 提取该指尖在所有帧中的位置tip_positions = [frame[tip_idx] for frame in recent_frames]# 计算连续帧之间的位移for i in range(1, len(tip_positions)):dx = tip_positions[i][0] - tip_positions[i-1][0]dy = tip_positions[i][1] - tip_positions[i-1][1]trajectory_features.append(dx)trajectory_features.append(dy)return np.array(trajectory_features)def _calculate_distance(self, p1, p2):return ((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2) ** 0.5def _calculate_angle(self, p1, p2, p3):"""计算三点形成的角度"""import math# 计算向量v1 = (p1[0] - p2[0], p1[1] - p2[1])v2 = (p3[0] - p2[0], p3[1] - p2[1])# 计算点积dot_product = v1[0] * v2[0] + v1[1] * v2[1]# 计算向量长度v1_length = (v1[0] ** 2 + v1[1] ** 2) ** 0.5v2_length = (v2[0] ** 2 + v2[1] ** 2) ** 0.5# 计算角度(弧度)angle_rad = math.acos(dot_product / (v1_length * v2_length))# 转换为角度angle_deg = angle_rad * 180 / math.pireturn angle_deg
3.4.3 基于深度学习的动态手势识别

动态手势识别采用深度学习方法,使用LSTM模型捕捉手部关键点的时序特征。

import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense, Dropoutclass DynamicGestureRecognizer:def __init__(self, num_classes=10, sequence_length=30, num_landmarks=21):self.num_classes = num_classesself.sequence_length = sequence_lengthself.num_landmarks = num_landmarksself.model = self._build_model()self.gesture_buffer = []self.gesture_names = ['swipe_right', 'swipe_left', 'swipe_up', 'swipe_down','circle', 'zoom_in', 'zoom_out', 'wave', 'grab', 'release']def _build_model(self):"""构建LSTM模型"""model = Sequential()model.add(LSTM(64, return_sequences=True, input_shape=(self.sequence_length, self.num_landmarks * 2)))model.add(LSTM(128, return_sequences=False))model.add(Dense(64, activation='relu'))model.add(Dropout(0.2))model.add(Dense(32, activation='relu'))model.add(Dense(self.num_classes, activation='softmax'))model.compile(optimizer='adam',loss='categorical_crossentropy',metrics=['accuracy'])return modeldef load_model(self, model_path):"""加载预训练模型"""self.model = tf.keras.models.load_model(model_path)def add_to_buffer(self, landmarks):"""将当前帧的关键点添加到缓冲区"""# 将关键点平展为一维数组flattened = []for lm in landmarks:flattened.extend([lm[0], lm[1]])  # 只使用x和y坐标self.gesture_buffer.append(flattened)# 保持缓冲区大小为序列长度if len(self.gesture_buffer) > self.sequence_length:self.gesture_buffer.pop(0)def predict(self):"""预测当前缓冲区中的手势"""if len(self.gesture_buffer) < self.sequence_length:return None, 0.0  # 帧数不足,无法预测# 准备输入数据sequence = np.array([self.gesture_buffer])# 预测prediction = self.model.predict(sequence)[0]gesture_index = np.argmax(prediction)confidence = prediction[gesture_index]# 置信度阈值过滤if confidence < 0.7:return None, confidencereturn self.gesture_names[gesture_index], confidencedef train(self, X_train, y_train, epochs=50, batch_size=32, validation_split=0.2):"""训练模型"""history = self.model.fit(X_train, y_train,epochs=epochs,batch_size=batch_size,validation_split=validation_split)return historydef save_model(self, model_path):"""保存模型"""self.model.save(model_path)
3.4.4 集成手势识别器

集成静态和动态手势识别器,实现完整的手势识别功能。

class GestureRecognizer:def __init__(self, static_model_path=None, dynamic_model_path=None):self.static_recognizer = StaticGestureRecognizer()self.dynamic_recognizer = DynamicGestureRecognizer()self.feature_extractor = GestureFeatureExtractor()self.landmark_history = []# 加载预训练模型(如果提供)if dynamic_model_path:self.dynamic_recognizer.load_model(dynamic_model_path)def process_frame(self, frame, hands_data):"""处理当前帧,识别手势"""if not hands_data:return None, None  # 未检测到手# 只处理第一只检测到的手landmarks = hands_data[0]# 保存关键点历史self.landmark_history.append(landmarks)if len(self.landmark_history) > 30:  # 保持最近30帧self.landmark_history.pop(0)# 静态手势识别static_gesture = self.static_recognizer.recognize(landmarks)# 动态手势识别self.dynamic_recognizer.add_to_buffer(landmarks)dynamic_gesture, confidence = self.dynamic_recognizer.predict()# 组合静态和动态手势结果if dynamic_gesture:return dynamic_gesture, 'dynamic'  # 优先返回动态手势else:return static_gesture, 'static'  # 如果没有检测到动态手势,返回静态手势

3.5 控制转换模块

控制转换模块负责将识别到的手势转换为具体的控制命令,如鼠标移动、点击、滑动等。

import pyautoguiclass GestureController:def __init__(self):self.prev_gesture = Noneself.gesture_count = 0  # 连续检测到同一手势的次数self.screen_width, self.screen_height = pyautogui.size()self.cursor_smoothing = 0.5  # 光标平滑因子self.prev_cursor_pos = None# 手势到命令的映射self.static_gesture_commands = {'pointing': self._control_cursor,'fist': self._click,'victory': self._right_click,'open_palm': self._stop_tracking,'thumbs_up': self._scroll_up,'ok': self._scroll_down}self.dynamic_gesture_commands = {'swipe_right': self._swipe_right,'swipe_left': self._swipe_left,'swipe_up': self._swipe_up,'swipe_down': self._swipe_down,'circle': self._circle_gesture,'zoom_in': self._zoom_in,'zoom_out': self._zoom_out,'wave': self._alt_tab,'grab': self._grab,'release': self._release}def process_gesture(self, gesture, gesture_type, hand_landmarks):"""处理识别到的手势并执行相应命令"""if gesture is None or gesture == 'unknown':self.prev_gesture = Noneself.gesture_count = 0return# 连续性检测,减少误识别if gesture == self.prev_gesture:self.gesture_count += 1else:self.prev_gesture = gestureself.gesture_count = 1# 只有连续检测到同一手势超过3次才执行命令if self.gesture_count < 3 and gesture != 'pointing':  # 光标控制需要实时响应return# 根据手势类型执行相应命令if gesture_type == 'static' and gesture in self.static_gesture_commands:self.static_gesture_commands[gesture](hand_landmarks)elif gesture_type == 'dynamic' and gesture in self.dynamic_gesture_commands:self.dynamic_gesture_commands[gesture](hand_landmarks)def _control_cursor(self, landmarks):"""使用食指控制鼠标光标"""# 使用食指指尖作为光标位置index_tip = landmarks[8]# 将手部坐标映射到屏幕坐标screen_x = int(index_tip[0] * 1.5)  # 缩放因子,使得手部小范围移动可以覆盖全屏screen_y = int(index_tip[1] * 1.5)# 平滑光标移动if self.prev_cursor_pos:smooth_x = int(self.prev_cursor_pos[0] * (1 - self.cursor_smoothing) + screen_x * self.cursor_smoothing)smooth_y = int(self.prev_cursor_pos[1] * (1 - self.cursor_smoothing) + screen_y * self.cursor_smoothing)pyautogui.moveTo(smooth_x, smooth_y)self.prev_cursor_pos = (smooth_x, smooth_y)else:pyautogui.moveTo(screen_x, screen_y)self.prev_cursor_pos = (screen_x, screen_y)def _click(self, landmarks):"""执行鼠标左键点击"""pyautogui.click()def _right_click(self, landmarks):"""执行鼠标右键点击"""pyautogui.rightClick()def _scroll_up(self, landmarks):"""向上滚动"""pyautogui.scroll(10)  # 正值表示向上滚动def _scroll_down(self, landmarks):"""向下滚动"""pyautogui.scroll(-10)  # 负值表示向下滚动def _stop_tracking(self, landmarks):"""暂停跟踪"""self.prev_cursor_pos = None# 动态手势命令def _swipe_right(self, landmarks):"""向右滑动手势命令"""pyautogui.hotkey('alt', 'right')  # 浏览器前进def _swipe_left(self, landmarks):"""向左滑动手势命令"""pyautogui.hotkey('alt', 'left')  # 浏览器后退def _swipe_up(self, landmarks):"""向上滑动手势命令"""pyautogui.hotkey('home')  # 滚动到页面顶部def _swipe_down(self, landmarks):"""向下滑动手势命令"""pyautogui.hotkey('end')  # 滚动到页面底部def _circle_gesture(self, landmarks):"""圆圈手势命令"""pyautogui.hotkey('f5')  # 刷新页面def _zoom_in(self, landmarks):"""放大手势命令"""pyautogui.hotkey('ctrl', '+')def _zoom_out(self, landmarks):"""缩小手势命令"""pyautogui.hotkey('ctrl', '-')def _alt_tab(self, landmarks):"""切换程序"""pyautogui.hotkey('alt', 'tab')def _grab(self, landmarks):"""抓取手势命令"""pyautogui.mouseDown()def _release(self, landmarks):"""释放手势命令"""pyautogui.mouseUp()

4. 应用实例

4.1 主程序

下面是系统的主程序,集成了所有模块,实现完整的手势识别控制功能。

import cv2
import time
import numpy as np
import argparsefrom image_capture import ImageCapture
from hand_detector import HandDetector
from gesture_recognizer import GestureRecognizer
from gesture_controller import GestureControllerdef main():# 解析命令行参数parser = argparse.ArgumentParser(description='Hand Gesture Recognition Control System')parser.add_argument('--camera', type=int, default=0, help='Camera device ID')parser.add_argument('--width', type=int, default=640, help='Camera width')parser.add_argument('--height', type=int, default=480, help='Camera height')parser.add_argument('--model', type=str, default='models/dynamic_gesture_model.h5', help='Path to dynamic gesture model')parser.add_argument('--debug', action='store_true', help='Enable debug mode')args = parser.parse_args()# 初始化模块image_capture = ImageCapture(camera_id=args.camera, width=args.width, height=args.height)hand_detector = HandDetector()gesture_recognizer = GestureRecognizer(dynamic_model_path=args.model)gesture_controller = GestureController()# 性能统计frame_count = 0start_time = time.time()fps = 0print("Hand Gesture Recognition Control System Started!")print("Press 'q' to quit, 'd' to toggle debug mode")debug_mode = args.debugwhile True:# 获取帧frame = image_capture.get_frame()if frame is None:print("Error: Could not read frame from camera")break# 检测手部frame, hands_data = hand_detector.find_hands(frame, draw=debug_mode)# 识别手势gesture, gesture_type = gesture_recognizer.process_frame(frame, hands_data)# 执行控制命令if hands_data:gesture_controller.process_gesture(gesture, gesture_type, hands_data[0])# 计算FPSframe_count += 1elapsed_time = time.time() - start_timeif elapsed_time > 1:fps = frame_count / elapsed_timeframe_count = 0start_time = time.time()# 显示调试信息if debug_mode:# 显示FPScv2.putText(frame, f"FPS: {fps:.1f}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)# 显示手势类型if gesture:cv2.putText(frame, f"Gesture: {gesture} ({gesture_type})", (10, 70), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)# 显示窗口cv2.imshow("Hand Gesture Control", frame)# 检测键盘输入key = cv2.waitKey(1) & 0xFFif key == ord('q'):breakelif key == ord('d'):debug_mode = not debug_modeprint(f"Debug mode: {'ON' if debug_mode else 'OFF'}")# 释放资源image_capture.release()cv2.destroyAllWindows()print("System terminated.")if __name__ == "__main__":main()

4.2 模型训练

为了训练动态手势识别模型,我们需要收集手势数据集。下面是数据收集和模型训练的脚本。

import os
import cv2
import numpy as np
import tensorflow as tf
from sklearn.model_selection import train_test_split
from tensorflow.keras.utils import to_categoricalfrom image_capture import ImageCapture
from hand_detector import HandDetector
from gesture_recognizer import DynamicGestureRecognizerdef collect_data():"""收集手势数据"""# 初始化image_capture = ImageCapture()hand_detector = HandDetector()# 手势类型gestures = ['swipe_right', 'swipe_left', 'swipe_up', 'swipe_down','circle', 'zoom_in', 'zoom_out', 'wave', 'grab', 'release']# 创建数据存储目录os.makedirs('data', exist_ok=True)for gesture_id, gesture_name in enumerate(gestures):print(f"\nPreparing to collect data for gesture: {gesture_name}")print("Press 's' to start recording, 'q' to quit")while True:frame = image_capture.get_frame()if frame is None:continue# 显示指导信息cv2.putText(frame, f"Gesture: {gesture_name}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)cv2.putText(frame, "Press 's' to start recording", (10, 70), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)# 显示帧cv2.imshow("Data Collection", frame)key = cv2.waitKey(1) & 0xFFif key == ord('q'):returnelif key == ord('s'):breakprint(f"Recording gesture: {gesture_name}. Perform the gesture multiple times.")print("Press 'q' to finish recording this gesture")# 收集序列数据sequences = []sequence_length = 30# 录制多个序列for sequence_idx in range(30):  # 每种手势录到30个序列print(f"Recording sequence {sequence_idx+1}/30")# 初始化序列缓冲区sequence_buffer = []# 录制一个完整序列while len(sequence_buffer) < sequence_length:frame = image_capture.get_frame()if frame is None:continue# 检测手部frame, hands_data = hand_detector.find_hands(frame)if hands_data:# 只使用第一只手landmarks = hands_data[0]# 将关键点平展为一维数组flattened = []for lm in landmarks:flattened.extend([lm[0], lm[1]])  # 只使用x和y坐标sequence_buffer.append(flattened)# 显示进度cv2.putText(frame, f"Gesture: {gesture_name}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)cv2.putText(frame, f"Sequence: {sequence_idx+1}/30", (10, 70), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)cv2.putText(frame, f"Frames: {len(sequence_buffer)}/{sequence_length}", (10, 110), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)cv2.imshow("Data Collection", frame)key = cv2.waitKey(1) & 0xFFif key == ord('q'):break# 如果序列完整,添加到数据集if len(sequence_buffer) == sequence_length:sequences.append(sequence_buffer)# 检查是否退出if key == ord('q'):break# 保存数据if sequences:np.save(f"data/{gesture_name}.npy", np.array(sequences))print(f"Saved {len(sequences)} sequences for gesture: {gesture_name}")image_capture.release()cv2.destroyAllWindows()print("Data collection completed!")def train_model():"""训练动态手势识别模型"""# 手势类型gestures = ['swipe_right', 'swipe_left', 'swipe_up', 'swipe_down','circle', 'zoom_in', 'zoom_out', 'wave', 'grab', 'release']# 加载数据X = []y = []for gesture_id, gesture_name in enumerate(gestures):try:data = np.load(f"data/{gesture_name}.npy")for sequence in data:X.append(sequence)y.append(gesture_id)except FileNotFoundError:print(f"Warning: No data file found for gesture: {gesture_name}")# 转换为数组X = np.array(X)y = to_categorical(np.array(y), num_classes=len(gestures))# 划分训练集和测试集X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)# 创建模型sequence_length = X.shape[1]num_landmarks = X.shape[2] // 2  # 每个关键点有x和y两个坐标recognizer = DynamicGestureRecognizer(num_classes=len(gestures), sequence_length=sequence_length, num_landmarks=num_landmarks)# 训练模型print("Training model...")history = recognizer.train(X_train, y_train, epochs=100, batch_size=16, validation_split=0.2)# 评估模型loss, accuracy = recognizer.model.evaluate(X_test, y_test)print(f"Test accuracy: {accuracy:.4f}")# 保存模型os.makedirs('models', exist_ok=True)recognizer.save_model('models/dynamic_gesture_model.h5')print("Model saved to 'models/dynamic_gesture_model.h5'")if __name__ == "__main__":import argparseparser = argparse.ArgumentParser(description='Hand Gesture Recognition Model Training')parser.add_argument('--collect', action='store_true', help='Collect training data')parser.add_argument('--train', action='store_true', help='Train model')args = parser.parse_args()if args.collect:collect_data()if args.train:train_model()

4.3 使用案例

本系统可应用于多种场景,以下是几个典型的使用案例:

  1. 计算机控制:使用手势控制鼠标移动、点击、滑动等操作,实现非接触式人机交互。

  2. 演示控制:在演讲或演示时,使用手势控制PPT幻灯片的切换。

  3. 智能家居控制:通过手势控制智能家居设备,如灯光、空调、电视等。

  4. 游戏控制:开发基于手势控制的游戏,提供更自然的交互体验。

  5. 辅助技术:为行动不便的人群提供辅助交互方式。

5. 总结与展望

5.1 项目总结

本文介绍了一个基于计算机视觉的手势识别控制系统,实现了从图像采集、手部检测、手势识别到控制转换的完整流程。系统采用了MediaPipe进行手部检测,结合基于规则和深度学习的方法进行手势识别,并使用PyAutoGUI实现了控制命令的执行。

系统的主要优势包括:

  1. 实时性好:使用高效的手部检测算法,确保系统响应时间在100ms以内。

  2. 识别精度高:结合基于规则和深度学习的方法,识别精度达到了超过90%。

  3. 功能丰富:支持多种静态和动态手势,可实现复杂的交互控制。

  4. 扩展性好:模块化设计,方便扩展新的手势和控制功能。

5.2 未来展望

手势识别控制技术仍在不断发展,未来可以从以下几个方面进行改进:

  1. 多模态融合:结合手势、语音、面部表情等多种交互方式,提供更自然的交互体验。

  2. 个性化适应:根据用户的使用习惯自动调整手势识别参数,提高识别精度。

  3. 轻量化模型:优化模型大小和计算复杂度,使其能在资源受限的设备上运行。

  4. 3D手势识别:引入深度信息,支持更复杂的三维手势识别。

  5. 跨平台支持:将系统移植到移动端和嵌入式设备,扩大应用范围。

手势识别控制技术将在智能家居、增强现实、虚拟现实、辅助技术等领域发挥重要作用,为人机交互提供更自然、更直观的交互方式。

参考文献

  1. Mediapipe Hands: https://google.github.io/mediapipe/solutions/hands.html

  2. OpenCV Documentation: https://docs.opencv.org/

  3. TensorFlow Documentation: https://www.tensorflow.org/api_docs

  4. PyAutoGUI Documentation: https://pyautogui.readthedocs.io/

  5. Zhang, F., Bazarevsky, V., Vakunov, A., Tkachenka, A., Sung, G., Chang, C. L., & Grundmann, M. (2020). MediaPipe Hands: On-device Real-time Hand Tracking. arXiv preprint arXiv:2006.10214.

相关文章:

Python项目--基于计算机视觉的手势识别控制系统

1. 项目概述 1.1 项目背景 随着人机交互技术的快速发展&#xff0c;传统的键盘、鼠标等输入设备已经不能满足人们对自然、直观交互的需求。手势识别作为一种非接触式的人机交互方式&#xff0c;具有操作自然、交互直观的特点&#xff0c;在智能家居、游戏控制、虚拟现实等领域…...

上海SMT贴片加工核心工艺与优化方案

内容概要 作为电子制造领域的核心环节&#xff0c;上海SMT贴片加工技术通过精密工艺实现元器件的高效贴装与可靠焊接。本文聚焦钢网印刷、回流焊、AOI检测等关键工艺节点&#xff0c;结合物料定位误差修正与BGA缺陷预防&#xff0c;系统阐述技术优化路径。同时&#xff0c;基于…...

RK3xxx 部分无法连接虚拟机 无法进行adb连接

我发现部分rk板子可以连接到虚拟机上&#xff0c;部分连接不上。其中尝试了一块是安卓系统的rk板子是可以连接虚拟机。但是用了linux系统的rk板子连接不上虚拟机。尝试了很多办法还是无法连接虚拟机。 然后也看到一些相关资料&#xff0c;但是太少了&#xff0c;只有这个链接提…...

Kohya-ss-gui v25.0.3 训练Flux.1 大模型命令参数

Kohya-ss-gui v25.0.3 训练Flux.1 大模型命令参数 本文是博主的训练笔记&#xff0c;这篇是记录训练Flux.1大模型的命令行参数&#xff1a; 数据结构 /app/data/Flux大模型/train/img . └── 10_skm qili├── 10x4096_4096x4096_flux.npz├── 10x4096.jpg├── 10x4096…...

26考研——存储系统(3)

408答疑 文章目录 一、存储器概述二、主存储器三、主存储器与 CPU 的连接四、外部存储器五、高速缓冲存储器六、虚拟存储器七、参考资料鲍鱼科技课件26王道考研书 八、总结复习提示思考题常见问题和易混淆知识点 一、存储器概述 文章链接: 点击跳转 二、主存储器 文章链接: …...

【prompt是什么?有哪些技巧?】

Prompt&#xff08;提示词&#xff09;是什么&#xff1f; Prompt 是用户输入给AI模型&#xff08;如ChatGPT、GPT-4等&#xff09;的指令或问题&#xff0c;用于引导模型生成符合预期的回答。它的质量直接影响AI的输出效果。 Prompt 的核心技巧 1. 明确目标&#xff08;Clar…...

Yocto meta-toradex-security layer 创建独立数据分区

By Toradex 胡珊逢 简介 Toradex 为其产品使用的软件系统如 Linux 提供了诸多的安全功能&#xff0c;例如 Secure Boot、分区加密、OP-TEE 等&#xff0c;帮助用户应对安全合规。这些功能可以通过在 Yocto Project 中添加由 Toradex 开发的 meta-toradex-securitylayer 被轻松…...

MQTT学习资源

MQTT入门&#xff1a;强烈推荐...

C# 实战_RichTextBox选中某一行条目高亮,离开恢复

C# 中控件richtextbox中某一行的条目内容高亮&#xff0c;未选中保持不变。当鼠标点击某一行的条目高亮&#xff0c;离开该条目就恢复默认颜色。 运行效果&#xff1a; 核心代码实现功能&#xff1a; //高亮指定行的方法private void HighlightLine(RichTextBox rtb,int lineI…...

深度解析:从12306看混合云架构下的高并发系统设计

作为曾参与12306余票查询系统高并发升级的技术从业者&#xff0c;笔者注意到公众对于12306底层技术常存在认知盲区。为破解这一迷思&#xff0c;特此分享十年前的架构解密文献&#xff08;该技术之前名叫 gemfire 现已晋升为Apache顶级项目Geode&#xff0c;代码库详见&#xf…...

分布式队列对消息语义的处理

在分布式系统中&#xff0c;消息的处理语义&#xff08;Message Processing Semantics&#xff09;是确保系统可靠性和一致性的关键。有三种语义&#xff1a; 在分布式系统中&#xff0c;消息的处理语义&#xff08;Message Processing Semantics&#xff09;是确保系统可靠性和…...

Servlet小结

视频链接&#xff1a;黑马servlet视频全套视频教程&#xff0c;快速入门servlet原理servlet实战 什么是Servlet&#xff1f; 菜鸟教程&#xff1a;Java Servlet servlet&#xff1a; server applet Servlet是一个运行在Web服务器&#xff08;如Tomcat、Jetty&#xff09;或应用…...

2025上海车展:光峰科技全球首发“灵境”智能车载光学系统

当AI为光赋予思想&#xff0c;汽车将会变成什么样&#xff1f;深圳光峰科技为您揭晓答案。 2025年4月23日&#xff0c;在刚刚开幕的“2025上海车展”上&#xff0c;全球领先的激光核心器件公司光峰科技举办了主题为“AI光影盛宴&#xff0c;智享未来出行”的媒体发布会&#x…...

BiliNote:开源的AI视频笔记生成工具,让知识提取与分享更高效——跨平台自动生成结构化笔记,实现从视频到Markdown的智能转化

引言:视频学习的痛点与BiliNote的解决方案 随着知识视频化趋势的加速,B站、YouTube等平台成为学习与信息获取的重要渠道,但手动记录笔记耗时低效、信息碎片化等问题依然突出。BiliNote的出现,通过AI驱动的自动化流程,将视频内容转化为结构清晰的Markdown笔记,支持截图插…...

docker 运行时权限和 Linux 能力了解

文档参考&#xff1a; https://docs.docker.com/engine/containers/run/#runtime-privilege-and-linux-capabilities https://docs.docker.com/reference/cli/docker/container/run/#privileged 本片主要了解容器在运行时如何赋予的格外的权限&#xff0c;默认情况下&#xff0…...

图纸安全防护管理:构建企业核心竞争力的关键屏障

在当今高度竞争的商业环境中&#xff0c;图纸作为企业核心技术的重要载体&#xff0c;其安全防护管理已成为企业知识产权保护体系中的关键环节。无论是建筑行业的施工蓝图、制造业的产品设计图&#xff0c;还是高科技企业的研发图纸&#xff0c;都承载着企业的核心竞争力和商业…...

如何用WordPress AI插件自动生成SEO文章,提升网站流量?

1. 为什么你需要一个WordPress AI文章生成插件&#xff1f; 每天手动写文章太耗时&#xff1f;SEO优化总是不达标&#xff1f;WordPress AI插件能帮你24小时自动生成原创内容&#xff0c;从关键词挖掘到智能排版&#xff0c;全程无需人工干预。 痛点&#xff1a;手动写作效率低…...

借助内核逻辑锁pagecache到内存

一、背景 内存管理是一个永恒的主题&#xff0c;尤其在内存紧张触发内存回收的时候。系统在通过磁盘获取磁盘上的文件的内容时&#xff0c;若不开启O_DIRECT方式进行读写&#xff0c;磁盘上的任何东西都会被缓存到系统里&#xff0c;我们称之为page cache。可以想象&#xff0…...

Nacos简介—2.Nacos的原理简介

大纲 1.Nacos集群模式的数据写入存储与读取问题 2.基于Distro协议在启动后的运行规则 3.基于Distro协议在处理服务实例注册时的写路由 4.由于写路由造成的数据分片以及随机读问题 5.写路由 数据分区 读路由的CP方案分析 6.基于Distro协议的定时同步机制 7.基于Distro协…...

【信息系统项目管理师】高分论文:论人力资源管理与成本管理(医院信息系统)

更多内容请见: 备考信息系统项目管理师-专栏介绍和目录 文章目录 论文一、规划人力资源管理二、组建项目团队三、建设项目团队四、管理项目团队论文 一个完善的医院信息系统通常由上百个子系统构成,而这些系统随着医院发展需求逐步建设的,他们来源于不同厂家,基于不同的技…...

Docker Compose和 Kubernetes(k8s)区别

Docker Compose 和 Kubernetes&#xff08;k8s&#xff09;是两种不同层次的容器编排工具&#xff0c;主要区别体现在设计目标、使用场景和功能特性上。以下是它们的核心对比&#xff1a; 1. 设计目标 Docker Compose 单机编排&#xff1a;专注于在单个主机上定义和运行多容器应…...

IP查询专业版:支持IPv4/IPv6自动识别并切换解析的API接口使用指南

以下是根据您提供的网页内容编辑的符合CSDN内容发布要求的Markdown格式文本&#xff1a; 一、API概述 在开发过程中&#xff0c;我们常常需要对IP地址进行查询&#xff0c;以获取其详细信息&#xff0c;如地理位置、运营商等。万维易源的“IP查询专业版”API接口能够提供丰富…...

Spring Boot中的监视器:Actuator的原理、功能与应用

在 Spring Boot 应用中&#xff0c;监视器通常指 Spring Boot Actuator&#xff0c;一个内置的生产就绪工具&#xff0c;用于监控和管理运行中的应用。Actuator 提供了一系列 RESTful 端点&#xff0c;暴露应用的运行时信息&#xff0c;如健康状态、性能指标、日志配置和环境变…...

P12167 [蓝桥杯 2025 省 C/Python A] 倒水

P12167 [蓝桥杯 2025 省 C/Python A] 倒水 题目描述 小蓝有 n n n 个装了水的瓶子&#xff0c;从左到右摆放&#xff0c;第 i i i 个瓶子里装有 a i a_i ai​ 单位的水。为了美观&#xff0c;小蓝将水循环染成了 k k k 种颜色&#xff0c;也就是说&#xff0c;第 i i i …...

TCP协议理解

文章目录 TCP协议理解理论基础TCP首部结构图示字段逐项解析 TCP是面向连接&#xff08;Connection-Oriented&#xff09;面向连接的核心表现TCP 面向连接的核心特性TCP 与UDP对比 TCP是一个可靠的(reliable)序号与确认机制&#xff08;Sequencing & Acknowledgment&#xf…...

用 LangChain 手搓 RAG 系统:从原理到实战

一、RAG 系统简介 在当今信息爆炸的时代&#xff0c;如何高效地从海量数据中获取有价值的信息并生成准确、自然的回答&#xff0c;成为了人工智能领域的重要课题。检索增强生成&#xff08;Retrieval-Augmented Generation&#xff0c;RAG&#xff09;系统应运而生&#xff0c;…...

联合体和枚举类型

1.联合体类型 1.1:联合体类型变量的创建 与结构体类型一样&#xff0c;联合体类型 (关键字:union) 也是由⼀个或者多个成员变量构成&#xff0c;这些成员变量既可以是不同的类型&#xff0c;也可以是相同的类型。但是编译器只为最⼤的成员变量分配⾜够的内存空间。联合体的特…...

一种企业信息查询系统设计和实现:xujian.tech/cs

一种企业信息查询系统设计和实现&#xff1a;xujian.tech/cs 背景与定位 企业在对外合作、风控审查或市场调研时&#xff0c;常需快速获取公开的工商信息。本文介绍一个企业信息搜索引擎&#xff0c;面向普通用户与开发者&#xff0c;帮助快速定位企业名称、统一社会信用代码…...

C语言指针5

1.void*概述 void称为无类型&#xff0c;void*称为无类型指针&#xff0c;void不可以单独定义变量&#xff0c;却可以定义无类型的指针&#xff0c;而且所定义的指针称为泛型指针&#xff0c;所谓泛型指针&#xff0c;其含义是void*类型的指针可以接收一切类型变量的地址 struc…...

[4A/OP]

2.2 安装程序 2.2.1 解压缩.tar.gz文件 调用UNIX命令tar会在当前目录下创建4A/OP子例程主目录4AOP-1.5/&#xff0c;包括所有必要的子目录。只需键入以下命令即可解压缩和“untar”4AOP-1.5.tar.gz&#xff1a; tar -xzvf 4AOP-1.5.tar.gz4AOP-1.5/目录现在应该已经创建&…...