> 백엔드 개발 > 파이썬 튜토리얼 > 초보자 Python 프로젝트: OpenCV 및 Mediapipe를 사용하여 증강 현실 그리기 앱 구축

초보자 Python 프로젝트: OpenCV 및 Mediapipe를 사용하여 증강 현실 그리기 앱 구축

Linda Hamilton
풀어 주다: 2025-01-02 14:47:38
원래의
737명이 탐색했습니다.

Beginner Python Project: Build an Augmented Reality Drawing App Using OpenCV and Mediapipe

이 Python 프로젝트에서는 간단한 AR 그리기 앱을 만들어 보겠습니다. 웹캠과 손 제스처를 사용하여 화면에 가상으로 그림을 그리고 브러시를 사용자 정의하고 창작물을 저장할 수도 있습니다!

설정

시작하려면 다음을 사용하여 새 폴더를 만들고 새 가상 환경을 초기화하세요.

python -m venv venv
로그인 후 복사
./venv/Scripts/activate
로그인 후 복사

다음으로 원하는 pip 또는 설치 프로그램을 사용하여 필수 라이브러리를 설치합니다.

pip install mediapipe
로그인 후 복사
pip install opencv-python
로그인 후 복사

참고

Python에 최신 버전의 mediapipe를 설치하는 데 문제가 있을 수 있습니다. 나는 이 블로그를 작성하면서 Python 3.11.2를 사용하고 있습니다. 반드시 Python에서 호환되는 버전을 사용하세요.

1단계: 웹캠 피드 캡처

첫 번째 단계는 웹캠을 설정하고 비디오 피드를 표시하는 것입니다. OpenCV의 VideoCapture를 사용하여 카메라에 액세스하여 프레임을 지속적으로 표시해 보겠습니다.

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

로그인 후 복사

아시나요?

OpenCV에서 cv2.waitKey()를 사용할 때 반환된 키 코드에는 플랫폼에 따라 추가 비트가 포함될 수 있습니다. 키 누름을 올바르게 감지하려면 결과를 0xFF로 마스크하여 하위 8비트(실제 ASCII 값)를 격리할 수 있습니다. 이것이 없으면 일부 시스템에서 주요 비교가 실패할 수 있으므로 일관된 동작을 위해 항상 & 0xFF를 사용하십시오!

2단계: 손 감지 통합

미디어파이프의 Hands 솔루션을 사용하여 손을 감지하고 검지, 중지 등 주요 랜드마크의 위치를 ​​추출해 보겠습니다.

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

로그인 후 복사

3단계: 손가락 위치 추적 및 그리기

검지 손가락을 추적하여 검지와 중지가 임계 거리만큼 떨어져 있어야만 그리기를 허용합니다.

원래 프레임에 그릴 검지의 좌표 목록을 유지하고 가운데 손가락이 충분히 가까울 때마다 이 좌표 배열에 None을 추가하여 파손을 나타냅니다.

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

로그인 후 복사

4단계: 개선

  • 브러시 크기와 색상을 전환하려면 OpenCV 직사각형() 및 putText() 버튼을 사용하세요.
  • 프레임 저장 옵션을 추가하세요.
  • 지우개 도구를 추가하고 새 좌표를 사용하여 draw_points 배열을 수정하세요.

위 내용은 초보자 Python 프로젝트: OpenCV 및 Mediapipe를 사용하여 증강 현실 그리기 앱 구축의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:dev.to
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿