アイキャッチ画像

Pythonで動画から静止部分を抜き出してみた

Pythonで、動画ファイルの中から静止している部分を選んで静止画として抜き出してみました。

目次

  1. 動画から静止画を切り出したい
  2. 動画から静止部分を取り出す手順
  3. コード
  4. 実施例

動画から静止画を切り出したい

iPadで「へのへのもへじ」を描いた動画を撮りました。動画を撮る際に、1画毎に数秒静止するようにしました。この動画から、Pythonを使って静止部分を静止画として抜き出してみたいと思います。

これが出来ると、アプリの操作説明の資料が作りやすくなるかもしれません。

動画から静止部分を取り出す手順

PythonでOpenCVを使用します。

OpenCVで1フレームずつ読み取りをして、前後のフレームを画像として比較して、特定の期間の間に変化がない場合にそのフレームを静止画として出力するようにします。

画像が変化しているかどうかは、下記の手順で判定します。

  1. フレームをグレースケールに変換する。
  2. 前のフレーム(グレースケール)との差分画像を作る。
  3. 差分画像の各ピクセルのうち最大値を調べる。
  4. 差分の最大値が閾値より小さければ、画像は変化していないものとする。

コード

下記のようなコードにしました。入力はMP4、出力はPNGです。

import cv2
import sys
import numpy as np
import argparse

# コマンドライン引数の設定
DESC = 'Pick up stop scene, and out put the frame as PNG image.'
parser = argparse.ArgumentParser(description=DESC)
parser.add_argument('fname', help='MP4 Video file name.')
parser.add_argument('--threshold', default=10, type=int, help='Threshold of changed.')
parser.add_argument('--duration', default=2, type=int, help='Duration frames to stop.')
args = parser.parse_args()

# ビデオデータの読み込み
video_data = cv2.VideoCapture(args.fname)
if video_data.isOpened() == False:
    print('Video file is not opened.')
    sys.exit()

# ビデオのフレーム数を調べる
frame_count = video_data.get(cv2.CAP_PROP_FRAME_COUNT)
print('Number of frames : ', frame_count)

# 静止画像の抜き出し
ret, prev_frame = video_data.read()
prev_frame_gray = cv2.cvtColor(prev_frame, cv2.COLOR_BGR2GRAY)
stop_counter = 0
while True:
    ret, frame = video_data.read()
    if ret:
        frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        frame_diff = cv2.absdiff(prev_frame_gray, frame_gray)
        frame_distance = np.max(frame_diff)
        if frame_distance < args.threshold:
            if stop_counter == args.duration:
                c = video_data.get(cv2.CAP_PROP_POS_FRAMES)
                cv2.imwrite( str(int(c)) + '.png', frame)
                stop_counter = stop_counter + 1
            else:
                stop_counter = stop_counter + 1
        else:
            stop_counter = 0
        prev_frame_gray = frame_gray
    else:
        break

# ビデオファイルの解放
video_data.release()

Python環境にNumPyとOpenCVをインストールしておく必要があります。

コマンドライン引数で、ファイル名といくつかの閾値の設定が出来るようにしてみました。閾値の指定をしない場合は、デフォルト値が使われます。

実施例

試してみます。

> python test.py test.mp4

出力される画像は、こんな感じになります。

出力画像01 出力画像02 出力画像03 出力画像04 出力画像05 出力画像06 出力画像07 出力画像08 出力画像09 出力画像10 出力画像11

まずまず、1画ずつの画像になりました。

広告

作ってみたカテゴリの投稿