news 2026/4/15 19:58:21

Mac 真人手势识别切水果游戏

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Mac 真人手势识别切水果游戏

1. 环境

mac python10

2. 代码

import cv2 import mediapipe as mp import time import numpy as np import random import math # 初始化MediaPipe解决方案 mp_hands = mp.solutions.hands mp_face_mesh = mp.solutions.face_mesh mp_draw = mp.solutions.drawing_utils # 自定义绘制样式 face_drawing_spec = mp_draw.DrawingSpec(thickness=1, circle_radius=1, color=(0, 255, 0)) hand_drawing_spec = mp_draw.DrawingSpec(thickness=2, circle_radius=3, color=(0, 0, 255)) # 初始化模型 hands = mp_hands.Hands( static_image_mode=False, max_num_hands=2, min_detection_confidence=0.5, # 降低检测阈值,提高灵敏度 min_tracking_confidence=0.3 # 降低跟踪阈值 ) face_mesh = mp_face_mesh.FaceMesh( static_image_mode=False, max_num_faces=1, min_detection_confidence=0.5, min_tracking_confidence=0.5 ) # 打开摄像头 cap = cv2.VideoCapture(0) if not cap.isOpened(): print("无法打开摄像头,请检查连接。") exit() # 设置摄像头分辨率(适中分辨率以保证性能) cap.set(cv2.CAP_PROP_FRAME_WIDTH, 720) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720) print("=== 切水果游戏 ===") print("游戏规则:") print("1. 伸出食指作为'刀'来切水果") print("2. 切中水果得分,错过扣分") print("3. 保持笑脸可以获得分数加成!") print("游戏时间:2分钟") print("控制:") print("Q - 退出游戏") print("R - 重新开始游戏") print("H - 显示/隐藏手部检测") print("F - 显示/隐藏面部检测") print("==================") # 游戏状态 show_hands = True show_face = False game_active = True score = 0 combo = 0 max_combo = 0 game_start_time = time.time() game_duration = 60 # 游戏时长120秒(2分钟) show_fireworks = False fireworks_start_time = 0 fireworks_duration = 5 # 烟花效果持续时间(秒) # FPS计算 pTime = 0 # 烟花粒子类 class FireworkParticle: def __init__(self, x, y): self.x = x self.y = y self.color = ( random.randint(150, 255), random.randint(150, 255), random.randint(150, 255) ) self.size = random.randint(2, 6) self.speed_x = random.uniform(-5, 5) self.speed_y = random.uniform(-8, -3) self.life = 100 self.gravity = 0.2 self.trail = [] def update(self): self.x += self.speed_x self.y += self.speed_y self.speed_y += self.gravity self.life -= 2 # 添加轨迹点 self.trail.append((int(self.x), int(self.y))) if len(self.trail) > 5: self.trail.pop(0) return self.life > 0 def draw(self, frame): # 绘制轨迹 for i in range(1, len(self.trail)): alpha = i / len(self.trail) color = ( int(self.color[0] * alpha), int(self.color[1] * alpha), int(self.color[2] * alpha) ) cv2.line(frame, self.trail[i-1], self.trail[i], color, 1) # 绘制粒子 cv2.circle(frame, (int(self.x), int(self.y)), self.size, self.color, -1) cv2.circle(frame, (int(self.x), int(self.y)), self.size, (255, 255, 255), 1) # 烟花效果 fireworks = [] def create_fireworks_effect(x, y, count=30): """在指定位置创建烟花效果""" for _ in range(count): fireworks.append(FireworkParticle(x, y)) # 水果类 class Fruit: def __init__(self, width, height): self.types = ['apple', 'banana', 'orange', 'watermelon', 'bomb'] self.colors = { 'apple': (0, 0, 255), # 红色 'banana': (0, 200, 255), # 黄色 'orange': (0, 165, 255), # 橙色 'watermelon': (0, 255, 0), # 绿色 'bomb': (100, 100, 100) # 灰色 } self.type = random.choice(self.types) self.color = self.colors[self.type] self.radius = random.randint(20, 45) # 减小最小半径,让小水果更容易识别 # 初始位置(从屏幕顶部随机位置出现) self.x = random.randint(self.radius, width - self.radius) self.y = -self.radius # 速度 self.speed_x = random.uniform(-2.0, 2.0) self.speed_y = random.uniform(3.0, 6.0) # 旋转(用于动画效果) self.angle = 0 self.rotation_speed = random.uniform(-3.0, 3.0) # 状态 self.sliced = False self.slice_time = 0 self.slice_animation = 0 # 得分值 self.points = { 'apple': 10, 'banana': 15, 'orange': 20, 'watermelon': 30, 'bomb': -50 # 炸弹扣分 } self.point_value = self.points[self.type] # 切割特效颜色 self.slice_color = ( min(255, self.color[0] + 50), min(255, self.color[1] + 50), min(255, self.color[2] + 50) ) def update(self, height, width): if not self.sliced: # 更新位置 self.x += self.speed_x self.y += self.speed_y # 边界反弹 if self.x <= self.radius or self.x >= width - self.radius: self.speed_x *= -0.8 # 添加摩擦力 self.x = max(self.radius, min(width - self.radius, self.x)) # 旋转 self.angle += self.rotation_speed # 检查是否掉出屏幕 if self.y > height + self.radius: return False # 水果应该被移除 else: # 切割动画 self.slice_animation += 1 if time.time() - self.slice_time > 1.5: # 1.5秒后消失 return False return True def draw(self, frame): if not self.sliced: # 绘制水果(带旋转效果) angle_rad = math.radians(self.angle) # 绘制水果主体 cv2.circle(frame, (int(self.x), int(self.y)), self.radius, self.color, -1) # 绘制高光(只对大水果) if self.radius > 25: highlight_radius = self.radius // 3 highlight_x = int(self.x - highlight_radius * math.cos(angle_rad)) highlight_y = int(self.y - highlight_radius * math.sin(angle_rad)) cv2.circle(frame, (highlight_x, highlight_y), highlight_radius // 2, (255, 255, 255), -1) # 绘制水果细节(只对大水果) if self.radius > 30: if self.type == 'apple': # 苹果梗 cv2.line(frame, (int(self.x), int(self.y - self.radius)), (int(self.x), int(self.y - self.radius - 15)), (80, 40, 0), 2) cv2.circle(frame, (int(self.x), int(self.y - self.radius - 15)), 2, (100, 50, 0), -1) elif self.type == 'banana': # 香蕉曲线 cv2.ellipse(frame, (int(self.x), int(self.y)), (self.radius-8, self.radius), self.angle, 0, 180, (30, 120, 180), 1) elif self.type == 'bomb': # 炸弹引线 cv2.line(frame, (int(self.x), int(self.y - self.radius)), (int(self.x + 10), int(self.y - self.radius - 20)), (50, 50, 50), 2) cv2.circle(frame, (int(self.x + 10), int(self.y - self.radius - 20)), 2, (200, 0, 0), -1) else: # 绘制被切割的水果(两部分) slice_offset = min(self.slice_animation * 5, 30) rotation = self.angle + self.slice_animation * 10 # 左半部分(旋转下落) left_x = int(self.x - slice_offset) left_y = int(self.y + self.slice_animation * 2) cv2.ellipse(frame, (left_x, left_y), (self.radius, self.radius//2), rotation, 0, 180, self.slice_color, -1) # 右半部分(旋转下落) right_x = int(self.x + slice_offset) right_y = int(self.y + self.slice_animation * 2) cv2.ellipse(frame, (right_x, right_y), (self.radius, self.radius//2), -rotation, 180, 360, self.slice_color, -1) # 绘制果汁溅射效果 for _ in range(max(1, self.radius // 10)): # 根据水果大小决定溅射点数 juice_x = int(self.x) + random.randint(-self.radius, self.radius) juice_y = int(self.y) + random.randint(-self.radius//2, self.radius//2) juice_size = random.randint(2, max(3, self.radius//8)) cv2.circle(frame, (juice_x, juice_y), juice_size, self.slice_color, -1) def check_slice(self, finger_x, finger_y, prev_finger_x, prev_finger_y): """检查手指是否切中了水果 - 优化小水果识别""" if self.sliced: return False # 方法1:检查当前手指位置是否在水果内(主要方法) distance = math.sqrt((finger_x - self.x)**2 + (finger_y - self.y)**2) # 动态阈值:小水果使用更宽松的阈值 slice_threshold = self.radius * 1.2 # 增加20%的检测范围 # 方法2:检查手指移动路径是否穿过水果(备用方法) path_sliced = False if prev_finger_x > 0 and prev_finger_y > 0 and distance > slice_threshold: # 计算手指移动线段与水果圆心的最短距离 line_length = math.sqrt((finger_x - prev_finger_x)**2 + (finger_y - prev_finger_y)**2) if line_length > 0: # 计算点到线段的距离 t = max(0, min(1, ((self.x - prev_finger_x)*(finger_x - prev_finger_x) + (self.y - prev_finger_y)*(finger_y - prev_finger_y)) / (line_length**2))) closest_x = prev_finger_x + t * (finger_x - prev_finger_x) closest_y = prev_finger_y + t * (finger_y - prev_finger_y) distance_to_path = math.sqrt((self.x - closest_x)**2 + (self.y - closest_y)**2) # 如果路径穿过水果 if distance_to_path <= slice_threshold: path_sliced = True # 如果当前位置或路径穿过水果 if distance <= slice_threshold or path_sliced: self.sliced = True self.slice_time = time.time() return True return False # 游戏水果列表 fruits = [] fruit_spawn_rate = 1.2 # 每秒生成水果的概率 # 手指追踪 finger_trail = [] prev_finger_x, prev_finger_y = -1, -1 max_trail_length = 15 def detect_finger_position(hand_landmarks, frame_shape): """检测食指指尖位置 - 简化版本""" h, w, _ = frame_shape # 食指指尖的索引是8 index_finger_tip = hand_landmarks.landmark[8] # 转换为像素坐标 x = int(index_finger_tip.x * w) y = int(index_finger_tip.y * h) # 由于后面会做镜像翻转,这里需要计算镜像后的x坐标 # 镜像公式:x_mirrored = width - x x_mirrored = w - x return x_mirrored, y def count_extended_fingers_simple(hand_landmarks, frame_shape): """计算伸直的手指数量 - 简化但更可靠的版本""" h, w, _ = frame_shape # 关键点索引 tip_ids = [4, 8, 12, 16, 20] # 指尖:拇指、食指、中指、无名指、小指 pip_ids = [3, 6, 10, 14, 18] # 第二关节 extended_count = 0 index_finger_extended = False # 检查拇指(简化逻辑) thumb_tip = hand_landmarks.landmark[tip_ids[0]] thumb_pip = hand_landmarks.landmark[pip_ids[0]] # 如果拇指指尖在PIP关节左侧(对于右手) if thumb_tip.x < thumb_pip.x: extended_count += 1 # 检查其他四指 for i in range(1, 5): tip = hand_landmarks.landmark[tip_ids[i]] pip = hand_landmarks.landmark[pip_ids[i]] # 简单判断:如果指尖在PIP关节上方(y坐标更小) # 添加一些容错空间 if tip.y < pip.y - 0.02: # 减少阈值,提高灵敏度 extended_count += 1 if i == 1: # 食指 index_finger_extended = True return extended_count, index_finger_extended def is_index_finger_extended(hand_landmarks): """专门检测食指是否伸直 - 更精确的方法""" # 食指关键点 index_tip = hand_landmarks.landmark[8] # 食指指尖 index_pip = hand_landmarks.landmark[6] # 食指PIP关节 index_mcp = hand_landmarks.landmark[5] # 食指MCP关节 # 计算角度来判断食指是否伸直 # 方法1:检查指尖是否在PIP关节上方 if index_tip.y < index_pip.y: # 方法2:检查指尖到MCP的距离是否大于PIP到MCP的距离 tip_to_mcp = math.sqrt((index_tip.x - index_mcp.x)**2 + (index_tip.y - index_mcp.y)**2) pip_to_mcp = math.sqrt((index_pip.x - index_mcp.x)**2 + (index_pip.y - index_mcp.y)**2) # 如果指尖离MCP比PIP离MCP更远,说明手指伸直 if tip_to_mcp > pip_to_mcp * 1.1: return True return False def detect_expression(face_landmarks, frame_shape): """基于面部关键点检测简单表情""" h, w, _ = frame_shape landmarks = face_landmarks.landmark # 嘴部关键点 mouth_top = landmarks[13] mouth_bottom = landmarks[14] mouth_top_y = int(mouth_top.y * h) mouth_bottom_y = int(mouth_bottom.y * h) mouth_height = abs(mouth_bottom_y - mouth_top_y) # 嘴角 left_corner = landmarks[61] right_corner = landmarks[291] # 表情判断 expression = "Neutral" color = (200, 200, 200) is_smiling = False # 检测微笑 if mouth_height > 15: if left_corner.y < mouth_top.y and right_corner.y < mouth_top.y: expression = "Smiling" color = (0, 255, 255) is_smiling = True else: expression = "Surprised" color = (255, 0, 0) return expression, color, is_smiling def draw_game_info(frame, fps, score, combo, max_combo, time_left, is_smiling, finger_x, finger_y): """绘制游戏信息面板""" h, w = frame.shape[:2] # 创建半透明信息面板 overlay = frame.copy() cv2.rectangle(overlay, (10, 10), (450, 220), (0, 0, 0), -1) frame = cv2.addWeighted(overlay, 0.7, frame, 0.3, 0) # 显示游戏信息 cv2.putText(frame, f'Fruit Slash!', (20, 45), cv2.FONT_HERSHEY_SIMPLEX, 1.3, (0, 255, 255), 3) cv2.putText(frame, f'Score: {score}', (20, 85), cv2.FONT_HERSHEY_SIMPLEX, 1.1, (255, 255, 255), 2) combo_color = (0, 255, 0) if combo > 1 else (200, 200, 200) cv2.putText(frame, f'Combo: x{combo}', (20, 125), cv2.FONT_HERSHEY_SIMPLEX, 1.1, combo_color, 2) # 时间显示颜色变化 time_color = (255, 255, 0) if time_left < 30: # 最后30秒变红色 time_color = (0, 0, 255) if int(time_left) % 2 == 0 else (255, 255, 0) minutes = int(time_left) // 60 seconds = int(time_left) % 60 cv2.putText(frame, f'Time: {minutes:02d}:{seconds:02d}', (20, 165), cv2.FONT_HERSHEY_SIMPLEX, 1.1, time_color, 2) # 表情加成提示 if is_smiling: cv2.putText(frame, f'Smile Bonus: +{combo*2}', (20, 205), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 255), 2) # 游戏提示 cv2.putText(frame, "Use INDEX finger to slice!", (w-400, 40), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (150, 150, 255), 2) # 在手指位置绘制"刀"的图标 if finger_x > 0 and finger_y > 0 and 0 <= finger_x < w and 0 <= finger_y < h: # 绘制刀光效果 for i in range(1, len(finger_trail)): if i < len(finger_trail) and len(finger_trail[i-1]) == 2 and len(finger_trail[i]) == 2: x1, y1 = finger_trail[i-1] x2, y2 = finger_trail[i] if (0 <= x1 < w and 0 <= y1 < h and 0 <= x2 < w and 0 <= y2 < h): thickness = max(1, 4 - i // 4) alpha = 1.0 - (i / len(finger_trail)) color = ( int(255 * alpha), int(255 * alpha), int(200 * alpha) ) try: cv2.line(frame, (int(x1), int(y1)), (int(x2), int(y2)), color, thickness) except: pass # 当前手指位置(刀尖) try: # 绘制更大的手指指示器,便于瞄准小水果 cv2.circle(frame, (int(finger_x), int(finger_y)), 15, (255, 255, 255), 2) cv2.circle(frame, (int(finger_x), int(finger_y)), 8, (0, 200, 255), -1) # 绘制瞄准十字 cv2.line(frame, (int(finger_x - 10), int(finger_y)), (int(finger_x + 10), int(finger_y)), (255, 255, 255), 1) cv2.line(frame, (int(finger_x), int(finger_y - 10)), (int(finger_x), int(finger_y + 10)), (255, 255, 255), 1) except: pass return frame def draw_game_over(frame, score, max_combo): """绘制游戏结束画面""" h, w = frame.shape[:2] # 半透明黑色背景 overlay = frame.copy() cv2.rectangle(overlay, (0, 0), (w, h), (0, 0, 0), -1) frame = cv2.addWeighted(overlay, 0.7, frame, 0.3, 0) # 游戏结束标题 cv2.putText(frame, "GAME OVER!", (w//2 - 180, h//2 - 100), cv2.FONT_HERSHEY_SIMPLEX, 2.5, (0, 0, 255), 4) # 得分显示 cv2.putText(frame, f"Final Score: {score}", (w//2 - 150, h//2 - 20), cv2.FONT_HERSHEY_SIMPLEX, 1.8, (255, 255, 255), 3) # 最大连击 cv2.putText(frame, f"Max Combo: x{max_combo}", (w//2 - 140, h//2 + 30), cv2.FONT_HERSHEY_SIMPLEX, 1.5, (0, 255, 255), 3) # 评价 if score >= 1000: evaluation = "EXCELLENT! You're a Fruit Ninja Master!" color = (0, 255, 0) elif score >= 500: evaluation = "GREAT! Keep practicing!" color = (0, 200, 255) elif score >= 200: evaluation = "GOOD JOB!" color = (255, 255, 0) else: evaluation = "Nice try! Play again!" color = (255, 150, 0) cv2.putText(frame, evaluation, (w//2 - 200, h//2 + 80), cv2.FONT_HERSHEY_SIMPLEX, 1.2, color, 3) # 重新开始提示 cv2.putText(frame, "Press 'R' to restart or 'Q' to quit", (w//2 - 200, h//2 + 140), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (200, 200, 0), 2) return frame # 主游戏循环 print("开始游戏!请伸出食指...") print("提示:确保手部在摄像头范围内,光照良好") while True: success, frame = cap.read() if not success: print("无法读取视频流。") break # 获取帧尺寸 h, w, _ = frame.shape # 转换颜色空间(在镜像前处理) rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # 游戏逻辑 current_time = time.time() time_left = max(0, game_duration - (current_time - game_start_time)) # 烟花效果逻辑 if show_fireworks: if current_time - fireworks_start_time < fireworks_duration: # 更新和绘制烟花 fireworks_to_remove = [] for i, firework in enumerate(fireworks): if not firework.update(): fireworks_to_remove.append(i) else: firework.draw(frame) # 移除已完成的烟花 for i in sorted(fireworks_to_remove, reverse=True): fireworks.pop(i) # 随机添加新烟花 if random.random() < 0.3: x = random.randint(100, w-100) y = random.randint(100, h-100) create_fireworks_effect(x, y, random.randint(20, 40)) else: show_fireworks = False fireworks = [] # 生成新水果 if game_active and time_left > 0 and random.random() < fruit_spawn_rate * 0.033: fruits.append(Fruit(w, h)) # 处理手部检测 - 优化版本 finger_x, finger_y = -1, -1 extended_fingers = 0 is_slicing = False if show_hands: hand_results = hands.process(rgb_frame) if hand_results.multi_hand_landmarks: for hand_landmarks in hand_results.multi_hand_landmarks: if show_hands: # 只绘制关键点和连接线,减少视觉干扰 mp_draw.draw_landmarks( frame, hand_landmarks, mp_hands.HAND_CONNECTIONS, mp_draw.DrawingSpec(color=(0, 255, 0), thickness=2), mp_draw.DrawingSpec(color=(255, 0, 255), thickness=2) ) # 使用专门的方法检测食指 if is_index_finger_extended(hand_landmarks): # 检测手指位置 fx, fy = detect_finger_position(hand_landmarks, (h, w, 3)) # 确保手指位置有效 if 0 <= fx < w and 0 <= fy < h: finger_x, finger_y = fx, fy is_slicing = True extended_fingers = 1 # 备用方法:使用简化检测 if not is_slicing: ext_count, index_extended = count_extended_fingers_simple(hand_landmarks, (h, w, 3)) if index_extended: fx, fy = detect_finger_position(hand_landmarks, (h, w, 3)) if 0 <= fx < w and 0 <= fy < h: finger_x, finger_y = fx, fy is_slicing = True extended_fingers = ext_count # 镜像翻转(在手指检测后) frame = cv2.flip(frame, 1) # 更新手指轨迹 if is_slicing and finger_x > 0 and finger_y > 0 and 0 <= finger_x < w and 0 <= finger_y < h: # 在镜像后的坐标系中处理手指位置 finger_trail.append((finger_x, finger_y)) if len(finger_trail) > max_trail_length: finger_trail.pop(0) else: if len(finger_trail) > 0: # 逐渐清空轨迹 finger_trail = finger_trail[1:] if len(finger_trail) > 1 else [] # 处理面部检测 is_smiling = False if show_face: face_results = face_mesh.process(rgb_frame) if face_results.multi_face_landmarks: for face_landmarks in face_results.multi_face_landmarks: if show_face: # 只绘制面部关键轮廓 mp_draw.draw_landmarks( frame, face_landmarks, mp_face_mesh.FACEMESH_CONTOURS, landmark_drawing_spec=None, connection_drawing_spec=face_drawing_spec ) # 检测表情 expression, expr_color, smiling = detect_expression(face_landmarks, (h, w, 3)) is_smiling = smiling # 显示表情标签 cv2.putText(frame, expression, (w//2 - 100, 60), cv2.FONT_HERSHEY_SIMPLEX, 1.2, expr_color, 2) # 更新和绘制水果 fruits_to_remove = [] for i, fruit in enumerate(fruits): # 更新水果状态 if not fruit.update(h, w): fruits_to_remove.append(i) continue # 检查是否被切割 if is_slicing and finger_x > 0 and finger_y > 0: if fruit.check_slice(finger_x, finger_y, prev_finger_x, prev_finger_y): # 计算得分 points_earned = fruit.point_value # 连击加成 if points_earned > 0: combo += 1 points_earned *= combo # 微笑加成 if is_smiling: points_earned += combo * 2 max_combo = max(max_combo, combo) # 在水果位置创建烟花效果 create_fireworks_effect(int(fruit.x), int(fruit.y), max(10, fruit.radius//2)) else: # 切到炸弹,连击中断 combo = 0 # 炸弹爆炸效果 for _ in range(max(10, fruit.radius//2)): fireworks.append(FireworkParticle(int(fruit.x), int(fruit.y))) score += points_earned # 显示得分 display_x = max(50, min(w-150, int(fruit.x))) display_y = max(50, min(h-50, int(fruit.y - 40))) score_text = f"+{points_earned}" if points_earned > 0 else f"{points_earned}" text_color = (0, 255, 0) if points_earned > 0 else (0, 0, 255) # 得分文本阴影效果 cv2.putText(frame, score_text, (display_x+2, display_y+2), cv2.FONT_HERSHEY_SIMPLEX, 1.2, (0, 0, 0), 3) cv2.putText(frame, score_text, (display_x, display_y), cv2.FONT_HERSHEY_SIMPLEX, 1.2, text_color, 2) # 绘制水果 fruit.draw(frame) # 保存当前手指位置作为下一帧的"上一帧位置" prev_finger_x, prev_finger_y = finger_x, finger_y # 移除需要删除的水果 for i in sorted(fruits_to_remove, reverse=True): fruits.pop(i) # 检查游戏结束 if game_active and time_left <= 0: game_active = False show_fireworks = True fireworks_start_time = current_time # 创建大量烟花庆祝 for _ in range(5): x = random.randint(100, w-100) y = random.randint(100, h-100) create_fireworks_effect(x, y, random.randint(30, 50)) # 计算FPS cTime = time.time() fps = 1 / (cTime - pTime) if (cTime - pTime) > 0 else 0 pTime = cTime # 绘制游戏界面 if game_active: frame = draw_game_info(frame, fps, score, combo, max_combo, time_left, is_smiling, finger_x, finger_y) # 显示手指状态提示 if is_slicing: cv2.putText(frame, "READY TO SLICE!", (w-300, h-30), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 0), 2) else: cv2.putText(frame, "EXTEND INDEX FINGER", (w-350, h-30), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (200, 200, 0), 2) else: frame = draw_game_over(frame, score, max_combo) # 显示图像 cv2.imshow('Fruit Slash Game - 2 Minute Challenge!', frame) # 键盘控制 key = cv2.waitKey(1) & 0xFF if key == ord('q'): # 退出 break elif key == ord('r'): # 重新开始游戏 fruits = [] finger_trail = [] fireworks = [] score = 0 combo = 0 max_combo = 0 game_start_time = time.time() game_active = True show_fireworks = False print("游戏重新开始!") elif key == ord('h'): # 切换手部检测显示 show_hands = not show_hands print(f"手部检测: {'显示' if show_hands else '隐藏'}") elif key == ord('f'): # 切换面部检测显示 show_face = not show_face print(f"面部检测: {'显示' if show_face else '隐藏'}") elif key == ord('d'): # 调试模式:显示检测信息 print(f"手指状态: 切割={is_slicing}, 坐标=({finger_x}, {finger_y})") print(f"水果数量: {len(fruits)}") # 释放资源 cap.release() cv2.destroyAllWindows()

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 12:45:38

UDP网络巩固知识基础题(1)

1. UDP协议在接收端如何处理校验和错误的数据报&#xff1f;A. 自动重传请求 B. 丢弃数据报并通知发送端 C. 丢弃数据报但不通知发送端 D. 尝试纠正错误答案&#xff1a;C 解析&#xff1a; UDP是不可靠协议&#xff0c;当接收端检测到校验和错误时&#xff0c;直接丢弃该数据报…

作者头像 李华
网站建设 2026/4/16 13:45:49

day23 常见特征筛选算法

1.方差筛选 是最基础的过滤法:计算特征的方差&#xff0c;剔除方差极低的特征(这类特征数值变化小&#xff0c;对样本区分度弱)。优点是计算极快&#xff0c;缺点是只看特征自身&#xff0c;不考虑和目标的关联。 2.皮尔逊相关系数筛选 属于过滤法:计算特征与目标变量的皮尔逊相…

作者头像 李华
网站建设 2026/4/16 13:42:59

双塔emb模型的分类头

class SimpleConcatMLPHead(nn.Module):"""MLP分类头:使用多种交互特征,提升embedding效果"""def __init__(self,hidden_size: int,num_labels:

作者头像 李华
网站建设 2026/4/16 11:00:48

杂项设备驱动/应用层与内核层数据传输

声明&#xff1a;内容源于B站UP主——北京迅为电子一、简介字符设备&#xff1a;IO的传递传递过程是以字符设备为单位的&#xff0c;没有缓冲&#xff0c;比如I2C,SPI都是字符设备 块设备&#xff1a;IO传递过程是一块为单位的&#xff0c;跟存储相关的&#xff0c;都属于块设备…

作者头像 李华
网站建设 2026/4/16 16:20:33

百度网盘直链解析实战手册:突破限速封锁的完整解决方案

还在为百度网盘蜗牛般的下载速度而焦虑吗&#xff1f;当你急需下载重要文件&#xff0c;却只能眼睁睁看着几十KB/s的进度条缓慢爬行&#xff0c;那种无助感确实令人沮丧。现在&#xff0c;通过百度网盘直链解析工具的巧妙应用&#xff0c;你将彻底告别这种困境&#xff0c;实现…

作者头像 李华
网站建设 2026/4/16 10:42:42

Springboot医院门诊管理系统fcdrv(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。

系统程序文件列表项目功能&#xff1a;用户,医院简介,医生,科室信息,扣减金额,余额充值,用户钱包,就医指南,挂号预约,医生诊疗开题报告内容Spring Boot医院门诊管理系统开题报告一、选题依据&#xff08;一&#xff09;研究背景在医疗行业快速发展的当下&#xff0c;医院门诊作…

作者头像 李华