openCVでgif動画をループして再生する方法


Background

現在自作でマイナーなOpenCVを紹介するwebページを作成しています。
https://featurepoints.jp/opencv_doc/

で、データセットとして GIFMAGAZINからGIFをMP4に変換して画像処理をしているのですが、そのままcv2.imshow("window name", mat) で動画再生しようとするとブラウザ表示のようにループして繰り返し表示はせずに短い時間で終了します。

ここでは、cv2.imshow()を使って動画再生をループさせる方法を書いてみようと思います。

gif to mp4

gifからmp4に変換する方法ですが、2つあります。ひとつはgifをブラウザで表示させて右クリックで「名前を付けて動画で保存」を選んで変換する方法です。あともうひとつはffmpegを使って変換する方法です。(FFmpegでgifアニメをmp4に変換する 参照)

ffmpeg -i [gif ファイルパス]  -movflags faststart -pix_fmt yuv420p -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" [mp4 ファイルパス] 

Method

繰り返し表示させる方法は、
1. 一度動画を再生し、すべてのフレームを配列に格納する
2. 無限ループの中に動画を再生
3. 処理中に終了条件を設定
とすればいいです。

Development

[ESC]で動画が終了しますが、[S]を押すとフレーム画像を保存することができます。

import numpy as np
import cv2
import argparse

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--src')
    args = parser.parse_args()

    cap = cv2.VideoCapture(args.src)
    fps = cap.get(cv2.CAP_PROP_FPS)
    frames = []

    #一度動画を再生して、フレームを配列に格納する
    while cap.isOpened():
        _ret, frame = cap.read()        
        if frame is None:
            break
        frames.append(frame)
    cap.release()

    end = False
    while True:
        if end:
            break
        for frame in frames:
            cv2.imshow("loop a gif",frame)

            k = cv2.waitKey(int(fps)) & 0xFF

            # ESC で終了
            if k == 27:
                end = True
                break
            # S で画像保存
            elif k == ord("s"):
                cv2.imwrite("output.png", frame)

if __name__ == '__main__':
    main()

Consequence

Afterword

動画(画像)データはせんとくんを止めろ!GIFゲームを使ってみました。タイミングよくSボタンを押すと"nice"と表示された画像が保存されます。結構捉えるが難しいです。
お手すきの時間にどうぞ