LoginSignup
5
10

More than 3 years have passed since last update.

Python+OpenCVで動画から1秒ずつフレームを切り出す

Last updated at Posted at 2020-01-28

大学で研究する過程で、一般的に役立ちそうだと思ったことをつらつら書きます。
こちらの記事を参考にしています。
上記の記事には動画から全フレームを抽出する、$t_1$秒から$t_2$秒間のフレームを抽出するなどの方法が載っておりますが、本記事では1秒ごとに切り出すという方法を紹介しています。

目的

「動画の分析してみたいけど、動画そのまま扱うの難しくね?:confounded:
「じゃあフレームで切り出せば、画像のタスクに帰着できんじゃね?:open_mouth:
という私の個人的な経験から、動画から1秒ずつフレームを切り出すことが目的です。

前提

以下のディレクトリ構成を想定しています。


|── sample.ipynb
|
|── video
|    └── video_sample.mp4
|     
└── frame
     └── video_sample
           |── image_0000.jpg
           ︙
           └── image_00030.jpg

動画(video_sample.mp4)が30秒の場合は、0秒時点, 1秒時点, ..., 30秒時点の31枚の画像が frame/video_sample下に保存される想定です。

実行環境

  • Windows 10
  • Python 3.7.5
  • OpenCV 4.1.2

OpenCVのインストールはopencv-pythonが参考になります。

実装

引数の説明

  • video_path: フレームを切り抜きたい動画のパス
  • frame_dir: フレームの保存先

コード

sample.ipynb
import cv2
from os import makedirs
from os.path import splitext, dirname, basename, join

def save_frames(video_path: str, frame_dir: str, 
                name="image", ext="jpg"):
    cap = cv2.VideoCapture(video_path)
    if not cap.isOpened():
        return
    v_name = splitext(basename(video_path))[0]
    if frame_dir[-1:] == "\\" or frame_dir[-1:] == "/":
        frame_dir = dirname(frame_dir)
    frame_dir_ = join(frame_dir, v_name)

    makedirs(frame_dir_, exist_ok=True)
    base_path = join(frame_dir_, name)

    idx = 0
    while cap.isOpened():
        idx += 1
        ret, frame = cap.read()
        if ret:
            if cap.get(cv2.CAP_PROP_POS_FRAMES) == 1:  # 0秒のフレームを保存
                cv2.imwrite("{}_{}.{}".format(base_path, "0000", ext),
                            frame)
            elif idx < cap.get(cv2.CAP_PROP_FPS):
                continue
            else:  # 1秒ずつフレームを保存
                second = int(cap.get(cv2.CAP_PROP_POS_FRAMES)/idx)
                filled_second = str(second).zfill(4)
                cv2.imwrite("{}_{}.{}".format(base_path, filled_second, ext),
                            frame)
                idx = 0
        else:
            break

save_frames(".\\video\\video_sample.mp4", ".\\frame")

実行すると、以下のように保存されています。
image.png

結論

動画の扱いって難しい。

5
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
10