¿Cómo "sincronizar" mejor al productor/consumidor de imágenes para manejar diferentes FPS?

Estoy construyendo un sistema que, entre otras cosas, tiene un sensor de imagen que emite video digital a 30 fps y un sistema de visualización que muestra en un monitor a 60 fps. Actualmente, el sistema utiliza un controlador de búfer de cuadros que he implementado en una FPGA y en una memoria fuera de chip. El lector (monitor) lee del búfer a voluntad y el escritor (cámara) bombea datos al búfer a voluntad (es un controlador totalmente asíncrono). Hay suficiente memoria para almacenar algunos marcos de datos. El sistema funciona bien. Puedo mostrar la transmisión de video de la cámara en un monitor sin problemas.

El problema al que me enfrento es que el lector/escritor tiene diferentes frecuencias/resoluciones de reloj y, por lo tanto, diferentes fps. Lo que esto implica es que en algún momento el monitor muestra datos del marco de imagen actual, pero debido a que consume datos más rápido de lo que la cámara produce datos, "supera" la cámara y comienza a mostrar datos de un marco de cámara obsoleto. Esto está bien siempre que la cámara no se mueva muy rápido o que se tome la misma escena una y otra vez. Sin embargo, si la cámara se mueve rápidamente o algo en la escena se mueve rápidamente (por ejemplo, las cosas en la escena se mueven más rápido que la frecuencia de muestreo de la cámara), entonces está claro que el cuadro actual será sustancialmente diferente del cuadro anterior. Eso significa que el monitor puede mostrar porciones de ambos cuadros al mismo tiempo, lo que se manifiesta en una línea "

Entonces, yendo a mi pregunta, me pregunto cuál es la mejor manera de resolver este problema. El monitor y la cámara tienen dos relojes independientes, que son asíncronos entre sí. Tengo el control (yo genero) el reloj de píxeles para el monitor, pero el reloj de píxeles de la cámara es 100% asíncrono con el sistema (sale de un IC deserializador). Algunos detalles más: el FPGA tiene una frecuencia de 100 MHz desde un oscilador. Utilizo un DCM interno para generar el reloj de píxeles de 40 MHz para el monitor y tengo varias otras piezas del sistema funcionando a 100MHz. El reloj de píxeles de la cámara es de unos 13 MHz (pero puede llegar hasta los 27 MHz). El FPS de la cámara generalmente está atascado en 30 FPS, pero puede ir más lento dependiendo del control de exposición.

Podría hacer algo como mostrar siempre el mismo cuadro dos veces para que el monitor esté haciendo 60 fps, pero 30 cuadros distintos por segundo. Eso funcionaría bien, pero si alguna vez cambio la velocidad de fotogramas de la cámara a algo arbitrario que no se divide bien en 60, no tendré suerte. Quizás lo más importante es que si cambio los fps de mi monitor, esto funciona mal. Como una extensión más robusta de esta idea, podría pensar en formas de mostrar solo "fotogramas completos". En otras palabras, no comience a leer un nuevo cuadro de imagen hasta que esté completamente escrito (o más sólidamente hasta que sepa que no va a pasar la cámara en ese cuadro). Esto significaría que no todos los marcos de imagen obtienen la misma cantidad de marcos de visualización, pero tal vez esté bien.

¿Alguna sugerencia? ¿Cómo manejan típicamente los sistemas comerciales este problema? En particular, ¿cómo manejan esto las cámaras USB? Eso parece un análogo bastante apropiado. Presumiblemente, transmiten datos a un búfer en el lado de la máquina y el software de visualización tiene que procesar los datos/volcarlos en el controlador de gráficos (estoy pensando en algo así como una llamada a glutswapbuffers).

Respuestas (2)

En programación, esta técnica se denomina doble almacenamiento en búfer. Tienes dos buffers de memoria entre la cámara y el monitor. Mientras la cámara llena uno de ellos, el otro se muestra en el monitor (cualquiera que sea el tiempo que cueste, 1, 2 o más fotogramas). Cuando el primer búfer está lleno (se lee todo el cuadro de la cámara), los dos búferes se intercambian y el segundo búfer ahora se lee de la cámara y el primero se muestra en el monitor.

De esta forma, algunos de los fotogramas de la cámara se mostrarán con 2 fotogramas de monitor de largo, algunos solo 1 (si la cámara es más rápida que la mitad de la velocidad de fotogramas del monitor) o 3 fotogramas del monitor (si la cámara es más lenta que la mitad de la velocidad de fotogramas del monitor). ) pero la sincronización se proporcionará automáticamente.

Espero que esta explicación sea lo suficientemente clara y haya entendido el problema correctamente.

Gracias por la publicacion. Creo que estás describiendo la última solución que propuse. Estoy familiarizado con el almacenamiento en búfer doble en software/búferes de ping-pong en HW. Supongo que mi pregunta con esta opción se relaciona exactamente con lo que estás tocando con el recuento de fama por cuadro de cámara (a lo que me referí cuando dije "no todos los cuadros de imagen obtienen la misma cantidad de cuadros de visualización"). Me pregunto si eso se verá "extraño" a la vista. ¿Hay algún problema de percepción con esta técnica? Simplemente no tengo ninguna intuición de cómo se ve eso a simple vista.
Se verá bien. Solo tenga en cuenta que 30 fps no es muy adecuado para movimientos rápidos. Pero esto no tiene nada en común con el problema discutido.
Genial gracias por tu respuesta Sí, me doy cuenta de que 30 fps no se ven fantásticos, pero la cámara está filmando en condiciones de muy poca luz/restringidas, por lo que el tiempo de cuadro más largo produce una exposición mucho mejor. Si aumento la ganancia de la cámara para obtener 60 fps, la imagen se ve bastante mal. De todos modos te dio un más 1 y la respuesta. ¡Aprecio tu ayuda!

Si necesita hacer todo esto con hardware de video (por ejemplo, sin entrar a una computadora), lo que necesita se llama "sincronizador de cuadros" o sincronización de cuadros. Estos son algunos ejemplos de productos comerciales utilizados en la transmisión de televisión para manejar este problema exacto: http://cobaltdigital.com/products/Frame-Synchronizers . En términos de manejar la sincronización real dentro de un FPGA, hay muchas formas de manejar esto, todas las cuales requieren algún tipo de memoria para almacenar al menos un par de líneas de televisión. En general, la lógica de drop-frame puede ser compleja y depende de muchas cosas (cuánto retraso puede tolerar, qué tan rápido se mueve la escena, etc.). De hecho, puede comprar IP que maneje esto: http://www.cubevisiontech.com/Home_files/CV2000C-2%20Scaler.pdf