외부 프레임 데이터 소스의 입력 프레임 데이터 요구 사항
외부 프레임 데이터 소스가 정상적으로 동작하게 하려면 가장 중요하면서도 가장 까다로운 작업은 데이터의 정확성을 보장하는 것입니다. 이 문서에서는 외부 프레임 데이터 소스의 입력 프레임 데이터 요구 사항을 설명합니다.
시작하기 전에
- 카메라와 입력 프레임 등의 기본 개념을 이해합니다.
- 외부 프레임 데이터 소스의 기본 개념과 일반적인 유형을 이해합니다.
입력 프레임 데이터 유형
Unity에서 외부 프레임 데이터 소스는 일반적으로 서로 다른 두 시점에 서로 다른 데이터를 받아야 합니다. 외부 데이터의 입력 시점과 데이터 특성에 따라 이 두 데이터 그룹을 다음과 같이 부릅니다.
- 카메라 프레임 데이터(camera frame data)
- 렌더링 프레임 데이터(rendering frame data)
외부 프레임 데이터 소스의 유형에 따라 이 두 데이터 그룹에 대한 요구 사항은 다릅니다.
- 이미지 및 디바이스 모션 데이터 입력 확장: 카메라 프레임 데이터와 렌더링 프레임 데이터가 모두 필요
- 이미지 입력 확장: 카메라 프레임 데이터만 필요
카메라 프레임 데이터
데이터 요구 사항:
- timestamp
- 원시 물리 카메라 이미지 데이터(raw camera image data)
- 내부 파라미터(intrinsics, 이미지 크기, 초점 거리, 주점을 포함합니다. 왜곡이 있는 경우 왜곡 모델과 왜곡 파라미터도 필요합니다)
- 외부 파라미터(extrinsics, Tcw 또는 Twc, 물리 카메라가 디바이스/머리 pose origin에 대해 갖는 물리적 오프셋을 표현하는 보정된 행렬)
- 추적 상태(tracking status)
- 디바이스 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 렌더링
데이터 요구 사항:
- Timestamp
- Tracking status
- 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