Unity は WebCamTexture でカメラ画像テクスチャを管理します。
OpenCV は Mat (行列) でカメラ画像情報を管理します。
目標は Unity の WebCamTexture を Mat に変換して、OpenCV の機能を存分に活用し
たとえば次のような MarkerlessAR Example の実行を行ってみたいと思います。
code/Chapter3_MarkerlessAR at master · MasteringOpenCV/code · GitHub
Unity でデバイスカメラから画像情報を毎フレーム取得する方法は1年前に記事で書いたことありました。
simplestar-tech.hatenablog.com
こちらの記事の
private void PlayDeviceCamera()
関数を参考にすると、画面をタップまたはスペースキーを押すたびにカメラを切り替えて ComputeShader による画像処理が試せます。
このカメラの使い方は複数のコンポーネントから共通して呼び出せた方がうれしいので、WebCamTexture を扱うコンポーネントを以下のように作り直してみました。
using System.Collections; using UnityEngine; using UnityEngine.Events; public class WebCamHelper : MonoBehaviour { public string requestedDeviceName; public int requestedWidth = 640; public int requestedHeight = 480; public int requestedFPS = 60; public WebCamTexture webCamTexture { get; private set; } public UnityEvent onInitialized = new UnityEvent(); public UnityEvent onDisposed = new UnityEvent(); public UnityEvent onErrorOccurred; public void InitializeCamera() { StartCoroutine(CoInitializeCamera()); } IEnumerator CoInitializeCamera() { if (hasInitDone) _Dispose(); isInitWaiting = true; if (!System.String.IsNullOrEmpty(requestedDeviceName)) { webCamTexture = new WebCamTexture(requestedDeviceName, requestedWidth, requestedHeight, requestedFPS); } else { // Checks how many and which cameras are available on the device for (int cameraIndex = 0; cameraIndex < WebCamTexture.devices.Length; cameraIndex++) { if (WebCamTexture.devices[cameraIndex].isFrontFacing == requestedIsFrontFacing) { webCamDevice = WebCamTexture.devices[cameraIndex]; webCamTexture = new WebCamTexture(webCamDevice.name, requestedWidth, requestedHeight, requestedFPS); break; } } } if (webCamTexture == null) { if (WebCamTexture.devices.Length > 0) { webCamDevice = WebCamTexture.devices[0]; webCamTexture = new WebCamTexture(webCamDevice.name, requestedWidth, requestedHeight, requestedFPS); } else { isInitWaiting = false; if (onErrorOccurred != null) onErrorOccurred.Invoke(); yield break; } } // Starts the camera webCamTexture.Play(); int initFrameCount = 0; bool isTimeout = false; while (true) { if (initFrameCount > timeoutFrameCount) { isTimeout = true; break; } else if (webCamTexture.didUpdateThisFrame) { Debug.Log("name " + webCamTexture.name + " width " + webCamTexture.width + " height " + webCamTexture.height + " fps " + webCamTexture.requestedFPS); Debug.Log("videoRotationAngle " + webCamTexture.videoRotationAngle + " videoVerticallyMirrored " + webCamTexture.videoVerticallyMirrored + " isFrongFacing " + webCamDevice.isFrontFacing); isInitWaiting = false; hasInitDone = true; if (onInitialized != null) onInitialized.Invoke(); break; } else { initFrameCount++; yield return 0; } } if (isTimeout) { webCamTexture.Stop(); webCamTexture = null; isInitWaiting = false; if (onErrorOccurred != null) onErrorOccurred.Invoke(); } if (null != onInitialized) { onInitialized.Invoke(); } yield return 0; } /// <summary> /// To release the resources for the initialized method. /// </summary> protected virtual void _Dispose() { isInitWaiting = false; hasInitDone = false; if (webCamTexture != null) { webCamTexture.Stop(); webCamTexture = null; } if (onDisposed != null) onDisposed.Invoke(); } bool requestedIsFrontFacing = false; bool hasInitDone = false; bool isInitWaiting = false; int timeoutFrameCount = 300; WebCamDevice webCamDevice; }
この WebCamHelper クラスの使い方は以下の通りですね。
Update の中で画像処理用の OpenCV につなげていきます。
このあたりの続きは次の記事で
using System.Collections; using System.Collections.Generic; using UnityEngine; [RequireComponent(typeof(WebCamHelper))] public class UnityDeOpenCV : MonoBehaviour { public GameObject quad; void Start () { webCamHelper = GetComponent<WebCamHelper>(); webCamHelper.onInitialized.AddListener(OnInitalizedCamera); webCamHelper.InitializeCamera(); } void Update () { if (webCamHelper.webCamTexture && webCamHelper.webCamTexture.didUpdateThisFrame) { } } void OnInitalizedCamera() { int width = webCamHelper.webCamTexture.width; int height = webCamHelper.webCamTexture.height; if (quad) { quad.GetComponent<Renderer>().material.mainTexture = webCamHelper.webCamTexture; } } WebCamHelper webCamHelper; }