はじめに
UnityからPythonファイルを実行する方法と、少し滑らかに動かす仕組みを作ったので紹介します☺️
顔や手が認識できなくなったとき、オブジェクトが残っていると違和感があるので、消すようにもしました。
UnityからPythonを実行することに伴い、UDP通信は双方向にしています。
Python
前回からの変更点は以下です。
- cv2での画面表示を削除
- UDP受信処理を追加
ソースコード
import time
import cv2
import mediapipe as mp
import numpy as np
from socket import socket, AF_INET, SOCK_DGRAM
import json
import queue
import threading
HOST = ''
PORT_UNITY = 65500
PORT_MEDIAPIPE = 65501
ADDRESS = "127.0.0.1"
face_model_path = './face_landmarker.task'
hands_model_path = './hand_landmarker.task'
# ... (ランドマーク取得・UDP送受信処理)
Unity
スクリプト
MediaPipe管理
using System.Diagnostics;
using UnityEngine;
public class MediaPipeManager : MonoBehaviour
{
private Process process;
[SerializeField] string pythonPath;
[SerializeField] string scriptPath;
void Start()
{
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = pythonPath;
psi.Arguments = scriptPath;
psi.UseShellExecute = false;
psi.RedirectStandardOutput = true;
process = Process.Start(psi);
}
private void OnApplicationQuit()
{
// UDP送信でPython停止を通知
}
}
UDP管理
using System.Net;
using System.Net.Sockets;
using System.Threading;
using UnityEngine;
using PartsData_face_ns;
using PartsData_righthand_ns;
using PartsData_lefthand_ns;
public class UDPManager : MonoBehaviour
{
private UdpClient udpClient;
private Thread receiveThread;
private const int PORT = 65500;
void Start()
{
udpClient = new UdpClient(PORT);
receiveThread = new Thread(ReceiveData);
receiveThread.IsBackground = true;
receiveThread.Start();
}
private void ReceiveData()
{
while (true)
{
IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, 0);
byte[] data = udpClient.Receive(ref endPoint);
string json = System.Text.Encoding.UTF8.GetString(data);
// partsフィールドでルーティング
}
}
}
エディタ設定
動作確認
顔と手のトラッキングがUnity上で動作するようになりました😁
課題:処理負荷が高い
MediaPipeの処理とUnityの描画が同じPC上で動作するため、処理負荷が高くなりやすいです。
フレームレートを下げるなどの対策が必要になる場合があります。
さいごに
それでは、今回はここまで。ありがとうございました😊