提升网站权重的策略,自己做一个外贸网站怎么样,长沙手机网站建设公司排名,如何成立一个自己的品牌在这个数字化飞速发展的时代#xff0c;手势识别技术正逐渐走入我们的日常生活#xff0c;从智能家居到增强现实#xff0c;无处不在。而今天#xff0c;我将与大家分享一个充满创意和趣味的项目——空中绘图板。这个项目利用了强大的 Mediapipe 库和 OpenCV#xff0c;实…在这个数字化飞速发展的时代手势识别技术正逐渐走入我们的日常生活从智能家居到增强现实无处不在。而今天我将与大家分享一个充满创意和趣味的项目——空中绘图板。这个项目利用了强大的 Mediapipe 库和 OpenCV实现了通过手势在空中绘制图形的功能。无论你是编程新手还是资深开发者这个项目都将为你带来灵感和乐趣。 项目概述
空中绘图板 是一个基于计算机视觉和手势识别技术的应用程序。用户可以通过简单的手势在空中“绘制”图形切换颜色甚至保存和加载绘图内容。这个项目不仅展示了手势识别的实用性还提供了一种全新的交互体验。
主要功能
手势绘图通过检测食指和拇指的尖端位置实现自由绘图、直线绘图和圆形绘图。颜色选择使用特定的手势切换绘图颜色支持多种颜色选择。撤销与重做通过手势实现绘图操作的撤销与重做。保存与加载允许用户保存当前绘图内容并在需要时加载。多手检测支持同时检测多只手提供更多交互方式。用户界面在窗口中显示当前颜色、绘图模式以及操作指南。
技术栈
Mediapipe用于实时手势检测和关键点识别。OpenCV处理视频流、绘图和图像显示。NumPy处理数组和数学运算。Pickle序列化和反序列化绘图内容实现保存与加载功能。
代码详解
这个项目的核心是一个名为 AirDrawingApp 的类它封装了摄像头捕捉、手势识别、绘图操作以及用户界面显示等功能。下面我们将逐步解析这个项目的关键部分。
手势识别
手势识别是整个应用的核心通过 Mediapipe 的手部模型实时检测用户的手部位置并根据手指的张开状态识别不同的手势。
def recognize_gesture(hand_landmarks):简单手势识别- 张开五指无动作- 做出“OK”手势颜色切换- 做出“拳头”手势清除画布- 做出“食指伸出”手势撤销- 做出“中指伸出”手势重做- 做出“拇指和小指伸出”手势保存画布- 做出“食指和中指伸出”手势加载画布- 做出四指伸出手势切换绘图模式# 获取各个手指的状态finger_tips_ids [4, 8, 12, 16, 20]fingers []for tip_id in finger_tips_ids:if hand_landmarks.landmark[tip_id].y hand_landmarks.landmark[tip_id - 2].y:fingers.append(1)else:fingers.append(0)total_fingers fingers.count(1)# 判断手势if total_fingers 0:return GESTURE_CLEARelif total_fingers 1:# 判断是否为“食指伸出”手势用于撤销if fingers[1] 1 and fingers[0] fingers[2] fingers[3] fingers[4] 0:return GESTURE_UNDOelif total_fingers 2:# 判断是否为“OK”手势拇指和食指接触用于颜色切换distance np.sqrt((hand_landmarks.landmark[4].x - hand_landmarks.landmark[8].x) ** 2 (hand_landmarks.landmark[4].y - hand_landmarks.landmark[8].y) ** 2)if distance 0.05:return GESTURE_COLOR_CHANGEelse:# 判断是否为“食指和中指伸出”手势用于加载画布if fingers[1] 1 and fingers[2] 1 and fingers[0] fingers[3] fingers[4] 0:return GESTURE_LOADelif total_fingers 3:# 判断是否为“中指伸出”手势用于重做if fingers[2] 1 and fingers[0] fingers[1] fingers[3] fingers[4] 0:return GESTURE_REDOelif total_fingers 4:# 判断是否为“绘图模式切换”手势四指伸出return GESTURE_DRAW_MODEelif total_fingers 5:# 全部五指伸出无动作return Nonereturn None通过手指的张开状态和相互之间的距离我们可以识别出不同的手势并执行相应的操作。
AirDrawingApp 类
AirDrawingApp 类是整个应用的核心负责处理摄像头输入、手势识别、绘图逻辑和用户界面显示。
class AirDrawingApp:def __init__(self):# 初始化摄像头self.cap cv2.VideoCapture(0)self.cap.set(3, 1280) # 设置宽度self.cap.set(4, 720) # 设置高度# 初始化 Mediapipe Handsself.hands mp_hands.Hands(max_num_hands2,min_detection_confidence0.7,min_tracking_confidence0.5)# 创建一个空白的画布self.canvas np.zeros((720, 1280, 3), dtypenp.uint8)# 用于存储前一个点的位置self.prev_points {} # 针对每只手# 撤销和重做栈self.undo_stack deque(maxlen20)self.redo_stack deque(maxlen20)# 画笔粗细self.brush_thickness 5# 当前选中的颜色self.current_color current_colorself.color_index color_index# 当前绘图模式self.current_draw_mode current_draw_modeself.draw_mode_index draw_mode_index# 标记画布是否被修改self.canvas_modified False核心功能方法
绘图方法支持自由绘图、直线绘图和圆形绘图。撤销与重做利用栈结构实现撤销和重做功能。保存与加载使用 pickle 序列化画布内容实现保存与加载。颜色和绘图模式切换通过手势切换当前绘图颜色和绘图模式。 def save_canvas(self, filenamecanvas.pkl):with open(filename, wb) as f:pickle.dump(self.canvas, f)print(Canvas saved.)def load_canvas(self, filenamecanvas.pkl):if os.path.exists(filename):with open(filename, rb) as f:self.canvas pickle.load(f)print(Canvas loaded.)else:print(No saved canvas found.)def undo(self):if self.undo_stack:self.redo_stack.append(self.canvas.copy())self.canvas self.undo_stack.pop()print(Undo performed.)else:print(Nothing to undo.)def redo(self):if self.redo_stack:self.undo_stack.append(self.canvas.copy())self.canvas self.redo_stack.pop()print(Redo performed.)else:print(Nothing to redo.)def clear_canvas(self):self.undo_stack.append(self.canvas.copy())self.canvas np.zeros((720, 1280, 3), dtypenp.uint8)print(Canvas cleared.)def change_color(self):self.color_index (self.color_index 1) % len(colors)self.current_color colors[self.color_index]print(fColor changed to {color_names[self.color_index]}.)def change_draw_mode(self):self.draw_mode_index (self.draw_mode_index 1) % len(draw_modes)self.current_draw_mode draw_modes[self.draw_mode_index]print(fDraw mode changed to {self.current_draw_mode}.)处理视频帧
通过摄像头捕捉每一帧视频进行手势识别和绘图操作。
def process_frame(self, frame):frame_rgb cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)results self.hands.process(frame_rgb)gesture Noneif results.multi_hand_landmarks:for hand_idx, hand_landmarks in enumerate(results.multi_hand_landmarks):# 绘制手部关键点mp_drawing.draw_landmarks(frame, hand_landmarks, mp_hands.HAND_CONNECTIONS,mp_drawing.DrawingSpec(color(0, 0, 255), thickness2, circle_radius2),mp_drawing.DrawingSpec(color(0, 255, 0), thickness2, circle_radius2))# 识别手势gesture recognize_gesture(hand_landmarks)# 获取食指和拇指的坐标x1 int(hand_landmarks.landmark[8].x * 1280)y1 int(hand_landmarks.landmark[8].y * 720)x2 int(hand_landmarks.landmark[4].x * 1280)y2 int(hand_landmarks.landmark[4].y * 720)# 计算中点mid_x int((x1 x2) / 2)mid_y int((y1 y2) / 2)# 绘制食指和拇指的连线cv2.line(frame, (x1, y1), (x2, y2), self.current_color, 2)cv2.circle(frame, (x1, y1), 5, self.current_color, -1)cv2.circle(frame, (x2, y2), 5, self.current_color, -1)# 根据绘图模式绘制不同形状if self.current_draw_mode DRAW_MODE_FREE:self.draw_free(hand_idx, x1, y1)elif self.current_draw_mode DRAW_MODE_LINE:self.draw_line(hand_idx, x1, y1)elif self.current_draw_mode DRAW_MODE_CIRCLE:self.draw_circle(hand_idx, x1, y1)else:self.prev_points {}# 根据手势执行操作if gesture GESTURE_CLEAR:self.clear_canvas()elif gesture GESTURE_COLOR_CHANGE:self.change_color()elif gesture GESTURE_UNDO:self.undo()elif gesture GESTURE_REDO:self.redo()elif gesture GESTURE_SAVE:self.save_canvas()elif gesture GESTURE_LOAD:self.load_canvas()elif gesture GESTURE_DRAW_MODE:self.change_draw_mode()return frame用户界面显示
在应用窗口中显示当前颜色、绘图模式和操作指南提升用户体验。
def display_ui(self, frame):# 显示当前颜色cv2.rectangle(frame, (10, 10), (60, 60), self.current_color, -1)cv2.putText(frame, Color, (70, 40),cv2.FONT_HERSHEY_SIMPLEX, 0.7, self.current_color, 2, cv2.LINE_AA)# 显示当前绘图模式cv2.rectangle(frame, (10, 80), (250, 120), (50, 50, 50), -1)cv2.putText(frame, fMode: {self.current_draw_mode}, (20, 110),cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 255, 255), 2, cv2.LINE_AA)# 显示帮助信息cv2.putText(frame, Gestures:, (10, 160),cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 255, 255), 2, cv2.LINE_AA)cv2.putText(frame, OK Gesture: Change Color, (10, 190),cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 255), 1, cv2.LINE_AA)cv2.putText(frame, Fist Gesture: Clear Canvas, (10, 220),cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 255), 1, cv2.LINE_AA)cv2.putText(frame, Index Finger: Undo, (10, 250),cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 255), 1, cv2.LINE_AA)cv2.putText(frame, Middle Finger: Redo, (10, 280),cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 255), 1, cv2.LINE_AA)cv2.putText(frame, Thumb Pinky: Save, (10, 310),cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 255), 1, cv2.LINE_AA)cv2.putText(frame, Index Middle: Load, (10, 340),cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 255), 1, cv2.LINE_AA)cv2.putText(frame, Four Fingers: Change Mode, (10, 370),cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 255), 1, cv2.LINE_AA)主循环
应用的主循环负责不断捕捉摄像头帧处理手势识别和绘图操作并在窗口中显示结果。
def run(self):while True:ret, frame self.cap.read()if not ret:print(Failed to grab frame.)break# 翻转图像水平翻转以便镜像显示frame cv2.flip(frame, 1)# 处理手部检测和绘图processed_frame self.process_frame(frame)# 合并画布和当前帧combined cv2.addWeighted(processed_frame, 0.5, self.canvas, 0.5, 0)# 显示用户界面self.display_ui(combined)# 显示合并后的图像cv2.imshow(Air Drawing - Enhanced, combined)# 按 q 键退出if cv2.waitKey(1) 0xFF ord(q):break# 释放资源self.cap.release()cv2.destroyAllWindows()使用指南
启动应用运行上述代码摄像头窗口将会启动并显示“Air Drawing - Enhanced”界面。绘图 自由绘图默认模式下通过食指在空中移动进行自由绘图。切换绘图模式做出四指伸出手势可以在自由绘图、直线绘图和圆形绘图模式之间切换。颜色选择做出“OK”手势拇指和食指接触绘图颜色将切换到下一个预设颜色并在控制台输出颜色更改信息。撤销和重做 撤销做出“食指伸出”手势撤销上一步绘图操作。重做做出“中指伸出”手势重做上一步被撤销的绘图操作。清除画布做出拳头手势当前画布上的所有内容将被清除。保存与加载 保存画布做出“拇指和小指伸出”手势将当前画布保存到文件。加载画布做出“食指和中指伸出”手势加载之前保存的画布。退出应用按下键盘上的 q 键即可退出应用。
创意扩展与优化
这个项目不仅仅是一个简单的手势识别绘图应用它还可以不断扩展和优化以下是一些建议
多手检测与交互支持同时检测多只手实现更复杂的交互方式例如一只手用于绘图另一只手用于控制工具。更多绘图工具增加更多绘图工具如矩形、椭圆、喷枪效果等丰富用户的绘图体验。界面优化使用图形用户界面库如 Tkinter 或 PyQt来创建更美观的界面包含工具栏、颜色选择器等。手势自定义允许用户自定义手势以执行更多操作如调整画笔大小、切换图层等。性能优化优化图像处理和绘图算法提高应用的响应速度和稳定性。跨平台支持优化代码使其在不同操作系统Windows、macOS、Linux上都能稳定运行。