Maison >développement back-end >Tutoriel Python >Comment utiliser Python+OpenCV pour obtenir l'effet de faire glisser des carrés virtuels

Comment utiliser Python+OpenCV pour obtenir l'effet de faire glisser des carrés virtuels

WBOY
WBOYavant
2023-05-15 19:22:121022parcourir

1. Effet de projet

2. Processus de base

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.

3. Processus de code

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.

1. Lisez la vidéo de la caméra et dessinez un rectangle

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.

2. Importez Mediapipe pour traiter les coordonnées des doigts

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)

Comment utiliser Python+OpenCV pour obtenir leffet de faire glisser des carrés virtuels

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()

3. Calcul de la position

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.

Comment utiliser Python+OpenCV pour obtenir leffet de faire glisser des carrés virtuels

Code complet

Comment utiliser Python+OpenCV pour obtenir leffet de faire glisser des carrés virtuels

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(&#39;frame&#39;,frame)
    
    # 退出条件
    if cv2.waitKey(1) & 0xFF == ord(&#39;q&#39;):
        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!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer