Table of Contents

Requisitos de datos del fotograma de entrada para fuentes de datos de fotogramas externas

Para que una fuente de datos de fotogramas externa funcione correctamente, la tarea más importante y también la parte más difícil es garantizar que los datos sean correctos. Este artículo describe los requisitos de datos del fotograma de entrada para fuentes de datos de fotogramas externas.

Antes de empezar

Tipos de datos del fotograma de entrada

En Unity, una fuente de datos de fotogramas externa suele necesitar recibir datos diferentes en dos momentos distintos. Según el momento de entrada y las características de los datos externos, estos dos grupos de datos se denominan:

  1. datos del fotograma de cámara (camera frame data)
  2. datos del fotograma de renderizado (rendering frame data)

Los distintos tipos de fuentes de datos de fotogramas externas tienen requisitos diferentes para estos dos grupos de datos:

  • Extensión de entrada de datos de imagen y movimiento del dispositivo: requiere tanto datos del fotograma de cámara como datos del fotograma de renderizado
  • Extensión de entrada de imagen: solo requiere datos del fotograma de cámara

Datos del fotograma de cámara

Requisitos de datos:

  1. timestamp
  2. datos de imagen sin procesar de la cámara física (raw camera image data)
  3. intrínsecos (intrinsics, incluidos tamaño de imagen, distancia focal y punto principal. Si hay distorsión, también se requieren el modelo y los parámetros de distorsión)
  4. extrínsecos (extrinsics, Tcw o Twc, matriz calibrada que expresa el desplazamiento físico de la cámara física respecto al origin de pose del dispositivo/cabeza)
  5. estado de seguimiento (tracking status)
  6. pose del dispositivo (device pose)

Tiempo de los datos:

  • Punto medio de la exposición de la cámara física

Uso de los datos:

  • Tiempo de llamada de API: puede cambiar según el diseño del código externo. Un método común usado por la mayoría de los dispositivos es consultar durante la actualización de renderizado del motor 3D y luego decidir, según el timestamp de los datos del dispositivo, si se requiere más procesamiento
  • Hilo de llamada de API: el game thread del motor 3D, o cualquier otro hilo si todas las API externas utilizadas son thread-safe

El ejemplo de llamada de API en Unity es el siguiente:

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

Renderizar frame data

Requisitos de datos:

  1. Timestamp
  2. Tracking status
  3. Device pose

Tiempo de los datos:

  • Momento en que el fotograma se presenta en pantalla. TimeWarp no se incluye. Los datos de device pose del mismo momento serán usados externamente, por ejemplo por el device SDK, para establecer el transform de la cámara virtual al renderizar el fotograma actual.
Nota

TimeWarp, a veces llamado también Reprojection o ATW/PTW, es una técnica común en visores VR/AR para reducir la latencia. Después de completar el renderizado, vuelve a deformar la imagen según la pose de cabeza más reciente para compensar el movimiento de cabeza producido durante el renderizado. EasyAR necesita el momento correspondiente a la pose usada para configurar la cámara virtual al inicio del renderizado, no el momento real de presentación en pantalla después de TimeWarp.

Uso de los datos:

  • Tiempo de llamada de API: cada fotograma de renderizado del motor 3D
  • Hilo de llamada de API: el game thread del motor 3D

El ejemplo de llamada a la API en Unity es el siguiente:

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

Detalles de los requisitos de datos

Datos de imagen de la cámara física:

  • Sistema de coordenadas de imagen: los datos adquiridos cuando el sensor está horizontal también deben ser horizontales. Los datos deben usar la esquina superior izquierda como origin y almacenarse en orden row-major. La imagen no debe reflejarse ni invertirse.
  • FPS de imagen: son aceptables datos normales de 30 o 60 fps. Si un fps alto tiene un impacto especial, la velocidad de fotogramas mínima aceptable para obtener un resultado de algoritmo razonable es 2. Se recomienda usar fps superiores a 2; normalmente basta con usar la velocidad de fotogramas original de los datos.
  • Tamaño de imagen: para obtener mejores resultados de cálculo, el lado más largo debe ser 960 o mayor. Normalmente no se recomienda realizar escalado de imagen costoso en la cadena de datos. Se recomienda usar directamente los datos originales, salvo que el tiempo de copia de los datos de tamaño completo ya sea inaceptablemente largo. La resolución de imagen no puede ser menor que 640*480.
  • Formato de píxel: priorizando el efecto de seguimiento y considerando el rendimiento, el orden de preferencia habitual es YUV > RGB > RGBA > Gray (el componente Y de YUV). Al usar datos YUV, se requiere una definición completa de los datos, incluidos detalles de empaquetado y padding. En comparación con imágenes de un solo canal, las imágenes en color ofrecen mejores resultados de Mega, pero afectan poco a otras funciones.
  • Acceso a datos: puntero de datos o una implementación equivalente. Es mejor eliminar todas las copias no necesarias posibles en la cadena de datos. En HandleRenderFrameData, EasyAR copia una copia de los datos y luego la usa de forma asíncrona. Una vez finalizada la llamada síncrona, los datos de imagen ya no se usan. Preste atención a la propiedad de los datos.

Marcas de tiempo:

  • Todas las marcas de tiempo deben estar sincronizadas por reloj, preferiblemente por hardware. La unidad de datos es segundos, pero la precisión debe llegar a nanosegundos o ser lo más alta posible.

Estado de tracking:

  • El estado de tracking lo define el dispositivo y debe incluir el estado de pérdida de tracking, cuando VIO no está disponible. Si hay más niveles, mejor.

Pose del dispositivo:

  • Todas las pose, incluido el transform de la cámara virtual en el motor 3D, deben usar el mismo origen.
  • Todas las pose y extrinsics deben usar el mismo sistema de ejes de coordenadas.
  • En Unity, el tipo de sistema de ejes de coordenadas de los datos de pose debe ser el sistema de ejes de coordenadas de Unity o el de EasyAR. Si la input extension está implementada por EasyAR y usa otra definición de sistema de ejes de coordenadas, proporcione una definición clara del sistema o un método para convertirlo al sistema de ejes de Unity o de EasyAR.
  • En Unity, si se usa el framework Unity XR, basta con ser compatible con el modo XROrigin.TrackingOriginMode.Device.

Intrinsics:

  • Todos los valores deben coincidir con los datos de imagen. Si es necesario, escale los intrinsics antes de introducirlos en EasyAR.
  • Si la input extension está implementada por EasyAR, indique si los intrinsics cambian en cada frame, ya que esto determina si el API correspondiente debe llamarse una vez o en cada frame.

Extrinsics:

  • En visores deben proporcionarse datos reales.
  • Es una matriz de calibración que expresa el offset físico de la cámara física con respecto al origen de pose del dispositivo/cabeza. Si la pose del dispositivo y la pose de la cámara física son iguales, debe ser una matriz identidad.
  • La interfaz correspondiente de Apple Vision Pro es CameraFrame.Sample.Parameters.extrinsics. Tenga en cuenta que su definición de datos difiere de los datos requeridos por la interfaz, y EasyAR la usa internamente después de la conversión.
  • En Unity, el tipo de sistema de ejes de coordenadas de extrinsics debe ser el sistema de Unity o el de EasyAR. Si la input extension está implementada por EasyAR y usa otra definición de sistema de ejes, proporcione una definición clara o un método para convertirla al sistema de Unity o EasyAR.
  • En dispositivos tipo visor suelen existir varios sistemas de coordenadas con definiciones diferentes, incluidas diferencias de origen, orientación y representación de mano izquierda/derecha. Los extrinsics deben calcularse dentro del mismo sistema de coordenadas. Los datos de esta interfaz requieren una transformación de coordenadas dentro del mismo sistema, no una matriz de transformación entre dos sistemas con definiciones distintas.

Rendimiento:

  • Los datos deben proporcionarse con eficiencia óptima. En la mayoría de implementaciones, las llamadas API ocurren durante el renderizado, por lo que, incluso si se requieren operaciones costosas en la capa inferior, no bloquee las llamadas API, o use estas API de forma razonable.
  • Si la input extension está implementada por EasyAR, describa todas las llamadas API que consumen tiempo.

Multi-cámara:

  • Se requieren datos de al menos una cámara. Puede ser una cámara RGB, VST, de localización, etc. En visores, si solo se introducen datos de una cámara, normalmente se recomienda usar una cámara RGB o VST situada en el centro o cerca de los ojos.
  • Usar varias cámaras puede mejorar el resultado del algoritmo EasyAR. Los datos de frame de todas las cámaras disponibles en un momento determinado deben introducirse simultáneamente en el mismo punto temporal.

Multi-cámara aún no está completamente soportado. Contacte con EasyAR para más detalles.

Siguientes pasos

Temas relacionados