Version: 2019.2
HoloLens のウェブカメラ
HoloLens VideoCapture

HoloLens の PhotoCapture

HoloLens のウェブカメラで写真を撮るには PhotoCapture API を使用します。PhotoCapture API を使用するには ウェブカメラマイク の機能を有効にする必要があります。以下の例では、PhotoCapture 機能を使って写真を撮る方法と、それを Unity の ゲームオブジェクト に表示する方法を紹介します。

using UnityEngine;
using System.Collections;
using System.Linq;
using UnityEngine.XR.WSA.WebCam;

public class PhotoCaptureExample : MonoBehaviour {
    PhotoCapture photoCaptureObject = null;
    Texture2D targetTexture = null;

    // これを使って初期化します
    void Start() {
        Resolution cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();
        targetTexture = new Texture2D(cameraResolution.width, cameraResolution.height);

        // PhotoCapture オブジェクトを作成します
        PhotoCapture.CreateAsync(false, delegate (PhotoCapture captureObject) {
            photoCaptureObject = captureObject;
            CameraParameters cameraParameters = new CameraParameters();
            cameraParameters.hologramOpacity = 0.0f;
            cameraParameters.cameraResolutionWidth = cameraResolution.width;
            cameraParameters.cameraResolutionHeight = cameraResolution.height;
            cameraParameters.pixelFormat = CapturePixelFormat.BGRA32;

            // カメラをアクティベートします
            photoCaptureObject.StartPhotoModeAsync(cameraParameters, delegate (PhotoCapture.PhotoCaptureResult result) {
                // 写真を撮ります
                photoCaptureObject.TakePhotoAsync(OnCapturedPhotoToMemory);
            });
        });
    }

    void OnCapturedPhotoToMemory(PhotoCapture.PhotoCaptureResult result, PhotoCaptureFrame photoCaptureFrame) {
        // ターゲットテクスチャに RAW 画像データをコピーします
        photoCaptureFrame.UploadImageDataToTexture(targetTexture);

        // テクスチャが適用されるゲームオブジェクトを作成
        GameObject quad = GameObject.CreatePrimitive(PrimitiveType.Quad);
        Renderer quadRenderer = quad.GetComponent<Renderer>() as Renderer;
        quadRenderer.material = new Material(Shader.Find("Custom/Unlit/UnlitTexture"));

        quad.transform.parent = this.transform;
        quad.transform.localPosition = new Vector3(0.0f, 0.0f, 3.0f);

        quadRenderer.material.SetTexture("_MainTex", targetTexture);

        // カメラを非アクティブにします
        photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
    }

    void OnStoppedPhotoMode(PhotoCapture.PhotoCaptureResult result) {
        // photo capture のリソースをシャットダウンします
        photoCaptureObject.Dispose();
        photoCaptureObject = null;
    }
}

写真をメモリにキャプチャ

画像をメモリにキャプチャすると、PhotoCaptureFrame が返されます。PhotoCaptureFrame には、ネイティブの画像データと、画像の取得場所を示す空間の行列の両方が含まれています。

画像をメモリにキャプチャすると、キャプチャされた画像をシェーダーで参照したり、ゲームオブジェクトに適用することができます。PhotoCaptureFrame から画像データを抽出する方法は 3 つあります。

  1. 画像データを Texture2D としてキャプチャします。これは、画像データを抽出する最も一般的な方法です。なぜなら、Unity のほとんどのコンポーネントには Texture2D の画像データにアクセスする方法が備わっているからです。画像をメモリに取り込んだら、画像データを Texture2D にアップロードする必要があります。画像データを Texture2D にアップロードすると、その画像データをマテリアル、スクリプト、またはプロジェクトの他の関連要素で参照することができます。Unity スクリプトリファレンスには、写真をメモリにキャプチャしてから Texture2D にアップロードする方法の例があります。Texture2D に写真を取り込む方法については、WebCam.PhotoCapture.TakePhotoAsync を参照してください。アップロードのコマンドを使用して画像データを Texture2D にアップロードすることは、Unityで画像データの使用する最も簡単な方法です。アップロード操作はメインスレッドで行われます。この操作はリソースに負荷がかかり、プロジェクトのパフォーマンスに影響する可能性があります。

  2. ネイティブの画像データを WinRT IMFMediaBuffer としてキャプチャします。 詳細は、Microsoft のドキュメント IMFMediaBuffer を参照してください。バイトリストを PhotoFrame.CopyRawImageDataIntoBuffer 関数に渡して、ネイティブの画像データのコピーを作成します。コピー操作はメインスレッドで行われることに注意してください。この操作はリソースに負荷がかかり、プロジェクトのパフォーマンスに影響する可能性があります。

  3. 独自のプラグインを作成したり、画像データを別のスレッドで処理したりする場合は、PhotoFrame.GetUnsafePointerToBuffer 関数を使用してネイティブの画像データへのポインターを取得します。返されるポインターは、 IMFMediaBuffer コンポーネントオブジェクトモデル (COM) へのポインターです。詳細は、Microsoft のドキュメントの IMFMediaBufferComponent Object Models を参照してください。この関数を呼び出すと、COM オブジェクトへの参照が追加されます。リソースが不要になったときに、参照を解放する必要があります。

HoloLens のウェブカメラ
HoloLens VideoCapture