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 origin에 대해 갖는 물리적 오프셋을 표현하는 보정된 행렬)
  5. 추적 상태(tracking status)
  6. 디바이스 pose(device pose)

데이터 시각:

  • 물리 카메라 노출의 중간 시점

데이터 사용:

  • API 호출 시각: 외부 코드의 설계에 따라 달라질 수 있습니다. 대부분의 디바이스에서 사용하는 일반적인 방법은 3D engine의 렌더링 업데이트 중에 질의한 뒤, 디바이스 데이터의 timestamp에 따라 데이터를 추가로 처리할지 판단하는 것입니다
  • API 호출 스레드: 3D engine의 game thread, 또는 사용하는 모든 외부 API가 thread-safe라면 임의의 다른 스레드

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

frame data 렌더링

데이터 요구 사항:

  1. Timestamp
  2. Tracking status
  3. Device pose

데이터 시각:

  • 화면에 표시되는 시점입니다. TimeWarp는 포함하지 않습니다. 같은 시점의 device pose 데이터는 외부, 예를 들어 device SDK에서 현재 프레임을 렌더링하기 위해 가상 카메라의 transform을 설정하는 데 사용됩니다.
참고

TimeWarp(때로는 Reprojection 또는 ATW/PTW라고도 함)는 VR/AR 헤드셋에서 지연 시간을 줄이기 위해 흔히 사용하는 기술입니다. 렌더링이 완료된 뒤 최신 머리 pose에 따라 이미지를 다시 워핑하여 렌더링 중 발생한 머리 움직임을 보정합니다. EasyAR에 필요한 것은 렌더링 시작 시 가상 카메라를 설정하는 데 사용된 pose에 해당하는 시각이며, TimeWarp 이후 실제로 화면에 표시되는 시각이 아닙니다.

데이터 사용:

  • API 호출 시각: 3D engine의 각 렌더링 프레임
  • API 호출 스레드: 3D engine의 game thread

Unity에서 API 호출 예시는 다음과 같습니다.

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

데이터 요구 사항 세부 정보

물리 카메라 이미지 데이터:

  • 이미지 좌표계: 센서가 수평일 때 획득한 데이터도 수평이어야 합니다. 데이터는 왼쪽 위 모서리를 origin으로 사용하고 row-major 순서로 저장해야 합니다. 이미지는 좌우 반전되거나 상하로 뒤집히면 안 됩니다.
  • 이미지 FPS: 일반적인 30 또는 60 fps 데이터는 모두 사용할 수 있습니다. 높은 fps가 특별한 영향을 주는 경우, 합리적인 알고리즘 결과를 얻기 위한 최소 허용 프레임률은 2입니다. 2보다 높은 fps 사용을 권장하며, 일반적으로 원본 데이터 프레임률을 그대로 사용하면 됩니다.
  • 이미지 크기: 더 좋은 계산 결과를 얻으려면 가장 긴 변이 960 이상이어야 합니다. 일반적으로 데이터 경로에서 시간이 많이 드는 이미지 스케일링은 권장하지 않습니다. 전체 크기 데이터의 복사 시간이 이미 허용할 수 없을 정도로 길지 않다면 원본 데이터를 직접 사용하는 것이 좋습니다. 이미지 해상도는 640*480보다 작을 수 없습니다.
  • 픽셀 형식: 추적 효과를 우선하고 성능을 종합적으로 고려할 때 일반적인 형식 우선순위는 YUV > RGB > RGBA > Gray(YUV의 Y 성분)입니다. YUV 데이터를 사용할 때는 데이터 패킹과 padding 세부 정보를 포함한 완전한 데이터 정의가 필요합니다. 단일 채널 이미지에 비해 컬러 이미지를 사용하면 Mega 효과가 더 좋지만, 다른 기능에는 큰 영향이 없습니다.
  • 데이터 접근: 데이터 포인터 또는 동등한 구현입니다. 데이터 경로에서 불필요한 모든 복사를 가능한 한 제거하는 것이 좋습니다. HandleRenderFrameData에서 EasyAR는 데이터를 한 부 복사한 뒤 비동기적으로 사용합니다. 해당 동기 호출이 완료되면 이미지 데이터는 더 이상 사용되지 않습니다. 데이터 소유권에 주의하십시오.

타임스탬프:

  • 모든 타임스탬프는 시계 동기화되어야 하며, 가능하면 하드웨어 동기화가 좋습니다. 데이터 단위는 초이지만 정밀도는 나노초 또는 가능한 한 높아야 합니다.

트래킹 상태:

  • 트래킹 상태는 디바이스가 정의하며, VIO 를 사용할 수 없는 트래킹 손실 상태를 포함해야 합니다. 더 많은 등급이 있으면 더 좋습니다.

디바이스 pose:

  • 3D 엔진의 가상 카메라 transform 을 포함한 모든 pose 는 동일한 원점을 사용해야 합니다.
  • 모든 pose 및 extrinsics 는 동일한 좌표축 시스템을 사용해야 합니다.
  • Unity 에서 pose 데이터의 좌표축 시스템 유형은 Unity 좌표축 시스템 또는 EasyAR 좌표축 시스템이어야 합니다. input extension 이 EasyAR 에 의해 구현되고 다른 좌표축 시스템 정의를 사용하는 경우, 명확한 좌표축 시스템 정의 또는 Unity 좌표축 시스템이나 EasyAR 좌표축 시스템으로 변환하는 방법을 제공해야 합니다.
  • Unity 에서 Unity XR framework 를 사용하는 경우 XROrigin.TrackingOriginMode.Device 모드와 호환되면 충분합니다.

Intrinsics:

  • 모든 값은 이미지 데이터와 일치해야 합니다. 필요한 경우 EasyAR 에 입력하기 전에 intrinsics 를 스케일링해야 합니다.
  • input extension 이 EasyAR 에 의해 구현되는 경우 intrinsics 가 매 프레임 변화하는지 설명해야 합니다. 이는 해당 API 를 한 번 호출할지 매 프레임 호출할지를 결정합니다.

Extrinsics:

  • 헤드셋에서는 실제 데이터를 제공해야 합니다.
  • 이는 물리 카메라가 디바이스/헤드의 pose 원점에 대해 가지는 물리적 오프셋을 표현하는 캘리브레이션 행렬입니다. 디바이스 pose 와 물리 카메라 pose 가 같다면 단위 행렬이어야 합니다.
  • Apple Vision Pro 의 해당 인터페이스는 CameraFrame.Sample.Parameters.extrinsics입니다. 그 데이터 정의는 인터페이스가 요구하는 데이터와 다르며, EasyAR 내부에서는 변환 후 사용된다는 점에 유의해야 합니다.
  • Unity 에서 extrinsics 의 좌표축 시스템 유형은 Unity 좌표축 시스템 또는 EasyAR 좌표축 시스템이어야 합니다. input extension 이 EasyAR 에 의해 구현되고 다른 좌표축 시스템 정의를 사용하는 경우, 명확한 좌표축 시스템 정의 또는 Unity 좌표축 시스템이나 EasyAR 좌표축 시스템으로 변환하는 방법을 제공해야 합니다.
  • 헤드셋 디바이스에는 일반적으로 원점, 방향, 좌수/우수 표현 등이 서로 다른 여러 좌표계가 존재합니다. Extrinsics 는 동일한 좌표계에서 계산해야 합니다. 이 인터페이스 데이터는 서로 다른 정의의 두 좌표계 간 변환 행렬이 아니라 동일 좌표계 내 좌표 변환이 필요합니다.

성능:

  • 데이터는 최적의 효율로 제공되어야 합니다. 대부분의 구현에서 API 호출은 렌더링 과정에서 발생하므로, 하위 계층에서 시간이 걸리는 작업이 필요하더라도 API 호출을 차단하지 않거나 이러한 API 를 합리적인 방식으로 사용하는 것이 좋습니다.
  • input extension 이 EasyAR 에 의해 구현되는 경우 시간이 걸리는 모든 API 호출을 설명해야 합니다.

멀티 카메라:

  • 최소 한 대의 카메라 데이터가 필요합니다. 이 카메라는 RGB 카메라, VST 카메라, 로컬라이제이션 카메라 등 어느 것이든 가능합니다. 헤드셋에서 한 대의 카메라 데이터만 입력하는 경우 일반적으로 중앙 또는 눈 근처의 RGB 카메라나 VST 카메라 사용을 권장합니다.
  • 멀티 카메라를 사용하면 EasyAR 알고리즘 효과를 향상시킬 수 있습니다. 사용 가능한 모든 카메라의 특정 시점 카메라 프레임 데이터는 동일한 시점에 동시에 입력되어야 합니다.

멀티 카메라는 현재 아직 완전히 지원되지 않습니다. 자세한 내용은 EasyAR 에 문의하십시오.

다음 단계

관련 항목

  • EasyAR 좌표계
  • 이미지 입력 확장 샘플 Workflow_FrameSource_ExternalImageStream