夜風のMixedReality

xRと出会って変わった人生と出会った技術を書き残すためのGeekなHoloRangerの居場所

HoloLens のキャプチャに関して調査する ドキュメント 写真キャプチャ

本日はHoloLensデバイスのキャプチャに関して調査します。

HoloLensアプリでは一般的なスマートフォーンアプリなどと同様にアプリ内からカメラにアクセスし、写真を撮影することができます。

キャプチャとしてアプリ内の記録の写真のほかに取得したメディアを処理して結果を返す使用法などがあります。

今回はキャプチャの処理に関して調査します。

〇ドキュメント

docs.microsoft.com

今回はMicrosoftDocsのドキュメントを和訳しながら自分なりに解釈します。

〇フォトカメラの有効方法

HoloLensアプリ内でフォトカメラを使用するためには[WebCam]を有効にする必要があります。

[WebCam]はUnityの[PlayerSettings]から[PublishingSettings]→[Capabilities]から有効にします。

f:id:Holomoto-Sumire:20210102212405j:plain

現在のカメラモードは[UnityEngine.XR.WSA.WebCam.Mode]で確認できます。 モードには[写真]、[ビデオ]、[なし]が存在します。

〇写真

ネームスペース:UnityEngine.Windows.WebCam;ドキュメントではUnityEngine.XR.WSA.WebCamとなっていますがUnity2019.3.9以降では使用できません。)

フォトキャプチャのために使用します。

フォトキャプチャでは次の流れで写真の処理を行っています。

①PhotoCaptureオブジェクトを作成する

②設定したいCameraParametersオブジェクトを作成します。

③StartPhotoModeAsync によるフォトモードの開始

④写真を撮る

⑤(オプション) 画像の追加の処理

フォトモードを停止しリソースをクリーンアップ

〇フォトキャプチャの設定

①PhotoCapture オブジェクトの作成

PhotoCapture photoCaptureObject = null;
   void Start()
   {
       PhotoCapture.CreateAsync(false, OnPhotoCaptureCreated);
   }

フォトモードを開始します。

void OnPhotoCaptureCreated(PhotoCapture captureObject)
   {
       photoCaptureObject = captureObject;

       Resolution cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();

       CameraParameters c = new CameraParameters();
       c.hologramOpacity = 0.0f;
       c.cameraResolutionWidth = cameraResolution.width;
       c.cameraResolutionHeight = cameraResolution.height;
       c.pixelFormat = CapturePixelFormat.BGRA32;

       captureObject.StartPhotoModeAsync(c, OnPhotoModeStarted);
   }

Resolutionは表示解像度を表します。 

cameraResolisionはPhotoCaptureの写真を撮るためにサポートされているすべてのデバイスの解像度のリストから降順に並べ替え指定します。

CameraParametersはカメラ撮影に使用される設定を含んだオブジェクトを生成しています。

CameraParametersの設定は以下のようになります。

・hologramOpacity 撮影されるホログラムの透明度

・cameraResolutionWidth 撮影される画像の解像度の幅

・cameraResolutionHeight 撮影される画像の解像度の高さ

・pixelFormat captureの際に使用されるピクセル形式 BGRA32、NY12、JPEGPNGの形式から指定します。

〇どのような写真のタイプを撮影するかを指定する

写真を撮影します。

private void OnPhotoModeStarted(PhotoCapture.PhotoCaptureResult result)
   {
       if (result.success)
       {
           string filename = string.Format(@"CapturedImage{0}_n.jpg", Time.time);
           string filePath = System.IO.Path.Combine(Application.persistentDataPath, filename);

           photoCaptureObject.TakePhotoAsync(filePath, PhotoCaptureFileOutputFormat.JPG, OnCapturedPhotoToDisk);
       }
       else
       {
           Debug.LogError("Unable to start photo mode!");
       }
   }

フォトキャプチャー操作の結果情報を格納したデータコンテナである[PhotoCapture.PhotoCaptureResult]の操作の完了を示す[success]が真の場合

photoCaptureObject.TakePhotoAsync(filePath, PhotoCaptureFileOutputFormat.JPG, OnCapturedPhotoToDisk);

によって写真が撮影されます。上記の例ではJPGで撮影されます。

〇フォトキャプチャの停止

void OnCapturedPhotoToDisk(PhotoCapture.PhotoCaptureResult result)
   {
       if (result.success)
       {
           Debug.Log("Saved Photo to disk!");
           photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
       }
       else
       {
           Debug.Log("Failed to save Photo to disk");
       }
   }

フォトキャプチャを停止します。

〇フォトキャプチャのクリーンアップ

フォトキャプチャの写真撮影後クリーンアップを行います。

void OnCapturedPhotoToDisk(PhotoCapture.PhotoCaptureResult result)
   {
       if (result.success)
       {
           Debug.Log("Saved Photo to disk!");
           photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
       }
       else
       {
           Debug.Log("Failed to save Photo to disk");
       }
   }

撮影時と同様[PhotoCapture.PhotoCaptureResult]の操作の完了を示す[success]が真の場合フォトキャプチャの停止が行われます。

以上が写真キャプチャ時の処理の流れになります。

スクリプト

using UnityEngine;
using UnityEngine.Windows.WebCam;
using System.Linq;
using UnityEngine.XR;

public class PhotoCapturetest: MonoBehaviour
{
    PhotoCapture photoCaptureObject = null;
    void Start()
    {
        PhotoCapture.CreateAsync(false, OnPhotoCaptureCreated);
    }
    void OnPhotoCaptureCreated(PhotoCapture captureObject)
    {
        photoCaptureObject = captureObject;

        Resolution cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();

        CameraParameters c = new CameraParameters();
        c.hologramOpacity = 0.0f;
        c.cameraResolutionWidth = cameraResolution.width;
        c.cameraResolutionHeight = cameraResolution.height;
        c.pixelFormat = CapturePixelFormat.BGRA32;

        captureObject.StartPhotoModeAsync(c,OnPhotoModeStarted);
    }

    private void OnPhotoModeStarted(PhotoCapture.PhotoCaptureResult result)
    {
        if (result.success)
        {
            string filename = string.Format(@"CapturedImage{0}_n.jpg", Time.time);
            string filePath = System.IO.Path.Combine(Application.persistentDataPath, filename);

            photoCaptureObject.TakePhotoAsync(filePath, PhotoCaptureFileOutputFormat.JPG, OnCapturedPhotoToDisk);
        }
        else
        {
            Debug.LogError("Unable to start photo mode!");
        }
    }
    void OnCapturedPhotoToDisk(PhotoCapture.PhotoCaptureResult result)
    {
        if (result.success)
        {
            Debug.Log("Saved Photo to disk!");
            photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
        }
        else
        {
            Debug.Log("Failed to save Photo to disk");
        }
    }

    void OnStoppedPhotoMode(PhotoCapture.PhotoCaptureResult result)
    {
        photoCaptureObject.Dispose();
        photoCaptureObject = null;
    }
}

●参考

www.urablog.xyz