Table of Contents

外部幀資料來源的輸入幀資料要求

為使外部幀資料來源正常工作,最重要的工作同時也是最棘手的部分是確保資料正確性。本文介紹了外部幀資料來源的輸入幀資料要求。

開始之前

輸入幀資料類型

在 Unity 中,外部幀資料來源通常需要在兩個不同時間接收不同的資料,根據外部資料輸入時間和資料特徵,我們將這兩組資料稱為:

  1. 相機幀資料(camera frame data)
  2. 渲染幀資料(rendering frame data)

不同類型的外部幀資料來源對這兩組資料的需求不同:

  • 影像和設備運動資料輸入擴展:同時需要相機幀資料及渲染幀資料
  • 影像輸入擴展:只需要相機幀資料

相機幀資料

資料需求:

  1. 時間戳(timestamp)
  2. 原始實體相機影像資料(raw camera image data)
  3. 內參(intrinsics,包括影像大小、焦距、主點。如果有畸變還需要畸變模型和畸變參數)
  4. 外參(extrinsics,Tcw 或 Twc,標定的矩陣,表達實體相機相對設備/頭的 pose 原點的物理偏移)
  5. 跟蹤狀態(tracking status)
  6. 設備位姿(device pose)

資料時間:

  • 實體相機曝光中點

資料使用:

  • API 呼叫時間:可根據外部代碼的設計改變。一個大多數設備使用的常規方法是在 3D 引擎的渲染更新中查詢,然後根據設備資料的時間戳來判斷是否進一步進行資料處理
  • API 呼叫線程:3D 引擎的 game thread 或任何其它線程(如果使用到的所有外部 API 都是線程安全的)

Unity 中 API 調用示例如下:

void TryInputCameraFrameData()
{
    double timestamp;

    if (timestamp == curTimestamp) { return; }
    curTimestamp = timestamp;

    PixelFormat format;
    Vector2Int size;
    Vector2Int pixelSize;
    int bufferSize;

    var bufferO = TryAcquireBuffer(bufferSize);
    if (bufferO.OnNone) { return; }
    var buffer = bufferO.Value;

    IntPtr imageData;
    buffer.tryCopyFrom(imageData, 0, 0, bufferSize);

    var historicalHeadPose = new Pose();
    MotionTrackingStatus trackingStatus = (MotionTrackingStatus)(-1);

    using (buffer)
    using (var image = Image.create(buffer, format, size.x, size.y, pixelSize.x, pixelSize.y))
    {
        HandleCameraFrameData(deviceCamera, timestamp, image, cameraParameters, historicalHeadPose, trackingStatus);
    }
}

渲染幀數據

數據需求:

  1. 時間戳(timestamp)
  2. 跟蹤狀態(tracking status)
  3. 設備位姿(device pose)

資料時間:

  • 上屏時刻。TimeWarp 不計算在內。相同時刻的 device pose 資料會由外部(比如設備 SDK)用來設置虛擬攝像機的 transform 以渲染當前幀。
附註

TimeWarp(有時也稱為 Reprojection 或 ATW/PTW)是 VR/AR 頭顯中常用的一種降低延遲的技術。它會在渲染完成後,根據最新的頭部位姿對影像進行再次扭曲變換,以補償渲染期間產生的頭部運動。EasyAR 需要的是渲染開始時用於設置虛擬攝像機的位姿對應的時刻,而不是 TimeWarp 後實際上屏的時刻。

資料使用:

  • API 呼叫時間:3D 引擎的每個渲染幀
  • API 呼叫線程:3D 引擎的 game thread

Unity 中 API 調用示例如下:

private void InputRenderFrameMotionData()
{
    double timestamp = 0e-9;
    var headPose = new Pose();
    MotionTrackingStatus trackingStatus = (MotionTrackingStatus)(-1);
    HandleRenderFrameData(timestamp, headPose, trackingStatus);
}

資料要求細節

實體相機影像資料:

  • 影像座標系:在傳感器水平時獲取的資料也應是水平的。資料應該以左上角為原點,行優先存儲。影像不應翻轉或顛倒。
  • 影像 FPS:正常 30 或 60 fps 的資料都可以。如果高 fps 有特殊影響,為達到合理的算法效果,最小可接受幀率為 2。建議使用高於 2 的 fps,通常情況下使用原始資料幀率即可。
  • 影像尺寸:為獲取更好的計算結果,最大邊應為 960 或更大。正常不鼓勵在資料鏈路中進行耗時的影像縮放,建議直接使用原始資料,除非完整大小的資料拷貝時間已經長得無法接受。影像解析度不能小於 640*480。
  • 像素格式:優先跟蹤效果並綜合考慮性能,通常格式優先順序為 YUV > RGB > RGBA > Gray (YUV中的Y分量)。在使用 YUV 資料時,需要完整的資料定義,包括資料封裝和填充細節。相較單通道影像而言,使用彩色影像 Mega 的效果會更好,但其它功能影響不大。
  • 資料訪問:資料指針或等價實現。最好在資料鏈路中消除所有可能的非必須拷貝。HandleRenderFrameData 中 EasyAR 複製一份資料,之後非同步使用,該同步呼叫完成後就不再使用影像資料。注意資料所有權。

時間戳:

  • 所有時間戳都應時鐘同步,最好是硬體同步。資料單位是秒,但精度要求達到奈秒或盡可能高。

追蹤狀態:

  • 追蹤狀態由設備定義,需要包含追蹤遺失(VIO不可用)的狀態。如有更多等級則更好。

設備位姿:

  • 所有 pose(包括 3D 引擎中虛擬攝影機的 transform)都應使用同一個原點。
  • 所有 pose 以及外參應該使用相同的座標軸系統。
  • 在 Unity 中,pose 資料的座標軸系統類型應為 Unity 座標軸系統或 EasyAR 座標軸系統。如果輸入擴展由 EasyAR 實現且使用了其它座標軸系統定義方式,應提供清晰的座標軸系統定義或給出轉換到 Unity 座標軸系統或 EasyAR 座標軸系統的方法。
  • 在 Unity 中,如果使用 Unity XR 框架,只需要相容 XROrigin.TrackingOriginMode.Device 模式即可。

內參:

  • 所有數值都應與影像資料匹配。如有需要應在輸入 EasyAR 之前對內參進行縮放。
  • 如果輸入擴展由 EasyAR 實現,應說明內參是否會在每一幀變化(區別是對應 API 應該呼叫一次還是每幀呼叫)。

外參:

  • 在頭顯上必須提供真實資料。
  • 它是一個標定矩陣,表達實體相機相對設備/頭的 pose 原點的實體偏移。如果設備的 pose 和實體相機 pose 相等,它應該是單位陣。
  • Apple Vision Pro 對應介面為: CameraFrame.Sample.Parameters.extrinsics,需要注意其資料定義與介面所需資料有區別,EasyAR 內部是進行轉換之後再使用的。
  • 在 Unity 中,外參的座標軸系統類型應為 Unity 座標軸系統或 EasyAR 座標軸系統。如果輸入擴展由 EasyAR 實現且使用了其它座標軸系統定義方式,應提供清晰的座標軸系統定義或給出轉換到 Unity 座標軸系統或 EasyAR 標軸系統的方法。
  • 在頭顯設備中,通常存在多個不同定義的座標系,這個不同可能包括座標軸原點、朝向、左右手表達等。外參應在同一座標系下計算,該介面資料需要同一座標系下的座標變換,而非兩個不同定義的座標系的變換矩陣。

效能:

  • 資料應以最優效率提供。在大多數實現中,API 呼叫會發生在渲染過程,所以建議即使在底層需要進行耗時操作的情況下,也不要阻塞 API 呼叫,或者以合理的方式來使用這些 API。
  • 如果輸入擴展由 EasyAR 實現,需要對所有耗時 API 呼叫進行說明。

多相機:

  • 至少一個相機的資料是需要的。這個相機可以是 RGB 相機、VST 相機、定位相機等中的任意一個。在頭顯上如果只輸入一個相機的資料,通常推薦使用在中央或在眼睛附近的 RGB 相機或 VST 相機。
  • 使用多相機可提升 EasyAR 演算法效果。所有可用相機某一時刻的相機幀資料應在在同一個時間點同時輸入。

多相機目前尚未完全支援,可以聯絡 EasyAR 取得更多細節。

後續步驟

相關主題

  • EasyAR 座標系
  • 影像輸入擴展示例 Workflow_FrameSource_ExternalImageStream