es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

cap.set(cv2.CAP_PROP_POS_MSEC) de OpenCV cambia a una marca de tiempo inalcanzable.

Estoy tratando de leer frames desde un cierto tiempo hasta un cierto tiempo, el problema es que justo después de configurarlo para comenzar en 800 milisegundos, por ejemplo:

start_time = 0.8
end_time = 4
MILLISECONDS = 1000
cap.set(cv2.CAP_PROP_POS_MSEC, float(start_time * MILLISECONDS))

Ahora intento comprobar dónde se encuentra con:

cap.get(cv2.CAP_PROP_POS_MSEC)

Lo cual devuelve:

13346.680013346679

y según la documentación de OpenCV aquí, esa bandera significa:

Posición actual del archivo de video en milisegundos.

Lo cual es confuso porque mi video completo dura 4 segundos, es decir, 4000 milisegundos, el fragmento de código completo es:

def load_video(path, start_time, end_time, skip_frames=False):
    MILLISECONDS = 1000
    frame_pos = 0

    cap = cv2.VideoCapture(path)
    cap.set(cv2.CAP_PROP_POS_MSEC, float(start_time * MILLISECONDS))
    frames = []
    try:
        while cap.isOpened() and cap.get(cv2.CAP_PROP_POS_MSEC) <= float(end_time * MILLISECONDS):
            ret, frame = cap.read()
            if not ret:
                break
            # El formato de captura predeterminado de OpenCV es BGR,
            # si se necesita RGB, descomenta esta línea:
            # frame = frame[:, :, [2, 1, 0]]
            frames.append(frame)
            if skip_frames:
                # Si queremos tomar cada 5º frame (donde se documenta una acción).
                frame_pos += 12
                cap.set(cv2.CAP_PROP_POS_FRAMES, frame_pos)

    finally:
        cap.release()
    return np.array(frames)

El punto es leer desde un cierto tiempo hasta un cierto tiempo, pero claramente la segunda condición en el bucle while no se cumple ya que 13346.680013346679 > 4000 desde el principio, y lo más extraño es que ret, frame = cap.read() realmente lee un frame cuando lo ejecuto en el depurador justo antes de pasar al chequeo del bucle while.

Entonces, ¿qué estoy haciendo mal aquí?

P.D.

El archivo de video es .avi y tiene una frecuencia de 60 fotogramas por segundo.

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    El problema aquí es que cap.get(cv2.CAP_PROP_POS_MSEC) no necesariamente te da la posición exacta en milisegundos que has establecido usando cap.set(cv2.CAP_PROP_POS_MSEC). La posición devuelta por cap.get(cv2.CAP_PROP_POS_MSEC) puede estar ligeramente desviada debido a la forma en que los frames de video están codificados, almacenados y leídos por OpenCV.

    En este caso, parece que OpenCV es capaz de leer un frame en la posición especificada por cap.set(cv2.CAP_PROP_POS_MSEC) aunque el valor devuelto por cap.get(cv2.CAP_PROP_POS_MSEC) sea mayor que la duración total del video. Esto probablemente se debe a que la codificación del video permite que los frames se lean ligeramente adelantados a su posición exacta en el tiempo.

    Para leer frames de forma precisa entre marcas de tiempo específicas, puedes usar la propiedad cv2.CAP_PROP_POS_FRAMES en lugar de cv2.CAP_PROP_POS_MSEC. Esta propiedad establece la posición del archivo de video en términos de número de frame en lugar de milisegundos. Puedes calcular el número de frame correspondiente a una marca de tiempo particular basándote en la tasa de frames del video.

    Por ejemplo:

    frame_rate = cap.get(cv2.CAP_PROP_FPS)
    start_frame = int(start_time * frame_rate)
    end_frame = int(end_time * frame_rate)
    cap.set(cv2.CAP_PROP_POS_FRAMES, start_frame)
    
    while cap.isOpened() and cap.get(cv2.CAP_PROP_POS_FRAMES) <= end_frame:
        ret, frame = cap.read()
        # ...
    

    Esto debería permitirte leer frames con precisión entre las marcas de tiempo especificadas.

Comments are closed.