از Depth در برنامه Android Foundation خود استفاده کنید

Depth API به دوربین دستگاه کمک می کند تا اندازه و شکل اشیاء واقعی را در یک صحنه درک کند. از دوربین برای ایجاد تصاویر عمق یا نقشه های عمق استفاده می کند و در نتیجه لایه ای از واقعیت واقعیت افزوده را به برنامه های شما اضافه می کند. می‌توانید از اطلاعات ارائه‌شده توسط یک تصویر عمقی استفاده کنید تا اشیاء مجازی را به‌طور دقیق در جلو یا پشت اشیاء دنیای واقعی نشان دهید و تجربه‌های واقعی و واقعی کاربر را امکان‌پذیر کنید.

اطلاعات عمق از حرکت محاسبه می شود و در صورت وجود ممکن است با اطلاعات یک حسگر عمق سخت افزاری مانند سنسور زمان پرواز (ToF) ترکیب شود. یک دستگاه برای پشتیبانی از Depth API به حسگر ToF نیاز ندارد .

پیش نیازها

قبل از ادامه، مطمئن شوید که مفاهیم اساسی AR و نحوه پیکربندی یک جلسه ARCore را درک کرده اید.

برنامه خود را طوری پیکربندی کنید که Depth Required یا Depth Optional باشد (فقط اندروید)

اگر برنامه شما به پشتیبانی Depth API نیاز دارد، یا به این دلیل که بخش اصلی تجربه واقعیت افزوده به عمق متکی است، یا به این دلیل که برای بخش‌هایی از برنامه که از عمق استفاده می‌کنند، نسخه بازگشتی خوبی وجود ندارد، می‌توانید توزیع برنامه خود را در 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 انتخاب کنید تا یک برنامه روی Depth اختیاری تنظیم شود.

Depth را فعال کنید

برای ذخیره منابع، ARCore به طور پیش فرض Depth API را فعال نمی کند. برای استفاده از عمق دستگاه‌های پشتیبانی‌شده، باید مؤلفه AROcclusionManager را به‌صورت دستی به شی بازی دوربین AR با مؤلفه Camera و ARCameraBackground اضافه کنید. برای اطلاعات بیشتر به انسداد خودکار در مستندات Unity مراجعه کنید.

در یک جلسه جدید 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 تبدیل کنید. نمونه ای برای نحوه انجام این کار را می توان در نمونه های ARFoundation Unity یافت.

درک مقادیر عمق

با توجه به نقطه A در هندسه دنیای واقعی مشاهده شده و یک نقطه 2 بعدی a همان نقطه را در تصویر عمق نشان می دهد، مقدار داده شده توسط Depth API در a برابر است با طول CA پیش بینی شده روی محور اصلی. این را می توان به عنوان مختصات z A نسبت به مبدا دوربین C نیز نام برد. هنگام کار با Depth API، درک این نکته مهم است که مقادیر عمق طول خود پرتو CA نیست، بلکه نمایش آن است.

اشیای مجازی را مسدود کنید و داده های عمق را تجسم کنید

برای مشاهده اجمالی سطح بالا از داده های عمق و نحوه استفاده از آن برای مسدود کردن تصاویر مجازی، پست وبلاگ Unity را بررسی کنید. علاوه بر این، نمونه‌های ARFoundation یونیتی انسداد تصاویر مجازی و تجسم داده‌های عمق را نشان می‌دهند.

شما می توانید انسداد را با استفاده از رندر دو گذری یا رندر در هر شی، به جلو رندر کنید. کارایی هر رویکرد به پیچیدگی صحنه و سایر ملاحظات خاص برنامه بستگی دارد.

رندر برای هر شی، گذر به جلو

رندر به ازای هر شی، گذر به جلو، انسداد هر پیکسل از جسم را در سایه‌زن مواد آن تعیین می‌کند. اگر پیکسل ها قابل مشاهده نباشند، معمولاً از طریق ترکیب آلفا بریده می شوند، بنابراین انسداد در دستگاه کاربر شبیه سازی می شود.

رندر دو پاس

با رندر دو پاس، اولین پاس تمام محتوای مجازی را به یک بافر واسطه تبدیل می کند. پاس دوم صحنه مجازی را بر اساس تفاوت بین عمق دنیای واقعی و عمق صحنه مجازی با پس‌زمینه ترکیب می‌کند. این رویکرد نیازی به کار اضافی شیدر مخصوص شیء ندارد و به طور کلی نتایج یکنواخت تری نسبت به روش گذر به جلو ایجاد می کند.

استخراج فاصله از یک تصویر عمقی

برای استفاده از 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;
}

بعدش چی