본문 바로가기

Unreal/Tips

[UE5] 언리얼 엔진과 미디어파이프를 활용한 인터렉티브 컨텐츠 개발하기

728x90
반응형

 

Solution

  • 미디어파이프(Mediapipe)의 경우 c++로 구현할 수 도 있지만, 언리얼 엔진 내부에서 돌리기에는 많이 무거운듯하다. 그렇기 때문에 python으로 돌리고 osc 통신을 통해 결과값을 언리얼 엔진으로 전달하는 형태의 구조로 구성
  • 언리얼 엔진 내부에서 동작하기에 미디어파이프도 C++로 구현되어 있지만, 빌드 체계가 언리얼 엔진과는 달라 통합하려면 상당한 작업이 필요하다고 알게 됨

1. Unreal에서 MediaPipe를 C++로 구현 가능할까?

✔️ 가능은 함(구글이 C++용 MediaPipe 라이브러리 제공)

  • MediaPipe는 원래 C++로 만들어졌습니다.
  • 다만 빌드 체계는 Bazel을 사용하며, Unreal은 CMake/Visual Studio 기반입니다.
  • 두 시스템을 통합하려면 상당한 수작업이 필요합니다.

C++ MediaPipe를 Unreal 플러그인으로 컴파일하기 위해 Bazel 빌드된 .so 또는 .lib 파일을 Unreal로 가져와야 함

 

2. Unreal에서 MediaPipe를 직접 붙일 때의 장단점

장점

항목  설명
엔진 내부에서 직접 실행 OSC 통신 없이 바로 Control Rig, Niagara 등에 연결 가능
모바일/배포 최적화 안드로이드/iOS 앱 안에 통합 가능
지연 최소화 데이터 송수신 지연 없이 곧바로 처리 가능

단점

항목 설명
빌드 통합 난이도 극단적 MediaPipe는 Bazel 빌드를 요구하고, Unreal은 CMake/VS 기반. 두 환경 충돌
구글의 Graph 기반 처리 방식 Unreal의 타임라인/프레임 기반 로직과 직접 연동 어려움
GPU 가속 구성 복잡 OpenGL, Vulkan 등 백엔드가 충돌 가능 (특히 DX 기반 Unreal과 충돌 여지 있음)
디버깅/패키징 어려움 Unreal 프로젝트 내에서 직접 트래킹 문제 발생 시 원인 추적이 어려움

 

  • 기본 미디어 파이프 종류

미디어 파이프 종류 (1/3)
미디어 파이프 종류 (2/3)
미디어 파이프 종류 (3/3)

 

  • Hand Tracking

HandTrakcing Index

 

Install Python

 

Visual Studio Code - Code Editing. Redefined

Visual Studio Code redefines AI-powered coding with GitHub Copilot for building and debugging modern web and cloud applications. Visual Studio Code is free and available on your favorite platform - Linux, macOS, and Windows.

code.visualstudio.com

 

 

Download Python

The official home of the Python Programming Language

www.python.org

 

  • 필요 모듈 임포트
pip install opencv-python mediapipe python-osc
  • opencv-python : 이미지 및 영상 처리를 위한 OpenCV 라이브러리
  • mediapipe : 구글에서 제공하는 실시간 포즈, 손, 얼굴 추적 등을 지원하는 라이브러리
  • python-osc : Python에서 Open Sound Control (OSC) 프로토콜을 사용하기 위한 라이브러리

 

주요 코드

import cv2
import mediapipe as mp
from pythonosc import udp_client

# OSC 설정
OSC_IP = "172.30.1.21"
OSC_PORT = 8000
client = udp_client.SimpleUDPClient(OSC_IP, OSC_PORT)

# MediaPipe 설정
mp_hands = mp.solutions.hands
mp_drawing = mp.solutions.drawing_utils
hands = mp_hands.Hands(
    static_image_mode=False,
    max_num_hands=1,
    model_complexity=1,
    min_detection_confidence=0.5,
    min_tracking_confidence=0.5
)

# 웹캠 시작
cap = cv2.VideoCapture(0)

while cap.isOpened():
    ret, frame = cap.read()
    if not ret:
        break

    frame = cv2.flip(frame, 1)
    image_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

    result = hands.process(image_rgb)

    if result.multi_hand_landmarks:
        for hand_landmarks in result.multi_hand_landmarks:
            # 중심을 계산할 landmark 인덱스
            center_indices = [0, 5, 9, 13, 17]  # 손목 + 손가락 시작점

            avg_x = sum([hand_landmarks.landmark[i].x for i in center_indices]) / len(center_indices)
            avg_y = sum([hand_landmarks.landmark[i].y for i in center_indices]) / len(center_indices)

            # OSC 전송
            client.send_message("/hand/center", [avg_x, avg_y])

            # 시각화
            h, w, _ = frame.shape
            cx, cy = int(avg_x * w), int(avg_y * h)
            cv2.circle(frame, (cx, cy), 10, (0, 255, 0), -1)
            mp_drawing.draw_landmarks(frame, hand_landmarks, mp_hands.HAND_CONNECTIONS)
    else:
        # 손이 감지되지 않을 때 텍스트 표시
        cv2.putText(frame, "No hand detected", (30, 50),
                    cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 0, 255), 2)
        
        client.send_message(f"/hand/exit", 0)

    cv2.imshow("Hand Center Tracking", frame)
    if cv2.waitKey(1) & 0xFF == 27:
        break

cap.release()
cv2.destroyAllWindows()

 

 

728x90