Maison >développement back-end >Tutoriel Python >Projet Python pour débutant : créer une application de dessin en réalité augmentée à l'aide d'OpenCV et Mediapipe
Dans ce projet Python, nous allons créer une simple application de dessin AR. Grâce à votre webcam et aux gestes de vos mains, vous pouvez dessiner virtuellement sur l'écran, personnaliser votre pinceau et même enregistrer vos créations !
Pour commencer, créez un nouveau dossier et initialisez un nouvel environnement virtuel en utilisant :
python -m venv venv
./venv/Scripts/activate
Ensuite, installez les bibliothèques requises à l'aide de pip ou du programme d'installation de votre choix :
pip install mediapipe
pip install opencv-python
Vous pourriez avoir des difficultés à installer Mediapipe avec la dernière version sur Python. Au moment où j'écris ce blog, j'utilise python 3.11.2. Assurez-vous d'utiliser la version compatible sur python.
La première étape consiste à configurer votre webcam et à afficher le flux vidéo. Nous utiliserons VideoCapture d'OpenCV pour accéder à la caméra et afficher les images en continu.
import cv2 # The argument '0' specifies the default camera (usually the built-in webcam). cap = cv2.VideoCapture(0) # Start an infinite loop to continuously capture video frames from the webcam while True: # Read a single frame from the webcam # `ret` is a boolean indicating success; `frame` is the captured frame. ret, frame = cap.read() # Check if the frame was successfully captured # If not, break the loop and stop the video capture process. if not ret: break # Flip the frame horizontally (like a mirror image) frame = cv2.flip(frame, 1) # Display the current frame in a window named 'Webcam Feed' cv2.imshow('Webcam Feed', frame) # Wait for a key press for 1 millisecond # If the 'q' key is pressed, break the loop to stop the video feed. if cv2.waitKey(1) & 0xFF == ord('q'): break # Release the webcam resource to make it available for other programs cap.release() # Close all OpenCV-created windows cv2.destroyAllWindows()
Le saviez-vous ?
Lors de l'utilisation de cv2.waitKey() dans OpenCV, le code clé renvoyé peut inclure des bits supplémentaires en fonction de la plate-forme. Pour vous assurer de détecter correctement les pressions sur les touches, vous pouvez masquer le résultat avec 0xFF pour isoler les 8 bits inférieurs (la valeur ASCII réelle). Sans cela, vos comparaisons clés pourraient échouer sur certains systèmes. Utilisez donc toujours & 0xFF pour un comportement cohérent !
Grâce à la solution Hands de Mediapipe, nous détecterons la main et extrairons la position des repères clés comme l'index et le majeur.
import cv2 import mediapipe as mp # Initialize the MediaPipe Hands module mp_hands = mp.solutions.hands # Load the hand-tracking solution from MediaPipe hands = mp_hands.Hands( min_detection_confidence=0.9, min_tracking_confidence=0.9 ) cap = cv2.VideoCapture(0) while True: ret, frame = cap.read() if not ret: break # Flip the frame horizontally to create a mirror effect frame = cv2.flip(frame, 1) # Convert the frame from BGR (OpenCV default) to RGB (MediaPipe requirement) frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # Process the RGB frame to detect and track hands result = hands.process(frame_rgb) # If hands are detected in the frame if result.multi_hand_landmarks: # Iterate through all detected hands for hand_landmarks in result.multi_hand_landmarks: # Get the frame dimensions (height and width) h, w, _ = frame.shape # Calculate the pixel coordinates of the tip of the index finger cx, cy = int(hand_landmarks.landmark[mp_hands.HandLandmark.INDEX_FINGER_TIP].x * w), \ int(hand_landmarks.landmark[mp_hands.HandLandmark.INDEX_FINGER_TIP].y * h) # Calculate the pixel coordinates of the tip of the middle finger mx, my = int(hand_landmarks.landmark[mp_hands.HandLandmark.MIDDLE_FINGER_TIP].x * w), \ int(hand_landmarks.landmark[mp_hands.HandLandmark.MIDDLE_FINGER_TIP].y * h) # Draw a circle at the index finger tip on the original frame cv2.circle(frame, (cx, cy), 10, (0, 255, 0), -1) # Green circle with radius 10 # Display the processed frame in a window named 'Webcam Feed' cv2.imshow('Webcam Feed', frame) if cv2.waitKey(1) & 0xFF == ord('q'): break # Exit the loop if 'q' is pressed # Release the webcam resources for other programs cap.release() cv2.destroyAllWindows()
Nous suivrons l'index et autoriserons le dessin uniquement lorsque l'index et le majeur sont séparés par une distance seuil.
Nous maintiendrons une liste de coordonnées des index à dessiner sur le cadre d'origine et chaque fois que le majeur sera suffisamment proche, nous ajouterons Aucun à ce tableau de coordonnées indiquant une casse.
import cv2 import mediapipe as mp import math # Initialize the MediaPipe Hands module mp_hands = mp.solutions.hands hands = mp_hands.Hands( min_detection_confidence=0.9, min_tracking_confidence=0.9 ) # Variables to store drawing points and reset state draw_points = [] # A list to store points where lines should be drawn reset_drawing = False # Flag to indicate when the drawing should reset # Brush settings brush_color = (0, 0, 255) brush_size = 5 cap = cv2.VideoCapture(0) while True: ret, frame = cap.read() if not ret: break frame = cv2.flip(frame, 1) frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) result = hands.process(frame_rgb) # If hands are detected if result.multi_hand_landmarks: for hand_landmarks in result.multi_hand_landmarks: h, w, _ = frame.shape # Get the frame dimensions (height and width) # Get the coordinates of the index finger tip cx, cy = int(hand_landmarks.landmark[mp_hands.HandLandmark.INDEX_FINGER_TIP].x * w), \ int(hand_landmarks.landmark[mp_hands.HandLandmark.INDEX_FINGER_TIP].y * h) # Get the coordinates of the middle finger tip mx, my = int(hand_landmarks.landmark[mp_hands.HandLandmark.MIDDLE_FINGER_TIP].x * w), \ int(hand_landmarks.landmark[mp_hands.HandLandmark.MIDDLE_FINGER_TIP].y * h) # Calculate the distance between the index and middle finger tips distance = math.sqrt((mx - cx) ** 2 + (my - cy) ** 2) # Threshold distance to determine if the fingers are close (used to reset drawing) threshold = 40 # If the fingers are far apart if distance > threshold: if reset_drawing: # Check if the drawing was previously reset draw_points.append(None) # None means no line reset_drawing = False draw_points.append((cx, cy)) # Add the current point to the list for drawing else: # If the fingers are close together set the flag to reset drawing reset_drawing = True # # Draw the lines between points in the `draw_points` list for i in range(1, len(draw_points)): if draw_points[i - 1] and draw_points[i]: # Only draw if both points are valid cv2.line(frame, draw_points[i - 1], draw_points[i], brush_color, brush_size) cv2.imshow('Webcam Feed', frame) if cv2.waitKey(1) & 0xFF == ord('q'): break # Release the webcam and close all OpenCV windows 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!