#第一版 import cv2 import mediapipe as mp # 初始化MediaPipe手势识别模块 mp_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 ) mp_drawing = mp.solutions.drawing_utils # 手势判断函数应定义在循环外部 def is_fist(hand_landmarks): wrist = hand_landmarks.landmark[mp_hands.HandLandmark.WRIST] tips = [ mp_hands.HandLandmark.THUMB_TIP, mp_hands.HandLandmark.INDEX_FINGER_TIP, mp_hands.HandLandmark.MIDDLE_FINGER_TIP, mp_hands.HandLandmark.RING_FINGER_TIP, mp_hands.HandLandmark.PINKY_TIP ] total_distance = 0 for tip in tips: tip_point = hand_landmarks.landmark[tip] distance = ((tip_point.x - wrist.x) ** 2 + (tip_point.y - wrist.y) ** 2) ** 0.5 total_distance += distance avg_distance = total_distance / len(tips) return avg_distance < 0.15 # 根据实际效果调整阈值 # 调用摄像头 cap = cv2.VideoCapture(0) while cap.isOpened(): success, frame = cap.read() if not success: break # 转换颜色空间 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_drawing.draw_landmarks( frame, hand_landmarks, mp_hands.HAND_CONNECTIONS ) # 调用手势判断函数并显示结果 if is_fist(hand_landmarks): cv2.putText(frame, "Fist", (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) else: cv2.putText(frame, "open", (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) cv2.imshow('Hand Tracking', frame) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows() #第二版 import cv2 import mediapipe as mp import math # 初始化MediaPipe手势模块 mp_hands = mp.solutions.hands mp_drawing = mp.solutions.drawing_utils # 配置摄像头 cap = cv2.VideoCapture(0) with mp_hands.Hands( static_image_mode=False, max_num_hands=2, min_detection_confidence=0.7, min_tracking_confidence=0.5 ) as hands: while cap.isOpened(): success, frame = cap.read() if not success: break # 转换颜色空间并处理 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_drawing.draw_landmarks( frame, hand_landmarks, mp_hands.HAND_CONNECTIONS, mp_drawing.DrawingSpec(color=(0, 255, 0), thickness=2), # 关键点 mp_drawing.DrawingSpec(color=(0, 0, 255), thickness=2) # 连接线 ) # ---------------------- 优化后的手指计数逻辑 ---------------------- finger_count = 0 h, w = frame.shape[:2] # 修复列表生成式括号问题 landmark_points = [(int(lm.x * w), int(lm.y * h)) for lm in hand_landmarks.landmark] # 拇指判断(优化角度计算) thumb_tip = landmark_points[mp_hands.HandLandmark.THUMB_TIP.value] thumb_ip = landmark_points[mp_hands.HandLandmark.THUMB_IP.value] thumb_mcp = landmark_points[mp_hands.HandLandmark.THUMB_MCP.value] # 向量点积计算角度(添加分母保护) vec1 = (thumb_ip[0] - thumb_mcp[0], thumb_ip[1] - thumb_mcp[1]) vec2 = (thumb_tip[0] - thumb_ip[0], thumb_tip[1] - thumb_ip[1]) dot_product = vec1[0] * vec2[0] + vec1[1] * vec2[1] denominator = (math.hypot(*vec1) * math.hypot(*vec2)) + 1e-6 angle = math.degrees(math.acos(dot_product / denominator)) # 其他手指判断(示例:食指) index_tip_y = landmark_points[mp_hands.HandLandmark.INDEX_FINGER_TIP.value][1] index_pip_y = landmark_points[mp_hands.HandLandmark.INDEX_FINGER_PIP.value][1] if index_tip_y < index_pip_y: # 指尖在PIP关节上方 finger_count += 1 index_tip_y1 = landmark_points[mp_hands.HandLandmark.MIDDLE_FINGER_TIP.value][1] index_pip_y1= landmark_points[mp_hands.HandLandmark.MIDDLE_FINGER_PIP.value][1] if index_tip_y1 < index_pip_y1: # 指尖在PIP关节上方 finger_count += 1 index_tip_y2= landmark_points[mp_hands.HandLandmark.RING_FINGER_TIP.value][1] index_pip_y2 = landmark_points[mp_hands.HandLandmark.RING_FINGER_PIP.value][1] if index_tip_y2 < index_pip_y2: # 指尖在PIP关节上方 finger_count += 1 # 显示计数结果 cv2.putText(frame, f"Fingers: {finger_count}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2) cv2.imshow('Hand Tracking', frame) cv2.imshow('Hand Tracking', frame) if cv2.waitKey(1) & 0xFF == ord('q'): break if cv2.waitKey(5) & 0xFF == 27: break cap.release() cv2.destroyAllWindows() #第三版 import cv2 import mediapipe as mp import math # 初始化MediaPipe手势模块 mp_hands = mp.solutions.hands mp_drawing = mp.solutions.drawing_utils # 配置摄像头 cap = cv2.VideoCapture(0) with mp_hands.Hands( static_image_mode=False, max_num_hands=2, min_detection_confidence=0.7, min_tracking_confidence=0.5 ) as hands: while cap.isOpened(): success, frame = cap.read() if not success: break # 转换颜色空间并处理 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_drawing.draw_landmarks( frame, hand_landmarks, mp_hands.HAND_CONNECTIONS, mp_drawing.DrawingSpec(color=(0, 255, 0), thickness=2), # 关键点 mp_drawing.DrawingSpec(color=(0, 0, 255), thickness=2) # 连接线 ) # ---------------------- 优化后的手指计数逻辑 ---------------------- finger_count1 = 0 finger_count2= 0 h, w = frame.shape[:2] # 修复列表生成式括号问题 landmark_points = [(int(lm.x * w), int(lm.y * h)) for lm in hand_landmarks.landmark] # 拇指判断(优化角度计算) thumb_tip = landmark_points[mp_hands.HandLandmark.THUMB_TIP.value] thumb_ip = landmark_points[mp_hands.HandLandmark.THUMB_IP.value] thumb_mcp = landmark_points[mp_hands.HandLandmark.THUMB_MCP.value] # 向量点积计算角度(添加分母保护) vec1 = (thumb_ip[0] - thumb_mcp[0], thumb_ip[1] - thumb_mcp[1]) vec2 = (thumb_tip[0] - thumb_ip[0], thumb_tip[1] - thumb_ip[1]) dot_product = vec1[0] * vec2[0] + vec1[1] * vec2[1] denominator = (math.hypot(*vec1) * math.hypot(*vec2)) + 1e-6 angle = math.degrees(math.acos(dot_product / denominator)) # 其他手指判断(示例:食指) index_tip_y = landmark_points[mp_hands.HandLandmark.INDEX_FINGER_TIP.value][1] index_pip_y = landmark_points[mp_hands.HandLandmark.INDEX_FINGER_PIP.value][1] if index_tip_y < index_pip_y: # 指尖在PIP关节上方 finger_count1 += 1 index_tip_y1 = landmark_points[mp_hands.HandLandmark.MIDDLE_FINGER_TIP.value][1] index_pip_y1= landmark_points[mp_hands.HandLandmark.MIDDLE_FINGER_PIP.value][1] if index_tip_y1 < index_pip_y1: # 指尖在PIP关节上方 finger_count2 += 1 # 显示计数结果 cv2.putText(frame, f"index: {finger_count1}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2) cv2.putText(frame, f"middle: {finger_count2}", (10, 60), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2) cv2.imshow('Hand Tracking', frame) # cv2.imshow('Hand Tracking', frame) if cv2.waitKey(1) & 0xFF == ord('q'): break if cv2.waitKey(5) & 0xFF == 27: break cap.release() cv2.destroyAllWindows() #第四版 import cv2 import mediapipe as mp import math # 初始化MediaPipe手势模块 mp_hands = mp.solutions.hands mp_drawing = mp.solutions.drawing_utils # 配置摄像头 cap = cv2.VideoCapture(0) with mp_hands.Hands( static_image_mode=False, max_num_hands=2, min_detection_confidence=0.7, min_tracking_confidence=0.5 ) as hands: while cap.isOpened(): success, frame = cap.read() if not success: break # 转换颜色空间并处理 rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) results = hands.process(rgb_frame) if results.multi_hand_landmarks: for hand_index, hand_landmarks in enumerate(results.multi_hand_landmarks): # 获取手部标签(左手或右手) handedness = results.multi_handedness[hand_index].classification[0].label # 绘制关键点 mp_drawing.draw_landmarks( frame, hand_landmarks, mp_hands.HAND_CONNECTIONS, mp_drawing.DrawingSpec(color=(0, 255, 0), thickness=2), # 关键点 mp_drawing.DrawingSpec(color=(0, 0, 255), thickness=2) # 连接线 ) # 初始化手指计数 finger_count = 0 h, w = frame.shape[:2] # 获取所有关键点的像素坐标 landmark_points = [(int(lm.x * w), int(lm.y * h)) for lm in hand_landmarks.landmark] # ---------------------- 大拇指判断优化 ---------------------- thumb_tip = landmark_points[mp_hands.HandLandmark.THUMB_TIP.value] thumb_ip = landmark_points[mp_hands.HandLandmark.THUMB_IP.value] thumb_mcp = landmark_points[mp_hands.HandLandmark.THUMB_MCP.value] # 判断大拇指是否伸展 if handedness == "Right": # 对于右手,如果 TIP 在 MCP 的左侧,则认为大拇指是伸展的 if thumb_tip[0] < thumb_mcp[0]: finger_count += 1 else: # 对于左手,如果 TIP 在 MCP 的右侧,则认为大拇指是伸展的 if thumb_tip[0] > thumb_mcp[0]: finger_count += 1 # ---------------------- 其他手指判断 ---------------------- fingers = [ mp_hands.HandLandmark.INDEX_FINGER_TIP, mp_hands.HandLandmark.MIDDLE_FINGER_TIP, mp_hands.HandLandmark.RING_FINGER_TIP, mp_hands.HandLandmark.PINKY_TIP ] for finger in fingers: tip_y = landmark_points[finger.value][1] pip_y = landmark_points[finger.value - 2][1] # PIP关节是TIP的前两个点 if tip_y < pip_y: # 指尖在PIP关节上方 finger_count += 1 # 显示计数结果 if handedness == "Right": y = 30 # 右手结果显示在 y=40 的位置 else: y = 70 # 左手结果显示在 y=60 的位置 cv2.putText(frame, f"{handedness} Hand: {finger_count}", (10, y), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) # 显示画面 cv2.imshow('Hand Tracking', frame) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows() #--------------------------------------------------------------------------------------------------------------------------- #第五版 import cv2 import mediapipe as mp import pyautogui import math import time import threading # 初始化MediaPipe手势模块 mp_hands = mp.solutions.hands mp_drawing = mp.solutions.drawing_utils # 配置摄像头 cap = cv2.VideoCapture(0) cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) # 降低分辨率以提高帧率 cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) # 设置窗口名称并调整窗口大小 cv2.namedWindow('Hand Gesture Control', cv2.WINDOW_NORMAL) cv2.resizeWindow('Hand Gesture Control', 640, 480) # 设置窗口大小为 1280x720 # 初始化pyautogui pyautogui.FAILSAFE = False # 禁用pyautogui的故障保护功能 # 全局变量用于多线程 frame = None results = None fps = 0 # 图像捕获线程 def capture_frame(): global frame while cap.isOpened(): success, img = cap.read() if not success: break frame = img # 更新全局帧 # 图像处理线程 def process_frame(): global results, fps with mp_hands.Hands( static_image_mode=False, max_num_hands=1, # 只检测一只手 min_detection_confidence=0.7, min_tracking_confidence=0.5 ) as hands: while cap.isOpened(): if frame is None: continue # 镜像模式:水平翻转帧 flipped_frame = cv2.flip(frame, 1) # 转换颜色空间并处理 rgb_frame = cv2.cvtColor(flipped_frame, cv2.COLOR_BGR2RGB) start_time = time.time() results = hands.process(rgb_frame) end_time = time.time() # 计算FPS fps = 1 / (end_time - start_time) # 启动图像捕获线程 capture_thread = threading.Thread(target=capture_frame) capture_thread.daemon = True capture_thread.start() # 启动图像处理线程 process_thread = threading.Thread(target=process_frame) process_thread.daemon = True process_thread.start() while cap.isOpened(): if frame is None or results is None: continue # 镜像模式:水平翻转帧 flipped_frame = cv2.flip(frame, 1) # 绘制手势识别结果 if results.multi_hand_landmarks: for hand_landmarks in results.multi_hand_landmarks: # 绘制关键点 mp_drawing.draw_landmarks( flipped_frame, hand_landmarks, mp_hands.HAND_CONNECTIONS, mp_drawing.DrawingSpec(color=(0, 255, 0), thickness=2), # 关键点 mp_drawing.DrawingSpec(color=(0, 0, 255), thickness=2) # 连接线 ) # 获取所有关键点的像素坐标 h, w = flipped_frame.shape[:2] landmark_points = [(int(lm.x * w), int(lm.y * h)) for lm in hand_landmarks.landmark] # 获取关键点坐标 thumb_tip = landmark_points[mp_hands.HandLandmark.THUMB_TIP.value] index_tip = landmark_points[mp_hands.HandLandmark.INDEX_FINGER_TIP.value] middle_tip = landmark_points[mp_hands.HandLandmark.MIDDLE_FINGER_TIP.value] ring_tip = landmark_points[mp_hands.HandLandmark.RING_FINGER_TIP.value] pinky_tip = landmark_points[mp_hands.HandLandmark.PINKY_TIP.value] wrist = landmark_points[mp_hands.HandLandmark.WRIST.value] # 计算手指是否伸展 fingers = [ (index_tip[1] < landmark_points[mp_hands.HandLandmark.INDEX_FINGER_PIP.value][1]), # 食指 (middle_tip[1] < landmark_points[mp_hands.HandLandmark.MIDDLE_FINGER_PIP.value][1]), # 中指 (ring_tip[1] < landmark_points[mp_hands.HandLandmark.RING_FINGER_PIP.value][1]), # 无名指 (pinky_tip[1] < landmark_points[mp_hands.HandLandmark.PINKY_PIP.value][1]) # 小指 ] # 判断手势 if all(fingers): # 所有手指都伸展(手掌张开) # 模拟鼠标移动 x, y = index_tip[0], index_tip[1] screen_width, screen_height = pyautogui.size() target_x = int((x / w) * screen_width) target_y = int((y / h) * screen_height) pyautogui.moveTo(target_x, target_y, duration=0.1) cv2.putText(flipped_frame, "Mouse Move", (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) elif not any(fingers): # 所有手指都弯曲(握拳) # 模拟鼠标左键点击 pyautogui.click() cv2.putText(flipped_frame, "Click", (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) elif fingers[0] and not any(fingers[1:]): # 只有食指伸展 # 模拟按下空格键 pyautogui.press('space') cv2.putText(flipped_frame, "Space", (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) elif not fingers[0] and not fingers[1] and not fingers[2] and fingers[3]: # 只有大拇指伸展 # 模拟按下Alt+Tab切换窗口 pyautogui.hotkey('alt', 'tab') cv2.putText(flipped_frame, "Alt+Tab", (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) # 显示FPS cv2.putText(flipped_frame, f"FPS: {int(fps)}", (10, 100), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) # 显示画面 cv2.imshow('Hand Gesture Control', flipped_frame) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows() #---------------------------------------------------------------------------------------------------------------------------- #第六版 import cv2 import mediapipe as mp import pyautogui import time import threading # 初始化MediaPipe手势模块 mp_hands = mp.solutions.hands mp_drawing = mp.solutions.drawing_utils # 配置摄像头 cap = cv2.VideoCapture(0) cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) # 降低分辨率以提高帧率 cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) # 设置窗口名称并调整窗口大小 cv2.namedWindow('Hand Gesture Control', cv2.WINDOW_NORMAL) cv2.resizeWindow('Hand Gesture Control', 640, 480) # 设置窗口大小为 1280x720 # 初始化pyautogui pyautogui.FAILSAFE = False # 禁用pyautogui的故障保护功能 # 全局变量用于多线程 frame = None results = None fps = 0 # 初始化点击时间记录 last_click_time = 0 # 图像捕获线程 def capture_frame(): global frame while cap.isOpened(): success, img = cap.read() if not success: break frame = img # 更新全局帧 # 图像处理线程 def process_frame(): global results, fps with mp_hands.Hands( static_image_mode=False, max_num_hands=1, # 只检测一只手 min_detection_confidence=0.7, min_tracking_confidence=0.5 ) as hands: while cap.isOpened(): if frame is None: continue # 镜像模式:水平翻转帧 flipped_frame = cv2.flip(frame, 1) # 转换颜色空间并处理 rgb_frame = cv2.cvtColor(flipped_frame, cv2.COLOR_BGR2RGB) start_time = time.time() results = hands.process(rgb_frame) end_time = time.time() # 计算FPS fps = 1 / (end_time - start_time) # 启动图像捕获线程 capture_thread = threading.Thread(target=capture_frame) capture_thread.daemon = True capture_thread.start() # 启动图像处理线程 process_thread = threading.Thread(target=process_frame) process_thread.daemon = True process_thread.start() while cap.isOpened(): if frame is None or results is None: continue # 镜像模式:水平翻转帧 flipped_frame = cv2.flip(frame, 1) # 绘制手势识别结果 if results.multi_hand_landmarks: for hand_landmarks in results.multi_hand_landmarks: # 绘制关键点 mp_drawing.draw_landmarks( flipped_frame, hand_landmarks, mp_hands.HAND_CONNECTIONS, mp_drawing.DrawingSpec(color=(0, 255, 0), thickness=2), # 关键点 mp_drawing.DrawingSpec(color=(0, 0, 255), thickness=2) # 连接线 ) # 获取所有关键点的像素坐标 h, w = flipped_frame.shape[:2] landmark_points = [(int(lm.x * w), int(lm.y * h)) for lm in hand_landmarks.landmark] # 获取关键点坐标 index_tip = landmark_points[mp_hands.HandLandmark.INDEX_FINGER_TIP.value] index_pip = landmark_points[mp_hands.HandLandmark.INDEX_FINGER_PIP.value] # 判断食指是否伸展 if index_tip[1] < index_pip[1]: # 食指伸展 # 模拟鼠标移动 x, y = index_tip[0], index_tip[1] screen_width, screen_height = pyautogui.size() target_x = int((x / w) * screen_width) target_y = int((y / h) * screen_height) pyautogui.moveTo(target_x, target_y, duration=0.1) cv2.putText(flipped_frame, "Mouse Move", (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) else: # 食指弯曲 current_time = time.time() if current_time - last_click_time > 0.5: # 每隔 0.5 秒才触发一次点击 # 模拟鼠标左键点击 pyautogui.click() last_click_time = current_time # 更新上次点击时间 cv2.putText(flipped_frame, "Click", (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) # 显示FPS cv2.putText(flipped_frame, f"FPS: {int(fps)}", (10, 100), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) # 显示画面 cv2.imshow('Hand Gesture Control', flipped_frame) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows() #------------------------------------------------------------------------------------------------------------------------------- #第七版 import cv2 import mediapipe as mp import pyautogui import time import threading from collections import deque # 初始化MediaPipe手势模块 mp_hands = mp.solutions.hands mp_drawing = mp.solutions.drawing_utils # 配置摄像头 cap = cv2.VideoCapture(0) cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) # 提高分辨率 cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) # 初始化pyautogui pyautogui.FAILSAFE = False # 禁用pyautogui的故障保护功能 # 全局变量用于多线程 frame = None results = None fps = 0 # 初始化点击时间记录 last_click_time = 0 # 防抖参数 smooth_factor = 5 # 移动平均滤波的帧数 position_history = deque(maxlen=smooth_factor) # 用于存储历史位置 dead_zone_threshold = 10 # 死区阈值,小于该值的移动将被忽略 # 图像捕获线程 def capture_frame(): global frame while cap.isOpened(): success, img = cap.read() if not success: break frame = img # 更新全局帧 # 图像处理线程 def process_frame(): global results, fps with mp_hands.Hands( static_image_mode=False, max_num_hands=1, # 只检测一只手 min_detection_confidence=0.7, min_tracking_confidence=0.5 ) as hands: while cap.isOpened(): if frame is None: continue # 关闭镜像模式 flipped_frame = cv2.flip(frame, 1) # 直接使用原始帧 # 转换颜色空间并处理 rgb_frame = cv2.cvtColor(flipped_frame, cv2.COLOR_BGR2RGB) start_time = time.time() results = hands.process(rgb_frame) end_time = time.time() # 计算FPS fps = 1 / (end_time - start_time) # 启动图像捕获线程 capture_thread = threading.Thread(target=capture_frame) capture_thread.daemon = True capture_thread.start() # 启动图像处理线程 process_thread = threading.Thread(target=process_frame) process_thread.daemon = True process_thread.start() while cap.isOpened(): if frame is None or results is None: continue # 关闭镜像模式 flipped_frame = frame # 直接使用原始帧 # 绘制手势识别结果 if results.multi_hand_landmarks: for hand_landmarks in results.multi_hand_landmarks: # 绘制关键点 mp_drawing.draw_landmarks( flipped_frame, hand_landmarks, mp_hands.HAND_CONNECTIONS, mp_drawing.DrawingSpec(color=(0, 255, 0), thickness=2), # 关键点 mp_drawing.DrawingSpec(color=(0, 0, 255), thickness=2) # 连接线 ) # 获取所有关键点的像素坐标 h, w = flipped_frame.shape[:2] landmark_points = [(int(lm.x * w), int(lm.y * h)) for lm in hand_landmarks.landmark] # 获取关键点坐标 index_tip = landmark_points[mp_hands.HandLandmark.INDEX_FINGER_TIP.value] index_pip = landmark_points[mp_hands.HandLandmark.INDEX_FINGER_PIP.value] # 判断食指是否伸展 if index_tip[1] < index_pip[1]: # 食指伸展 # 模拟鼠标移动 x, y = index_tip[0], index_tip[1] screen_width, screen_height = pyautogui.size() # 缩放因子,用于放大控制范围 scale_factor = 1.5 # 例如,放大2倍 # 计算目标鼠标位置 target_x = int((x / w) * screen_width * scale_factor) target_y = int((y / h) * screen_height * scale_factor) # 确保目标位置在屏幕范围内 target_x = max(0, min(target_x, screen_width - 1)) target_y = max(0, min(target_y, screen_height - 1)) # 添加当前位置到历史记录 position_history.append((target_x, target_y)) # 计算移动平均值 if len(position_history) == smooth_factor: avg_x = sum(p[0] for p in position_history) / smooth_factor avg_y = sum(p[1] for p in position_history) / smooth_factor # 死区控制:忽略微小移动 if abs(avg_x - target_x) > dead_zone_threshold or abs(avg_y - target_y) > dead_zone_threshold: pyautogui.moveTo(int(avg_x), int(avg_y), duration=0.1) cv2.putText(flipped_frame, "Mouse Move", (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) else: # 食指弯曲 current_time = time.time() if current_time - last_click_time > 0.5: # 每隔 0.5 秒才触发一次点击 # 模拟鼠标左键点击 pyautogui.click() last_click_time = current_time # 更新上次点击时间 cv2.putText(flipped_frame, "Click", (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) # 显示FPS cv2.putText(flipped_frame, f"FPS: {int(fps)}", (10, 100), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) # 显示画面 cv2.imshow('Hand Gesture Control', flipped_frame) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows() #----------------------------------------------------------------------------------------------------------------------- #第八版 import cv2 import mediapipe as mp import pyautogui import time import threading from collections import deque # 初始化MediaPipe手势模块 mp_hands = mp.solutions.hands mp_drawing = mp.solutions.drawing_utils # 配置摄像头 cap = cv2.VideoCapture(0) if not cap.isOpened(): raise Exception("无法打开摄像头,请检查摄像头连接。") cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) # 初始化pyautogui pyautogui.FAILSAFE = False # 禁用故障保护 # 全局变量与线程锁 frame = None results = None fps = 0 frame_lock = threading.Lock() results_lock = threading.Lock() # 控制板参数 control_board_width = 400 # 控制板宽度 control_board_height = 300 # 控制板高度 control_board_x = 100 # 控制板左上角x坐标 control_board_y = 100 # 控制板左上角y坐标 # 防抖参数 smooth_factor = 5 position_history = deque(maxlen=smooth_factor) dead_zone_threshold = 10 # 图像捕获线程 def capture_frame(): global frame while cap.isOpened(): success, img = cap.read() if not success: print("警告: 无法读取摄像头帧") break with frame_lock: frame = img # 图像处理线程 def process_frame(): global results, fps with mp_hands.Hands( static_image_mode=False, max_num_hands=1, min_detection_confidence=0.7, min_tracking_confidence=0.5 ) as hands: while cap.isOpened(): # 获取并翻转帧 with frame_lock: if frame is None: continue working_frame = cv2.flip(frame, 1) # 处理手势识别 rgb_frame = cv2.cvtColor(working_frame, cv2.COLOR_BGR2RGB) start_time = time.time() processed_results = hands.process(rgb_frame) end_time = time.time() # 更新结果 with results_lock: results = processed_results fps = 1 / (end_time - start_time) # 启动线程 capture_thread = threading.Thread(target=capture_frame, daemon=True) process_thread = threading.Thread(target=process_frame, daemon=True) capture_thread.start() process_thread.start() try: while cap.isOpened(): # 获取当前帧 with frame_lock: if frame is None: continue display_frame = cv2.flip(frame, 1).copy() # 获取处理结果 with results_lock: current_results = results current_fps = fps # 绘制控制板区域 cv2.rectangle(display_frame, (control_board_x, control_board_y), (control_board_x + control_board_width, control_board_y + control_board_height), (0, 255, 0), 2) # 手势识别处理 if current_results and current_results.multi_hand_landmarks: for hand_landmarks in current_results.multi_hand_landmarks: # 绘制关键点 mp_drawing.draw_landmarks( display_frame, hand_landmarks, mp_hands.HAND_CONNECTIONS, mp_drawing.DrawingSpec(color=(0,255,0), thickness=2), # 关键点 mp_drawing.DrawingSpec(color=(0,0,255), thickness=2) # 连接线 ) # 获取食指坐标 h, w = display_frame.shape[:2] landmarks = [(int(lm.x * w), int(lm.y * h)) for lm in hand_landmarks.landmark] tip = landmarks[mp_hands.HandLandmark.INDEX_FINGER_TIP] # 检查食指是否在控制板区域内 if (control_board_x <= tip[0] <= control_board_x + control_board_width and control_board_y <= tip[1] <= control_board_y + control_board_height): # 计算控制板内相对位置 relative_x = tip[0] - control_board_x relative_y = tip[1] - control_board_y # 计算屏幕坐标 screen_w, screen_h = pyautogui.size() target_x = int((relative_x / control_board_width) * screen_w) target_y = int((relative_y / control_board_height) * screen_h) # 防抖处理 position_history.append((target_x, target_y)) if len(position_history) == smooth_factor: avg_x = sum(p[0] for p in position_history) // smooth_factor avg_y = sum(p[1] for p in position_history) // smooth_factor # 死区控制:忽略微小移动 if abs(avg_x - target_x) > dead_zone_threshold or \ abs(avg_y - target_y) > dead_zone_threshold: pyautogui.moveTo(avg_x, avg_y, duration=0.1) cv2.putText(display_frame, "Moving", (10,50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,255,0), 2) # 显示FPS cv2.putText(display_frame, f"FPS: {int(current_fps)}", (10,100), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,255,0), 2) # 显示窗口 cv2.imshow('Gesture Mouse Control', display_frame) if cv2.waitKey(1) & 0xFF == ord('q'): break except Exception as e: print(f"程序异常: {e}") finally: cap.release() cv2.destroyAllWindows() print("程序已正常退出") #--------------------------------------------------------------------------------------------------------------------------- #第九版 import cv2 import mediapipe as mp import pyautogui import time import threading from collections import deque import math class GestureMouseControl: def __init__(self): self.cap = cv2.VideoCapture(0) if not self.cap.isOpened(): raise Exception("无法打开摄像头,请检查摄像头连接。") self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) self.mp_hands = mp.solutions.hands self.mp_drawing = mp.solutions.drawing_utils self.hands = self.mp_hands.Hands( static_image_mode=False, max_num_hands=1, min_detection_confidence=0.7, min_tracking_confidence=0.5 ) self.frame = None self.results = None self.fps = 0 self.frame_lock = threading.Lock() self.results_lock = threading.Lock() # 控制板参数 self.control_board_width = 340 self.control_board_height = 240 self.control_board_x = 150 self.control_board_y = 130 # 边缘缓冲区域宽度 self.edge_buffer = 50 self.smooth_factor = 5 self.position_history = deque(maxlen=self.smooth_factor) self.dead_zone_threshold = 10 # 点击阈值(手指距离小于该值时触发点击) self.click_threshold = 30 # 防抖标志 self.left_clicked = False self.right_clicked = False self.running = True # 平滑滤波参数 self.smoothing_factor = 0.5 self.last_x, self.last_y = pyautogui.position() def capture_frame(self): while self.running: success, img = self.cap.read() if not success: print("警告: 无法读取摄像头帧") break with self.frame_lock: self.frame = img def process_frame(self): while self.running: with self.frame_lock: if self.frame is None: continue working_frame = cv2.flip(self.frame, 1) rgb_frame = cv2.cvtColor(working_frame, cv2.COLOR_BGR2RGB) start_time = time.time() processed_results = self.hands.process(rgb_frame) end_time = time.time() with self.results_lock: self.results = processed_results self.fps = 1 / (end_time - start_time) def run(self): capture_thread = threading.Thread(target=self.capture_frame, daemon=True) process_thread = threading.Thread(target=self.process_frame, daemon=True) capture_thread.start() process_thread.start() try: while self.running: with self.frame_lock: if self.frame is None: continue display_frame = cv2.flip(self.frame, 1).copy() with self.results_lock: current_results = self.results current_fps = self.fps self.draw_control_board(display_frame) self.process_gestures(display_frame, current_results) self.display_fps(display_frame, current_fps) cv2.imshow('Gesture Mouse Control', display_frame) if cv2.waitKey(1) & 0xFF == ord('q'): self.running = False except Exception as e: print(f"程序异常: {e}") finally: self.cap.release() cv2.destroyAllWindows() print("程序已正常退出") def draw_control_board(self, frame): # 绘制控制板 cv2.rectangle(frame, (self.control_board_x, self.control_board_y), (self.control_board_x + self.control_board_width, self.control_board_y + self.control_board_height), (0, 255, 0), 2) # 绘制边缘缓冲区域 cv2.rectangle(frame, (self.control_board_x - self.edge_buffer, self.control_board_y - self.edge_buffer), (self.control_board_x + self.control_board_width + self.edge_buffer, self.control_board_y + self.control_board_height + self.edge_buffer), (0, 0, 255), 1) def process_gestures(self, frame, results): if results and results.multi_hand_landmarks: for hand_landmarks in results.multi_hand_landmarks: self.draw_landmarks(frame, hand_landmarks) self.move_mouse(frame, hand_landmarks) self.detect_clicks(frame, hand_landmarks) def draw_landmarks(self, frame, hand_landmarks): self.mp_drawing.draw_landmarks( frame, hand_landmarks, self.mp_hands.HAND_CONNECTIONS, self.mp_drawing.DrawingSpec(color=(0, 255, 0), thickness=2), self.mp_drawing.DrawingSpec(color=(0, 0, 255), thickness=2) ) def move_mouse(self, frame, hand_landmarks): h, w = frame.shape[:2] landmarks = [(int(lm.x * w), int(lm.y * h)) for lm in hand_landmarks.landmark] tip = landmarks[self.mp_hands.HandLandmark.INDEX_FINGER_TIP] # 检查手指是否在控制板或边缘缓冲区域内 if (self.control_board_x - self.edge_buffer <= tip[0] <= self.control_board_x + self.control_board_width + self.edge_buffer and self.control_board_y - self.edge_buffer <= tip[1] <= self.control_board_y + self.control_board_height + self.edge_buffer): # 计算相对位置(包括缓冲区域) relative_x = tip[0] - (self.control_board_x - self.edge_buffer) relative_y = tip[1] - (self.control_board_y - self.edge_buffer) # 计算目标位置 screen_w, screen_h = pyautogui.size() target_x = int((relative_x / (self.control_board_width + 2 * self.edge_buffer)) * screen_w) target_y = int((relative_y / (self.control_board_height + 2 * self.edge_buffer)) * screen_h) # 使用指数平滑滤波 smoothed_x = self.last_x + self.smoothing_factor * (target_x - self.last_x) smoothed_y = self.last_y + self.smoothing_factor * (target_y - self.last_y) self.last_x, self.last_y = smoothed_x, smoothed_y # 检查是否超过死区阈值 if abs(smoothed_x - target_x) > self.dead_zone_threshold or \ abs(smoothed_y - target_y) > self.dead_zone_threshold: pyautogui.moveTo(int(smoothed_x), int(smoothed_y), duration=0.1) cv2.putText(frame, "Moving", (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) def detect_clicks(self, frame, hand_landmarks): h, w = frame.shape[:2] landmarks = [(int(lm.x * w), int(lm.y * h)) for lm in hand_landmarks.landmark] # 获取指尖坐标 index_tip = landmarks[self.mp_hands.HandLandmark.INDEX_FINGER_TIP] thumb_tip = landmarks[self.mp_hands.HandLandmark.THUMB_TIP] middle_tip = landmarks[self.mp_hands.HandLandmark.MIDDLE_FINGER_TIP] # 计算食指和拇指的距离 index_thumb_distance = math.hypot(index_tip[0] - thumb_tip[0], index_tip[1] - thumb_tip[1]) # 计算中指和拇指的距离 middle_thumb_distance = math.hypot(middle_tip[0] - thumb_tip[0], middle_tip[1] - thumb_tip[1]) # 左键点击(食指和拇指接触) if index_thumb_distance < self.click_threshold: if not self.left_clicked: pyautogui.click(button='left') self.left_clicked = True cv2.putText(frame, "Left Click", (10, 150), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) else: self.left_clicked = False # 右键点击(中指和拇指接触) if middle_thumb_distance < self.click_threshold: if not self.right_clicked: pyautogui.click(button='right') self.right_clicked = True cv2.putText(frame, "Right Click", (10, 200), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) else: self.right_clicked = False def display_fps(self, frame, fps): cv2.putText(frame, f"FPS: {int(fps)}", (10, 100), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) if __name__ == "__main__": gesture_mouse_control = GestureMouseControl() gesture_mouse_control.run()
免责:中间代码可能有错误(新人创作,轻点喷)
安装库可以转上一篇