web-dev-qa-db-ja.com

ビデオの各フレームのタイムスタンプを取得する

Android 5.2で作成したアプリケーションを使用して、タブレットのフロントカムから複数のビデオを記録しました。各ビデオの開始タイムスタンプをミリ秒(Unix時間)で保存しました。

残念ながら、各ビデオのフレームレートは異なります(20〜30の範囲)。 OpenCVを使用すると、各ビデオのフレームレートを取得できます。

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

これはうまく機能し、理論的には、ビデオの各フレームに1000/fps(ミリ秒)を追加することができます。ただし、これは録画全体を通してフレームレートが安定していることを前提としています。これが事実かどうかはわかりません。

Pythonに、フレームレートに関係なくビデオの各フレームのタイムスタンプ(ミリ秒単位)を取得する可能性はありますか?

9
machinery

cv2.CAP_PROP_POS_MSECが必要です。さまざまなキャプチャプロパティをすべて表示します here

編集:実際、 DanMašek が指摘したように、そのプロパティを取得すると、OpenCVは 正確にその計算を行う のように見えます(少なくともFFMPEGを使用していると仮定します) ):

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

したがって、常に一定のフレームレートの仮定に依存するようです。ただし、一定のフレームレートを想定しても、1000/fpsを追加し続けるだけでなく、フレーム番号を掛けることが重要です。フロートを繰り返し追加するとエラーが発生し、長いビデオで大きな違いが生じる可能性があります。例えば:

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))

フレーム0の差:0.0
フレーム1の差:0.0
フレーム2の差:0.0
フレーム3の違い:1.4210854715202004e-14
フレーム4の違い:0.011111111111091532
フレーム5の違い:0.011111111111091532
フレーム6の違い:0.011111111111091532
フレーム7の違い:0.011111111111119953
フレーム8の違い:0.022222222222183063
フレーム9の違い:0.022222222222183063
...
フレーム294の違い:0.8111111111411446

これはもちろんミリ秒単位であるため、それほど大きくはないようです。しかし、ここでは計算で1msほど遅れています。これは、11秒のビデオのためだけです。とにかく、このプロパティを使用する方が簡単です。

14
alkasm