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.
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 usandocap.set(cv2.CAP_PROP_POS_MSEC)
. La posición devuelta porcap.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 porcap.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 decv2.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:
Esto debería permitirte leer frames con precisión entre las marcas de tiempo especificadas.