Saltar al contenido

Retraso de OpenCV VideoCapture debido al búfer de captura

Nuestros mejores investigadores han agotado sus depósitos de café, buscando todo el tiempo por la respuesta, hasta que Julian halló el arreglo en Bitbucket por lo tanto hoy la compartimos contigo.

Solución:

Solución OpenCV

De acuerdo con esta fuente, puede establecer el tamaño de búfer de un cv::VideoCapture objeto.

cv::VideoCapture cap;
cap.set(CV_CAP_PROP_BUFFERSIZE, 3); // internal buffer will now store only 3 frames

// rest of your code...

Sin embargo, existe una limitación importante:

CV_CAP_PROP_BUFFERSIZE Cantidad de fotogramas almacenados en la memoria intermedia interna (nota: solo compatible con el backend DC1394 v 2.x actualmente)

Actualizar desde los comentarios. En las versiones más nuevas de OpenCV (3.4+), la limitación parece haber desaparecido y el código usa enumeraciones con ámbito:

cv::VideoCapture cap;
cap.set(cv::CAP_PROP_BUFFERSIZE, 3);

truco 1

Si la solución no funciona, echa un vistazo a esta publicación que explica cómo solucionar el problema.

En pocas palabras: se mide el tiempo necesario para consultar un marco; si es demasiado bajo, significa que el marco se leyó del búfer y se puede descartar. Continúe consultando fotogramas hasta que el tiempo medido exceda un cierto límite. Cuando esto sucede, el búfer estaba vacío y el marco devuelto está actualizado.

(La respuesta en la publicación vinculada muestra: devolver un cuadro desde el búfer toma aproximadamente 1/8 del tiempo de devolver un cuadro actualizado. ¡Su millaje puede variar, por supuesto!)


truco 2

Una solución diferente, inspirada en esta publicación, es crear un tercer subproceso que tome fotogramas continuamente a alta velocidad para mantener el búfer vacío. Este hilo debería usar el cv::VideoCapture.grab() para evitar sobrecargas.

Podría usar un bloqueo de giro simple para sincronizar los marcos de lectura entre el subproceso de trabajo real y el tercer subproceso.

Chicos, esta es una solución bastante estúpida y desagradable, pero la respuesta aceptada no me ayudó por algunas razones. (Código en python pero la esencia bastante clara)

# vcap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
data = np.zeros((1140, 2560))
image = plt.imshow(data)

while True:
    vcap = cv2.VideoCapture("rtsp://admin:@192.168.3.231")
    ret, frame = vcap.read()
    image.set_data(frame)
    plt.pause(0.5) # any other consuming operation
    vcap.release()

Puede asegurarse de que agarrar el marco tomó un poco de tiempo. Es bastante simple de codificar, aunque un poco poco confiable; potencialmente, este código podría conducir a un interbloqueo.

#include 
using clock = std::chrono::high_resolution_clock;
using duration_float = std::chrono::duration_cast>;
// ...
while (1) 
    TimePoint time_start = clock::now();
    camera.grab();
    if (duration_float(clock::now() - time_start).count() * camera.get(cv::CAP_PROP_FPS) > 0.5) 
        break;
    

camera.retrieve(dst_image);

El código usa C++11.

Si haces scroll puedes encontrar los comentarios de otros desarrolladores, tú además tienes la habilidad insertar el tuyo si te gusta.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *