共用方式為


執行階段 SDK 概觀

本節提供 Object Anchors 執行階段 SDK 的高階概觀,可用來使用Object Anchors 模型來偵測物件。 您將可了解物件的表示方式,以及各種元件的用途。

下列其中一個命名空間可以找到下列所有類型:Microsoft.Azure.ObjectAnchorsMicrosoft.Azure.ObjectAnchors.DiagnosticsMicrosoft.Azure.ObjectAnchors.SpatialGraph

類型

ObjectModel

ObjectModel 代表實體物件的幾何,並可將偵測和姿勢估計的必要參數進行編碼。 必須使用 Object Anchors 服務來建立。 然後,應用程式可以使用 Object Anchors API 載入產生的模型檔案,並查詢該模型中內嵌的網格以取得視覺效果。

ObjectSearchArea

ObjectSearchArea 會指定要尋找一或多個物件的空間。 由空間圖形節點識別碼和空間圖表節點識別碼所代表座標系統中的空間界限所定義。 Object Anchors 執行階段 SDK 支援四種類型的界限,也就是檢視欄位週框方塊球體位置

AccountInformation

AccountInformation 會儲存 Azure Object Anchors 帳戶的識別碼、金鑰和網域。

ObjectAnchorsSession

ObjectAnchorsSession 代表用來建立用來偵測實體世界中物件的 ObjectObserver 執行個體的 Azure Object Anchors 工作階段。

ObjectObserver

ObjectObserver 會在 HoloLens 座標系統中載入物件模型、偵測其執行個體,以及報告每個執行個體 6-DoF 姿勢。

雖然任何物件模型或執行個體都是從觀察者建立的,但有各自的存留期。 應用程式可以處置觀察者,並繼續使用物件模型或執行個體。

ObjectQuery

ObjectQuery 會告知物件觀察者如何尋找指定模型的物件。 它會提供下列可調整參數,其預設值可以從物件模型擷取。

MinSurfaceCoverage

MinSurfaceCoverage 屬性會指出要視為偵測到執行個體的值。

針對每個候選物件,觀察者會計算轉換物件模型與場景之間的重疊表面比例,然後只有在涵蓋範圍比例高於指定的臨界值時,才會向應用程式報告候選物件。

IsExpectedToBeStandingOnGroundPlane

IsExpectedToBeStandingOnGroundPlane 屬性會指出目標物件是否預期位於地平面上。

地平面是搜尋區域中的最低水平層。 它可針對可能的物件姿勢提供良好的限制式。 開啟此旗標會引導觀察者估計有限空間中的姿勢,並可改善正確性。 如果模型不應位於地平面,則會忽略此參數。

ExpectedMaxVerticalOrientationInDegrees

ExpectedMaxVerticalOrientationInDegrees 屬性指出物件執行個體往上的方向與重力之間的預期最大角度為單位。

此參數會針對估計姿勢的向上方向提供另一個限制式。 例如,如果物件位於右上方,此參數可能是 0。 Object Anchors 不應偵測與模型不同的物件。 如果模型位於右上方,則不會偵測到向下的執行個體。 新的模型會用於向下配置。 相同的規則適用於清晰度。

MaxScaleChange

MaxScaleChange 屬性指出有關空間對應的物件縮放變更上限 (範圍為 0 ~ 1)。 預估小數位數會套用至轉換的物件頂點,這些頂點以原點為中心並對齊座標軸。 估計刻度可能不是 CAD 模型與其實體表示之間的實際刻度,但部分值可讓應用程式將物件模型轉譯為接近實體物件上的空間對應。

SearchAreas

SearchAreas 屬性指出可尋找物件的空間界限陣列。

觀察者會在查詢中指定的所有搜尋區域聯合空間中尋找物件。 在此版本中,我們最多會傳回一個具有最高信賴度的物件,以減少延遲。

ObjectInstance

ObjectInstance 代表假設的位置,其中指定模型的執行個體可以位於 HoloLens 座標系統中。 每個執行個體都有 SurfaceCoverage 屬性,以指出估計姿勢的優異程度。

執行個體是藉由呼叫 ObjectObserver.DetectAsync 方法來建立,然後在作用中時自動更新背景。 應用程式可以接聽特定執行個體上的狀態變更事件,或變更追蹤模式以暫停/繼續更新。 追蹤遺失時,會自動從觀察者移除執行個體。

ObjectDiagnosticsSession

ObjectDiagnosticSession 會記錄診斷並將資料寫入封存。

診斷封存包括場景點雲端、觀察者的狀態,以及模型的相關資訊。 這項資訊有助於識別可能的執行階段問題。 如需詳細資訊,請參閱常見問題集

執行階段 SDK 使用量和詳細資料

本節應介紹如何使用執行階段 SDK 的基本概念。 應透過範例應用程式提供足夠的內容,讓您可以了解如何全面使用 Object Anchors。

初始化

應用程式必須先呼叫 ObjectObserver.IsSupported() API,才能判斷裝置上是否支援 Object Anchors,再進行使用。 如果 ObjectObserver.IsSupported() API 傳回 false,請檢查應用程式是否已啟用 spatialPerception 功能,以及\或升級至最新的 HoloLens OS。

using Microsoft.Azure.ObjectAnchors;

if (!ObjectObserver.IsSupported())
{
    // Handle the error
}

// This call should grant the access we need.
ObjectObserverAccessStatus status = await ObjectObserver.RequestAccessAsync();
if (status != ObjectObserverAccessStatus.Allowed)
{
    // Handle the error
}

接下來,應用程式會建立物件觀察者,並載入 Object Anchors 模型轉換服務所產生的必要模型。

using Microsoft.Azure.ObjectAnchors;

// Note that you need to provide the Id, Key and Domain for your Azure Object
// Anchors account.
Guid accountId = new Guid("[your account id]");
string accountKey = "[your account key]";
string accountDomain = "[your account domain]";

AccountInformation accountInformation = new AccountInformation(accountId, accountKey, accountDomain);
ObjectAnchorsSession session = new ObjectAnchorsSession(accountInformation);
ObjectObserver observer = session.CreateObjectObserver();

// Load a model into a byte array. The model could be a file, an embedded
// resource, or a network stream.
byte[] modelAsBytes;
ObjectModel model = await observer.LoadObjectModelAsync(modelAsBytes);

// Note that after a model is loaded, its vertices and normals are transformed
// into a centered coordinate system for the ease of computing the object pose.
// The rigid transform can be retrieved through the `OriginToCenterTransform`
// property.

應用程式會建立查詢來偵測空間內該模型的執行個體。

#if WINDOWS_UWP || DOTNETWINRT_PRESENT
#define SPATIALCOORDINATESYSTEM_API_PRESENT
#endif

using Microsoft.Azure.ObjectAnchors;
using Microsoft.Azure.ObjectAnchors.SpatialGraph;
using Microsoft.Azure.ObjectAnchors.Unity;
using UnityEngine;

// Get the coordinate system.
SpatialGraphCoordinateSystem? coordinateSystem = null;

#if SPATIALCOORDINATESYSTEM_API_PRESENT
SpatialCoordinateSystem worldOrigin = ObjectAnchorsWorldManager.WorldOrigin;
if (worldOrigin != null)
{
    coordinateSystem = await Task.Run(() => worldOrigin.TryToSpatialGraph());
}
#endif

if (!coordinateSystem.HasValue)
{
    Debug.LogError("no coordinate system?");
    return;
}

// Get the search area.
SpatialFieldOfView fieldOfView = new SpatialFieldOfView
{
    Position = Camera.main.transform.position.ToSystem(),
    Orientation = Camera.main.transform.rotation.ToSystem(),
    FarDistance = 4.0f, // Far distance in meters of object search frustum.
    HorizontalFieldOfViewInDegrees = 75.0f, // Horizontal field of view in
                                            // degrees of object search frustum.
    AspectRatio = 1.0f // Aspect ratio (horizontal / vertical) of object search
                       // frustum.
};

ObjectSearchArea searchArea = ObjectSearchArea.FromFieldOfView(coordinateSystem.Value, fieldOfView);

// Optionally change the parameters, otherwise use the default values embedded
// in the model.
ObjectQuery query = new ObjectQuery(model);
query.MinSurfaceCoverage = 0.2f;
query.ExpectedMaxVerticalOrientationInDegrees = 1.5f;
query.MaxScaleChange = 0.1f;
query.SearchAreas.Add(searchArea);

// Detection could take a while, so we run it in a background thread.
IReadOnlyList<ObjectInstance> detectedObjects = await observer.DetectAsync(query);

根據預設,觀察者會自動追蹤每個偵測到的執行個體。 我們可以透過變更追蹤模式或接聽其狀態變更事件,選擇性地操作這些執行個體。

using Microsoft.Azure.ObjectAnchors;

foreach (ObjectInstance instance in detectedObjects)
{
    // Supported modes:
    // "LowLatencyCoarsePosition"    - Consumes less CPU cycles thus fast to
    //                                 update the state.
    // "HighLatencyAccuratePosition" - Uses the device's camera and consumes more CPU
    //                                 cycles thus potentially taking longer
    //                                 time to update the state.
    // "Paused"                      - Stops to update the state until mode
    //                                 changed to low or high.
    instance.Mode = ObjectInstanceTrackingMode.LowLatencyCoarsePosition;

    // Listen to state changed event on this instance.
    instance.Changed += InstanceChangedHandler;

    // Optionally dispose an instance if not interested in it.
    // instance.Dispose();
}

在狀態變更事件中,我們可以查詢最新的狀態,或在執行個體遺失追蹤時進行處置。

using Microsoft.Azure.ObjectAnchors;

void InstanceChangedHandler(object sender, ObjectInstanceChangedEventArgs args)
{
    // Try to query the current instance state.
    ObjectInstanceState state = sender.TryGetCurrentState();

    if (state != null)
    {
        // Process latest state.
        // An object pose includes rotation and translation, applied in
        // the same order to the object model in the centered coordinate system.
    }
    else
    {
        // This object instance is lost for tracking, and will never be recovered.
        // The caller can detach the Changed event handler from this instance
        // and dispose it.
    }
}

此外,應用程式可以選擇性地記錄一或多個診斷工作階段,以進行離線偵錯。

using Microsoft.Azure.ObjectAnchors;
using Microsoft.Azure.ObjectAnchors.Diagnostics;

string diagnosticsFolderPath = Windows.Storage.ApplicationData.Current.TemporaryFolder.Path;
const uint maxSessionSizeInMegaBytes = uint.MaxValue;

// Recording starts on the creation of a diagnostics session.
ObjectDiagnosticsSession diagnostics = new ObjectDiagnosticsSession(observer, maxSessionSizeInMegaBytes);

// Wait for the observer to do a job.

// Application can report some **pseudo ground-truth** pose for an instance
// acquired from other means.
diagnostics.ReportActualInstanceLocation(instance, coordinateSystem, Vector3.Zero, Quaternion.Identity);

// Close a session and write the diagnostics into an archive at specified location.
await diagnostics.CloseAsync(System.IO.Path.Combine(diagnosticsFolderPath, "diagnostics.zip"));

最後,我們會透過處置所有物件來釋放資源。

using Microsoft.Azure.ObjectAnchors;

foreach (ObjectInstance instance in activeInstances)
{
    instance.Changed -= InstanceChangedHandler;
    instance.Dispose();
}

model.Dispose();
observer.Dispose();