AR Foundation Android アプリで Depth を使用する

Depth API を使用すると、デバイスのカメラでシーン内の実際の物体のサイズと形状を認識できます。カメラを使用して奥行き画像(奥行きマップ)を作成することで、アプリに AR のリアリティのレイヤを追加します。奥行きのある画像から得られる情報を使用して、仮想オブジェクトを現実世界のオブジェクトの前または後ろに正確に表示し、臨場感のあるリアルなユーザー エクスペリエンスを実現できます。

奥行き情報は動きから計算され、可能であれば飛行時間(ToF)センサーなどのハードウェア奥行きセンサーからの情報と組み合わせることができます。デバイスで Depth API をサポートするため ToF センサーは不要

前提条件

AR の基礎的なコンセプトを理解しておいてください。 と ARCore セッションを構成する方法を確認してください。

アプリを Depth Required または Depth Optional に設定する(Android のみ)

アプリで Depth API のサポートが必要な場合は、次の操作を行います。 AR エクスペリエンスの核となる部分が深さに依存するため、または アプリで深度を使用する領域に適切な代替手段がない場合、 Google Play ストアでのアプリの配信を、 Depth API をサポートするデバイス

アプリを Depth Required にする

Edit > Project Settings > XR Plug-in Management > ARCore に移動します。

Depth はデフォルトで Required に設定されています。

アプリを Depth Optional にする

  1. Edit > Project Settings > XR Plug-in Management > ARCore に移動します。

  2. [Depth] プルダウン メニューから [Optional] を選択します。 必要に応じてアプリの深度を設定します。

奥行きを有効にする

リソースを節約するため、ARCore はデフォルトでは Depth API を有効にしません。使用する 深度の利点を活かすには、 AROcclusionManager コンポーネントを AR カメラゲーム オブジェクトに CameraARCameraBackground コンポーネント。詳しくは、 自動オクルージョン をご覧ください。

新しい ARCore セッションで、 ユーザーのデバイスは、次のように深度と Depth API をサポートしています。

// Reference to AROcclusionManager that should be added to the AR Camera
// game object that contains the Camera and ARCameraBackground components.
var occlusionManager = …

// Check whether the user's device supports the Depth API.
if (occlusionManager.descriptor?.supportsEnvironmentDepthImage)
{
    // If depth mode is available on the user's device, perform
    // the steps you want here.
}

奥行きのある画像を取得する

最新の環境深度イメージを AROcclusionManager

// Reference to AROcclusionManager that should be added to the AR Camera
// game object that contains the Camera and ARCameraBackground components.
var occlusionManager = …

if (occlusionManager.TryAcquireEnvironmentDepthCpuImage(out XRCpuImage image))
{
    using (image)
    {
        // Use the texture.
    }
}

未加工の CPU イメージを RawImage に変換できます。 柔軟性の向上です「 これを行う方法の例については、Unity の ARFoundation サンプルをご覧ください。

深度値について

観測された実世界のジオメトリ上の点 A と 2D の点 a 深度画像内の同じポイントを表します。Depth a の API の座標は、CA を主軸に投影した長さと等しくなります。 これは、カメラを基準とする A の Z 座標とも呼ばれます。 オリジン: C。Depth API を使用する際は、次の点を理解することが重要です。 深度値は光線 CA 自体の長さではなく、投影です できます。

仮想オブジェクトを遮断して深度データを可視化する

Unity のブログ投稿を確認する 深度データの概要と、この検出方法を使用して 説明します。また、Unity の ARFoundation のサンプル 仮想画像のオクルージョンと奥行きデータの可視化を実演しています。

オクルージョンは、2 パス レンダリングまたはオブジェクトごとのフォワードパス レンダリングを使用してレンダリングできます。それぞれの方法の効率は、シーンの複雑さやその他のアプリ固有の考慮事項によって異なります。

オブジェクトごとのフォワードパス レンダリング

オブジェクトごとのフォワードパス レンダリングでは、マテリアル シェーダーでのオブジェクトの各ピクセルのオクルージョンを決定します。ピクセルが見えない場合は、通常はアルファ ブレンディングによってクリップされ、ユーザーのデバイスでオクルージョンをシミュレートします。

2 パス レンダリング

2 パス レンダリングでは、最初のパスですべての仮想コンテンツが中間バッファにレンダリングされます。2 回目のパスでは、現実世界の奥行きと仮想シーンの奥行きの差に基づいて、仮想シーンを背景にブレンドします。この方法では、オブジェクト固有のシェーダーを追加で作業する必要はなく、通常はフォワードパス メソッドよりも均一な結果が得られます。

深度画像から距離を抽出する

仮想オブジェクトの隠蔽や奥行きデータの可視化以外の目的で Depth API を使用するには、奥行き画像から情報を抽出します。

Texture2D _depthTexture;
short[] _depthArray;

void UpdateEnvironmentDepthImage()
{
  if (_occlusionManager &&
        _occlusionManager.TryAcquireEnvironmentDepthCpuImage(out XRCpuImage image))
    {
        using (image)
        {
            UpdateRawImage(ref _depthTexture, image, TextureFormat.R16);
            _depthWidth = image.width;
            _depthHeight = image.height;
        }
    }
  var byteBuffer = _depthTexture.GetRawTextureData();
  Buffer.BlockCopy(byteBuffer, 0, _depthArray, 0, byteBuffer.Length);
}

// Obtain the depth value in meters at a normalized screen point.
public static float GetDepthFromUV(Vector2 uv, short[] depthArray)
{
    int depthX = (int)(uv.x * (DepthWidth - 1));
    int depthY = (int)(uv.y * (DepthHeight - 1));

    return GetDepthFromXY(depthX, depthY, depthArray);
}

// Obtain the depth value in meters at the specified x, y location.
public static float GetDepthFromXY(int x, int y, short[] depthArray)
{
    if (!Initialized)
    {
        return InvalidDepthValue;
    }

    if (x >= DepthWidth || x < 0 || y >= DepthHeight || y < 0)
    {
        return InvalidDepthValue;
    }

    var depthIndex = (y * DepthWidth) + x;
    var depthInShort = depthArray[depthIndex];
    var depthInMeters = depthInShort * MillimeterToMeter;
    return depthInMeters;
}

次のステップ

  • Raw Depth API を使用すると、より正確な検出が可能になります。
  • ARCore Depth Lab で、深度データにアクセスするさまざまな方法を確認しましょう。