阅读量:0
目录
1 流程
手指拖拽屏幕上的方块儿步骤
- OpenCv获取视频流
- 获取手指关节关键点坐标
- 判断手指是否在方块上
- 如果在方块上,方块跟着手指移动
2 代码
import cv2 import numpy as np import math import mediapipe as mp ## 检测手掌参数设置 mp_drawing = mp.solutions.drawing_utils mp_drawing_styles = mp.solutions.drawing_styles mp_hands = mp.solutions.hands # 获取手的21个关节 hands = mp_hands.Hands( model_complexity=0, min_detection_confidence=0.5, min_tracking_confidence=0.5) # 获取摄像头的视频流 cap = cv2.VideoCapture(0) # 获取画面宽度,高度 width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) # 方块的相关参数 ## box左上角坐标、宽度、颜色 box_x = 100 box_y = 100 box_width = 100 box_high = 120 box_color = (255, 0, 255) ## 阈值,当食指和中指指尖距离大于阈值时,停止移动box threth = 80 ## 食指指尖与box左上角坐标的距离 d1 = 0 d2 = 0 ## 食指指尖是否在方块上 on_box = False while True: # 1. 读取每一帧 ret, frame = cap.read() # 对图像进行处理 # 镜像处理,对y轴进行翻转 frame = cv2.flip(frame, 1) # mediapipe处理RGB通道的图像 frame.flags.writeable = False frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) ## 2.手掌检测RGB图像 results = hands.process(frame) frame.flags.writeable = True frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR) # 判断是否检测到手掌 if results.multi_hand_landmarks: # 遍历每一只手掌 for hand_landmarks in results.multi_hand_landmarks: # 绘制手掌的21个关键点 mp_drawing.draw_landmarks( frame, hand_landmarks, mp_hands.HAND_CONNECTIONS, mp_drawing_styles.get_default_hand_landmarks_style(), mp_drawing_styles.get_default_hand_connections_style() ) # 保存手掌的21个x,y的坐标 x_list = [] y_list = [] for landmark in hand_landmarks.landmark: # 会循环21次把手的关节弄好 # 添加x坐标 x_list.append(landmark.x) # append表示添加x坐标 # 添加y坐标 y_list.append(landmark.y) # 获取食指指尖xy坐标 index_finger_x = int(x_list[8] * width) index_finger_y = int(y_list[8] * height) # 获取中指指尖,用于退出方块 middle_finger_x = int(x_list[12] * width) middle_finger_y = int(y_list[12] * height) # 计算食指指尖和中指指尖的欧式距离 finger_len = math.hypot((index_finger_x - middle_finger_x), (index_finger_y - middle_finger_y)) if finger_len < threth: # 3. 判断指尖是否在方块上面 if (box_x < index_finger_x < box_x + box_width and box_y < index_finger_y < box_y + box_high): if on_box == False: ## 如果食指在box内移动,则保持d1、d2不更新,即box与食指的相对位置不变 d1 = abs(index_finger_x - box_x) d2 = abs(index_finger_y - box_y) on_box = True ## 如果食指在box上,则变换box为水红色 box_color = (255, 0, 255) else: on_box = False ## 如果食指不在box上,则变换box为蓝颜 box_color = (255, 0, 0) if on_box: # 如果手指在方块上面 box_x = index_finger_x - d1 # 根据算法 box_y = index_finger_y - d2 # 4. 画出box cv2.rectangle(frame, (box_x, box_y), (box_x + box_width, box_y + box_high), box_color, -1) frame = cv2.addWeighted(frame.copy(), 0.5, frame, 0.5, 0) # 做一个半透明 # 显示图像 cv2.imshow('Box drag', frame) # 退出条件 if cv2.waitKey(10) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows()