Maison >développement back-end >Tutoriel Python >Comment utiliser Python+OpenCV pour obtenir l'effet de faire glisser des carrés virtuels
1. OpenCV lit le flux vidéo et dessine un rectangle sur chaque image de l'image.
2. Utilisez Mediapipe pour obtenir les coordonnées des points clés du doigt.
3. En fonction de la position des coordonnées du doigt et de la position des coordonnées du rectangle, déterminez si la pointe du doigt est sur le rectangle. Si c'est le cas, le rectangle suivra le mouvement du doigt.
Préparation de l'environnement :
python : 3.8.8
opencv : 4.2.0.32
mediapipe : 0.8.10.1
Remarque :
1. élevé ou trop faible Par exemple, si la caméra ne peut pas être allumée ou plante, la version de python affecte la version sélectionnable d'opencv.
2. OpenCV ne pourra peut-être pas être utilisé normalement après l'installation de pip mediapipe. Désinstallez-le et téléchargez-le à nouveau.
import cv2 import time import numpy as np # 调用摄像头 0 默认摄像头 cap = cv2.VideoCapture(0) # 初始方块数据 x = 100 y = 100 w = 100 h = 100 # 读取一帧帧照片 while True: # 返回frame图片 rec,frame = cap.read() # 镜像 frame = cv2.flip(frame,1) # 画矩形 cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 255), -1) # 显示画面 cv2.imshow('frame',frame) # 退出条件 if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows()
C'est une étape très basique. Maintenant, nous exécutons ce code et la caméra est allumée. Nous serons surpris de voir notre beau visage et un 100 en haut à gauche. coin. *100 rectangle violet.
pip install mediapipe
Certains problèmes peuvent survenir à ce moment-là, comme openCV qui devient soudainement inutilisable, désinstallez-le et téléchargez-le à nouveau.
détails de mediapipe : Hands - mediapipe (google.github.io)
En termes simples, il nous renverra les coordonnées de 21 points clés du doigt, c'est-à-dire son rapport de position dans l'écran vidéo (0~1 ), on le multiplie par la largeur et la hauteur de l'écran correspondant pour obtenir les coordonnées correspondant au doigt.
Cette fois, j'ai utilisé le bout de mon index et de mon majeur, qui sont les numéros 8 et 12.
2.1 Configurez quelques informations de base
import cv2 import time import numpy as np import mediapipe as mp mp_drawing = mp.solutions.drawing_utils mp_drawing_styles = mp.solutions.drawing_styles mp_hands = mp.solutions.hands hands = mp_hands.Hands( static_image_mode=True, max_num_hands=2, min_detection_confidence=0.5)
2.2 Lors du traitement de chaque image d'image, ajoutez
frame.flags.writeable = False frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # 返回结果 results = hands.process(frame) frame.flags.writeable = True frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
Lorsque nous lisons chaque image d'image dans le flux vidéo, convertissez-la de BGR en RVB et fournissez-la au mediapipe L'objet mains généré est lu et il renverra les informations des points clés des doigts dans cette image. Il suffit de continuer à le dessiner sur chaque image de l'image.
# 如果结果不为空 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_styles.get_default_hand_landmarks_style(), mp_drawing_styles.get_default_hand_connections_style())
2.3 Le code complet de cette étape
import cv2 import time import numpy as np import mediapipe as mp mp_drawing = mp.solutions.drawing_utils mp_drawing_styles = mp.solutions.drawing_styles mp_hands = mp.solutions.hands hands = mp_hands.Hands( static_image_mode=True, max_num_hands=2, min_detection_confidence=0.5) # 调用摄像头 0 默认摄像头 cap = cv2.VideoCapture(0) # 方块初始数组 x = 100 y = 100 w = 100 h = 100 # 读取一帧帧照片 while True: # 返回frame图片 rec,frame = cap.read() # 镜像 frame = cv2.flip(frame,1) frame.flags.writeable = False frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # 返回结果 results = hands.process(frame) frame.flags.writeable = True frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR) # 如果结果不为空 if results.multi_hand_landmarks: # 遍历双手(根据读取顺序,一只只手遍历、画画) # results.multi_hand_landmarks n双手 # hand_landmarks 每只手上21个点信息 for hand_landmarks in results.multi_hand_landmarks: 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()) # 画矩形 cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 255), -1) # 显示画面 cv2.imshow('frame',frame) # 退出条件 if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows()
Notre expérience nécessite de faire glisser la boîte, et il y aura certainement des moments où elle ne sera pas glissée, donc autant obtenir l'index ( 8) et le majeur (12) selon l'étape précédente) position du bout du doigt si les deux sont proches, nous modifierons les coordonnées du bloc en fonction de la position du doigt lorsqu'il coïncide avec le bloc.
import cv2 import time import math import numpy as np import mediapipe as mp # mediapipe配置 mp_drawing = mp.solutions.drawing_utils mp_drawing_styles = mp.solutions.drawing_styles mp_hands = mp.solutions.hands hands = mp_hands.Hands( static_image_mode=True, max_num_hands=2, min_detection_confidence=0.5) # 调用摄像头 0 默认摄像头 cap = cv2.VideoCapture(0) # cv2.namedWindow("frame", 0) # cv2.resizeWindow("frame", 960, 640) # 获取画面宽度、高度 width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) # 方块初始数组 x = 100 y = 100 w = 100 h = 100 L1 = 0 L2 = 0 on_square = False square_color = (0, 255, 0) # 读取一帧帧照片 while True: # 返回frame图片 rec,frame = cap.read() # 镜像 frame = cv2.flip(frame,1) frame.flags.writeable = False frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # 返回结果 results = hands.process(frame) frame.flags.writeable = True frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR) # 如果结果不为空 if results.multi_hand_landmarks: # 遍历双手(根据读取顺序,一只只手遍历、画画) # results.multi_hand_landmarks n双手 # hand_landmarks 每只手上21个点信息 for hand_landmarks in results.multi_hand_landmarks: 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()) # 记录手指每个点的x y 坐标 x_list = [] y_list = [] for landmark in hand_landmarks.landmark: x_list.append(landmark.x) y_list.append(landmark.y) # 获取食指指尖 index_finger_x, index_finger_y = int(x_list[8] * width),int(y_list[8] * height) # 获取中指 middle_finger_x,middle_finger_y = int(x_list[12] * width), int(y_list[12] * height) # 计算两指尖距离 finger_distance = math.hypot((middle_finger_x - index_finger_x), (middle_finger_y - index_finger_y)) # 如果双指合并(两之间距离近) if finger_distance < 60: # X坐标范围 Y坐标范围 if (index_finger_x > x and index_finger_x < (x + w)) and ( index_finger_y > y and index_finger_y < (y + h)): if on_square == False: L1 = index_finger_x - x L2 = index_finger_y - y square_color = (255, 0, 255) on_square = True else: # 双指不合并/分开 on_square = False square_color = (0, 255, 0) # 更新坐标 if on_square: x = index_finger_x - L1 y = index_finger_y - L2 # 图像融合 使方块不遮挡视频图片 overlay = frame.copy() cv2.rectangle(frame, (x, y), (x + w, y + h), square_color, -1) frame = cv2.addWeighted(overlay, 0.5, frame, 1 - 0.5, 0) # 显示画面 cv2.imshow('frame',frame) # 退出条件 if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows()
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!