Elsaの技術日記(徒然なるままに)

主に自分で作ったアプリとかの報告・日記を記載

MENU

OpenCVで特定時間から動画再生や早送り・巻き戻し

OpenCVで動画再生方法の記事はいくつか投稿していたのですが、
そういえば、初めから再生させる方法しか知らなかったな!!と思い調べてみました!!
今回は忘れないように備忘録として残しておこうと思います。



■環境

 ・使用言語:Python3
 ・OS:WIndows(anaconda)

■動画の途中から再生する方法

OpenCVで動画の途中から再生する方法ですが、
再生したいフレーム番号(数)をセットしてからフレームを読み出していけばOKです!!

全体のコードはこちら。

if __name__ == '__main__':
    cap = cv2.VideoCapture('ファイルパス')

    if (cap.isOpened()== False):
        print("File Open Error") 

    fps = int(cap.get(cv2.CAP_PROP_FPS))

    FPS = 1/(fps*1)
    cap.set(cv2.CAP_PROP_POS_FRAMES, 読み出したいフレーム番号(数))
    while(cap.isOpened()):
        ret, frame2 = cap.read()
        if ret == True:
            frame = cv2.resize(frame2 , (int(960/2), int(540/2)))

            cv2.imshow("Video", frame)
            if cv2.waitKey(1) & 0xFF == ord('q'): 
                break
            time.sleep(FPS)
        else:
            print("Cap Read Error")

    cap.release()

    cv2.destroyAllWindows()

重要なのは、

cap.set(cv2.CAP_PROP_POS_FRAMES, 読み出したいフレーム番号(数))

で、VideoCaptureで読み出した動画データのフレームプロパティ(CAP_PROP_POS_FRAMES)にset関数でフレーム数をセットする。
です。
逆に言えばこれだけです。

フレーム数のセットですので時間換算で考える場合にはFPSから計算してください。
動画データのFPSを取得する場合には、

cap.get(cv2.CAP_PROP_FPS)

を用いればOKです。
今回、FPSをint型で取得したいので

fps = int(cap.get(cv2.CAP_PROP_FPS))

といたしました。

■動画早送り

この、

cap.set(cv2.CAP_PROP_POS_FRAMES, 読み出したいフレーム番号(数))

を用いると早送り・巻き戻しが出来ます。

まずは動画早送り方法です。
コードはこちら。

if __name__ == '__main__':
    cap = cv2.VideoCapture('Forest - 49981.mp4')

    if (cap.isOpened()== False):
        print("File Open Error") 

    fps = int(cap.get(cv2.CAP_PROP_FPS))
    counter = 0
    speed = 10
    FPS = 1/(fps*1)
    cap.set(cv2.CAP_PROP_POS_FRAMES, 1000)
    while(cap.isOpened()):
        cap.set(cv2.CAP_PROP_POS_FRAMES, counter)

        ret, frame2 = cap.read()
        counter+=speed

        if ret == True:
            frame = cv2.resize(frame2 , (int(960/2), int(540/2)))

            cv2.imshow("Video", frame)
            if cv2.waitKey(1) & 0xFF == ord('q'): 
                break
            time.sleep(FPS)
        else:
            print("Cap Read Error")

    cap.release()

    cv2.destroyAllWindows()

実施していることは、

    while(cap.isOpened()):
        cap.set(cv2.CAP_PROP_POS_FRAMES, counter)

        ret, frame2 = cap.read()
        counter+=speed

で、counter変数にセットされたフレーム数をset関数で動画データのプロパティにセットし、そこのフレームを読み込むことを繰り返しております。
ここでcounter変数にはspeedにセットされた値分だけ増加するコードになっているため、次に読み出すフレームはspeed分だけ加算された数になります。
要するにspeedが10であった場合には、
1⇒11⇒21⇒・・・
といった形で飛び飛びのフレームが読み込まれるようになっている、ということです。
このため、speed分だけ倍速で動画が再生されることになるので早送りのような動画再生が可能になる、というわけです。

一応、

time.sleep(FPS)

の値を短くしても早送りは出来るのですが、、、
読み出し速度や処理速度がネックになり早送りに限界があります。
一方こちらの方法ですと読み込むフレーム数を飛ばしただけ高速で再生できるため何倍にも早送りが出来ます。

■動画巻き戻し

次に動画の巻き戻しです。
と言っても察しの良い方はすぐに分かるかと思います。
そう!!
やることはセットするフレーム数を引き算していけばよいだけです!!
コードはこちら。

if __name__ == '__main__':
    cap = cv2.VideoCapture('Forest - 49981.mp4')

    if (cap.isOpened()== False):
        print("File Open Error") 

    frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
    fps = int(cap.get(cv2.CAP_PROP_FPS))
    counter = frame_count
    speed = 10
    FPS = 1/(fps*1)
    cap.set(cv2.CAP_PROP_POS_FRAMES, 1000)
    while(cap.isOpened()):
        cap.set(cv2.CAP_PROP_POS_FRAMES, counter)

        ret, frame2 = cap.read()
        counter-=speed

        if ret == True:
            frame = cv2.resize(frame2 , (int(960/2), int(540/2)))

            cv2.imshow("Video", frame)
            if cv2.waitKey(1) & 0xFF == ord('q'): 
                break
            time.sleep(FPS)
        else:
            print("Cap Read Error")

    cap.release()

    cv2.destroyAllWindows()

counter変数に全フレーム数であるframe_countを格納し

    while(cap.isOpened()):
        cap.set(cv2.CAP_PROP_POS_FRAMES, counter)

        ret, frame2 = cap.read()
        counter-=speed

といった形でspeed分だけフレーム数を差し引いています。
この方法により、
100⇒90⇒80⇒・・・
といった形でフレーム数が差し引かれて読み出されるため巻き戻し再生が行える、というわけです。

■実際に動かしてみる

では実際に比較させてみたいと思います。
結果はこちら。
【通常】
f:id:Elsammit:20210503225142g:plain

【早送り(10倍速)】
f:id:Elsammit:20210503225020g:plain

【巻き戻し(2倍速)】
f:id:Elsammit:20210503224837g:plain

■最後に

今回はフレーム数を指定した特定時間からの動画再生や早送り・巻き戻しについてまとめてみました。
OpenCVを用いると動画早送りや巻き戻しが簡単に行えるのでとても便利だな!!と思いました。

簡単なビデオプレーヤーぐらいなら作れそうなので今度作ってみようかな??