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 つあります。
画像データを Texture2D としてキャプチャします。これは、画像データを抽出する最も一般的な方法です。なぜなら、Unity のほとんどのコンポーネントには Texture2D の画像データにアクセスする方法が備わっているからです。画像をメモリに取り込んだら、画像データを Texture2D にアップロードする必要があります。画像データを Texture2D にアップロードすると、その画像データをマテリアル、スクリプト、またはプロジェクトの他の関連要素で参照することができます。Unity スクリプトリファレンスには、写真をメモリにキャプチャしてから Texture2D にアップロードする方法の例があります。Texture2D に写真を取り込む方法については、WebCam.PhotoCapture.TakePhotoAsync を参照してください。アップロードのコマンドを使用して画像データを Texture2D にアップロードすることは、Unityで画像データの使用する最も簡単な方法です。アップロード操作はメインスレッドで行われます。この操作はリソースに負荷がかかり、プロジェクトのパフォーマンスに影響する可能性があります。
ネイティブの画像データを WinRT IMFMediaBuffer としてキャプチャします。 詳細は、Microsoft のドキュメント IMFMediaBuffer を参照してください。バイトリストを PhotoFrame.CopyRawImageDataIntoBuffer 関数に渡して、ネイティブの画像データのコピーを作成します。コピー操作はメインスレッドで行われることに注意してください。この操作はリソースに負荷がかかり、プロジェクトのパフォーマンスに影響する可能性があります。
独自のプラグインを作成したり、画像データを別のスレッドで処理したりする場合は、PhotoFrame.GetUnsafePointerToBuffer 関数を使用してネイティブの画像データへのポインターを取得します。返されるポインターは、 IMFMediaBuffer コンポーネントオブジェクトモデル (COM) へのポインターです。詳細は、Microsoft のドキュメントの IMFMediaBuffer と Component Object Models を参照してください。この関数を呼び出すと、COM オブジェクトへの参照が追加されます。リソースが不要になったときに、参照を解放する必要があります。