Unity のフォト ビデオ カメラ

カメラ アクセスのための機能の有効化

アプリでカメラを使用するには、"WebCam" 機能を宣言する必要があります。

  1. Unity Editor で、[編集]> [プロジェクト設定] > [プレイヤー] ページにアクセスして、[プレーヤーの設定] に移動します
  2. [Windows ストア] タブを選択します
  3. [Publishing Settings](パブリッシュ設定) > [Capabilities](機能) セクションで、WebCam および マイク 機能にチェックを付けます

カメラで一度に実行できる操作は 1 つだけです。 カメラで現在使用しているモードは、Unity 2018 以前では UnityEngine.XR.WSA.WebCam.Mode、Unity 2019 以降では UnityEngine.Windows.WebCam.Mode を使用して確認できます。 使用可能なモードは photo、video、または none です。

写真キャプチャ

名前空間 (Unity 2018 以前):UnityEngine.XR.WSA.WebCam
名前空間 (Unity 2019 以降):UnityEngine.Windows.WebCam
タイプ:PhotoCapture

PhotoCapture タイプでは、フォト ビデオ カメラを使用してスチール写真を撮ることができます。 PhotoCapture を使用して写真を撮る一般的なパターンは次のとおりです。

  1. PhotoCapture オブジェクトを作成します
  2. 希望する設定で CameraParameters オブジェクトを作成します
  3. StartPhotoModeAsync を使用して写真モードを開始します
  4. 撮りたい写真を撮影します
    • (オプション) 撮影した画像を加工します
  5. フォト モードを停止してリソースをクリーンアップします

PhotoCapture の共通セットアップ

3 つの用途すべてについて、上記の最初の 3 つの手順から開始します

まず、PhotoCapture オブジェクトを作成します

private void Start()
{
    PhotoCapture.CreateAsync(false, OnPhotoCaptureCreated);
}

次に、オブジェクトを格納し、パラメーターを設定して、写真モードを開始します

private PhotoCapture photoCaptureObject = null;

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, false, OnPhotoModeStarted);
}

最後に、ここで示しているものと同じクリーンアップ コードも使用します

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

これらの手順が終了したら、キャプチャする写真の種類を選択できます

ファイルへの写真のキャプチャ

最も簡単な操作は、写真を直接、ファイルにキャプチャすることです。 写真は JPG または PNG 形式で保存できます。

写真モードを正常に開始した場合は、写真を撮影してディスクに保存します

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");
    }
}

保存先指定で Texture2D に写真をキャプチャする

Texture2D にデータをキャプチャする場合の手順は、ディスクへのキャプチャとほぼ同様です。

上記のセットアップ手順に従います。

OnPhotoModeStarted で、フレームをメモリにキャプチャします。

private void OnPhotoModeStarted(PhotoCapture.PhotoCaptureResult result)
{
    if (result.success)
    {
        photoCaptureObject.TakePhotoAsync(OnCapturedPhotoToMemory);
    }
    else
    {
        Debug.LogError("Unable to start photo mode!");
    }
}

次に、結果をテクスチャに適用し、上記の共通クリーンアップ コードを使用します。

void OnCapturedPhotoToMemory(PhotoCapture.PhotoCaptureResult result, PhotoCaptureFrame photoCaptureFrame)
{
    if (result.success)
    {
        // Create our Texture2D for use and set the correct resolution
        Resolution cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();
        Texture2D targetTexture = new Texture2D(cameraResolution.width, cameraResolution.height);
        // Copy the raw image data into our target texture
        photoCaptureFrame.UploadImageDataToTexture(targetTexture);
        // Do as we wish with the texture such as apply it to a material, etc.
    }
    // Clean up
    photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
}

場所を特定できるカメラ

このテクスチャをシーンに配置し、場所を特定できるカメラ行列を使用して表示するには、次のコードを result.success チェックの OnCapturedPhotoToMemory に追加します。

if (photoCaptureFrame.hasLocationData)
{
    photoCaptureFrame.TryGetCameraToWorldMatrix(out Matrix4x4 cameraToWorldMatrix);

    Vector3 position = cameraToWorldMatrix.GetColumn(3) - cameraToWorldMatrix.GetColumn(2);
    Quaternion rotation = Quaternion.LookRotation(-cameraToWorldMatrix.GetColumn(2), cameraToWorldMatrix.GetColumn(1));

    photoCaptureFrame.TryGetProjectionMatrix(Camera.main.nearClipPlane, Camera.main.farClipPlane, out Matrix4x4 projectionMatrix);
}

特定のシェーダーに射影行列を適用するためのサンプル コードが Unity に用意されています (フォーラムを参照)。

写真をキャプチャして生のバイトを操作する

メモリ内フレームの生バイトを操作するには、上記と同じセットアップ手順に従い、Texture2D に写真をキャプチャする場合と同様に OnPhotoModeStarted を使用します。 違いは OnCapturedPhotoToMemory の部分で、ここで、生のバイトを取得して操作できます。

この例では、リストを作成し、処理を進めるか、SetPixels() を使用してテクスチャに適用します

void OnCapturedPhotoToMemory(PhotoCapture.PhotoCaptureResult result, PhotoCaptureFrame photoCaptureFrame)
{
    if (result.success)
    {
        List<byte> imageBufferList = new List<byte>();
        // Copy the raw IMFMediaBuffer data into our empty byte list.
        photoCaptureFrame.CopyRawImageDataIntoBuffer(imageBufferList);

        // In this example, we captured the image using the BGRA32 format.
        // So our stride will be 4 since we have a byte for each rgba channel.
        // The raw image data will also be flipped so we access our pixel data
        // in the reverse order.
        int stride = 4;
        float denominator = 1.0f / 255.0f;
        List<Color> colorArray = new List<Color>();
        for (int i = imageBufferList.Count - 1; i >= 0; i -= stride)
        {
            float a = (int)(imageBufferList[i - 0]) * denominator;
            float r = (int)(imageBufferList[i - 1]) * denominator;
            float g = (int)(imageBufferList[i - 2]) * denominator;
            float b = (int)(imageBufferList[i - 3]) * denominator;

            colorArray.Add(new Color(r, g, b, a));
        }
        // Now we could do something with the array such as texture.SetPixels() or run image processing on the list
    }
    photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
}

ビデオのキャプチャ

名前空間 (Unity 2018 以前):UnityEngine.XR.WSA.WebCam
名前空間 (Unity 2019 以降):UnityEngine.Windows.WebCam
タイプ:VideoCapture

VideoCapturePhotoCapture とほぼ同様に機能します。 2 つの点のみが異なっており、それは 1 秒あたりのフレーム数 (FPS) の値を指定する必要がある点と、MP4 ファイルとしてディスクへの直接保存のみが可能な点です。 VideoCapture を使用する手順は次のとおりです。

  1. VideoCapture オブジェクトを作成します
  2. 希望する設定で CameraParameters オブジェクトを作成します
  3. StartVideoModeAsync を使用してビデオ モードを開始します
  4. ビデオの録画を開始します
  5. ビデオの録画を停止します
  6. ビデオ モードを停止してリソースをクリーンアップします

まず、VideoCapture オブジェクト VideoCapture m_VideoCapture = null; を作成します。

void Start ()
{
    VideoCapture.CreateAsync(false, OnVideoCaptureCreated);
}

次に、録画に使用するパラメーターを設定し、開始します。

void OnVideoCaptureCreated(VideoCapture videoCapture)
{
    if (videoCapture != null)
    {
        m_VideoCapture = videoCapture;

        Resolution cameraResolution = VideoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();
        float cameraFramerate = VideoCapture.GetSupportedFrameRatesForResolution(cameraResolution).OrderByDescending((fps) => fps).First();

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

        m_VideoCapture.StartVideoModeAsync(cameraParameters,
                                            VideoCapture.AudioState.None,
                                            OnStartedVideoCaptureMode);
    }
    else
    {
        Debug.LogError("Failed to create VideoCapture Instance!");
    }
}

開始後すぐに、録画が始まります

void OnStartedVideoCaptureMode(VideoCapture.VideoCaptureResult result)
{
    if (result.success)
    {
        string filename = string.Format("MyVideo_{0}.mp4", Time.time);
        string filepath = System.IO.Path.Combine(Application.persistentDataPath, filename);

        m_VideoCapture.StartRecordingAsync(filepath, OnStartedRecordingVideo);
    }
}

録画開始後、UI または動作を更新して停止を有効にすることができます。 ここでは、ただログを記録します。

void OnStartedRecordingVideo(VideoCapture.VideoCaptureResult result)
{
    Debug.Log("Started Recording Video!");
    // We will stop the video from recording via other input such as a timer or a tap, etc.
}

後で、たとえば、タイマーまたはユーザー入力を使用して録画を停止します。

// The user has indicated to stop recording
void StopRecordingVideo()
{
    m_VideoCapture.StopRecordingAsync(OnStoppedRecordingVideo);
}

録画が停止したら、ビデオ モードを停止してリソースをクリーンアップします。

void OnStoppedRecordingVideo(VideoCapture.VideoCaptureResult result)
{
    Debug.Log("Stopped Recording Video!");
    m_VideoCapture.StopVideoModeAsync(OnStoppedVideoCaptureMode);
}

void OnStoppedVideoCaptureMode(VideoCapture.VideoCaptureResult result)
{
    m_VideoCapture.Dispose();
    m_VideoCapture = null;
}

トラブルシューティング

  • 利用できるトラブルシューティングはありません
    • WebCam 機能をプロジェクトで規定しておきます。

次の開発チェックポイント

Microsoft による Unity 開発チェックポイント体験に沿って進んでいるなら、ここでは Mixed Reality プラットフォームの機能と API を扱います。 ここから、次のトピックを続けることができます。

または、デバイスまたはエミュレーターへのアプリの配置操作に直接移動します。

いつでも Unity 開発チェックポイントに戻ることができます。

関連項目