web-dev-qa-db-fra.com

Obtention de l'horodatage de chaque image dans une vidéo

J'ai enregistré plusieurs vidéos de la caméra avant de ma tablette avec une application Android 5.2 que j'ai écrite. J'ai stocké l'horodatage de démarrage en millisecondes (heure Unix) pour chaque vidéo.

Malheureusement, chaque vidéo a une fréquence d'images différente (allant de 20 à 30). Avec OpenCV, je peux obtenir le framerate pour chaque vidéo:

import cv2
video = cv2.VideoCapture(videoFile)
fps = video.get(cv2.CAP_PROP_FPS)

Cela fonctionne bien et théoriquement, je pourrais simplement ajouter 1000/fps (en raison des millisecondes) pour chaque image de la vidéo. Mais cela suppose que le framerate reste stable tout au long de l'enregistrement. Je ne sais pas si c'est le cas.

Y a-t-il une possibilité dans Python pour obtenir l'horodatage (en millisecondes) de chaque image dans la vidéo indépendamment du framerate?

9
machinery

Tu veux cv2.CAP_PROP_POS_MSEC. Voir toutes les différentes propriétés de capture ici .

Edit: En fait, comme Dan Mašek m'a fait remarquer, lorsque vous saisissez cette propriété, il semble que OpenCV soit faisant exactement ce calcul (au moins en supposant que vous utilisez FFMPEG ):

case CV_FFMPEG_CAP_PROP_POS_MSEC:
    return 1000.0*(double)frame_number/get_fps();

Il semble donc que vous allez toujours compter sur une hypothèse de fréquence d'images constante. Cependant, même en supposant une fréquence d'images constante, il est important de multiplier par le nombre d'images et de ne pas simplement ajouter 1000/fps. Des erreurs s'accumulent lorsque vous ajoutez à plusieurs reprises des flottants qui, sur une longue vidéo, peuvent faire une grande différence. Par exemple:

import cv2

cap = cv2.VideoCapture('vancouver2.mp4')
fps = cap.get(cv2.CAP_PROP_FPS)

timestamps = [cap.get(cv2.CAP_PROP_POS_MSEC)]
calc_timestamps = [0.0]

while(cap.isOpened()):
    frame_exists, curr_frame = cap.read()
    if frame_exists:
        timestamps.append(cap.get(cv2.CAP_PROP_POS_MSEC))
        calc_timestamps.append(calc_timestamps[-1] + 1000/fps)
    else:
        break

cap.release()

for i, (ts, cts) in enumerate(Zip(timestamps, calc_timestamps)):
    print('Frame %d difference:'%i, abs(ts - cts))

Différence de l'image 0: 0,0
Différence de la trame 1: 0,0
Différence de trame 2: 0,0
Différence de trame 3: 1.4210854715202004e-14
Différence de trame 4: 0,011111111111091532
Différence de trame 5: 0,011111111111091532
Différence de trame 6: 0,011111111111091532
Différence de la trame 7: 0,011111111111119953
Différence de trame 8: 0,022222222222183063
Différence de la trame 9: 0,022222222222183063
...
Différence entre le cadre 294: 0,8111111111411446

C'est bien sûr en millisecondes, alors peut-être que cela ne semble pas si grand. Mais ici, je suis presque à 1 ms du calcul, et ce n'est que pour une vidéo de 11 secondes. Et de toute façon, l'utilisation de cette propriété est tout simplement plus facile.

14
alkasm