現在動画コンテンツはどんどん増えてきていますが、動画の中のある場面を静止画にしたい時、再生画面を単にキャプチャするだけだと画質が粗くなります。ここでは、Pythonで動画に直接アクセスし、静止画を抽出する方法を紹介します。
こんにちは。wat(@watlablog)です。
意外と動画の中から静止画を抽出したいという需要は高いのではないでしょうか?ここではPythonのOpenCVを使って簡単に動画から静止画を抽出する方法を説明します!
動画から静止画を抽出する方法(図解)
今回のプログラムの内容は、簡単にイメージ図で説明すると以下の図のようになります。
動画とは、沢山の静止画の集まりです。そのため、動画ファイルを紐解けば静止画を抽出することは容易です。
しかし、動画を1フレーム毎に全て抽出してしまうと、膨大な静止画ファイルが抽出されてしまいます。また、動画は1フレーム違いで内容の違いは大してありません。無駄なデータを保存しないように間引くことも時には必要です。
では早速Pythonコードの説明をしていきましょう!
動画から静止画を抽出するPythonコード
全コードと解説
以下に動画から静止画を抽出するための全コードを示します。ファイルパスや静止画を保存するフォルダ、動画から何フレーム毎に静止画を保存するかのステップ数、静止画ファイルの拡張子といった引数を設定して実行することでファイルが順次生成されていきます。
抽出の方法は、まず初めにnp.arangeで静止画とするフレーム番号配列を作っておき、forループ中のiがリスト内にあれば保存処理をするというものです。
forループの中に「check = i == ext_index」がありますが、この部分でext_indexとiを比較し、一致していたらTrue、一致していなかったらFalseというブール配列が作成されます。
次のif文の条件式「True in check」は、「check配列の中にTrueが1つでもあればTrue」を意味しているので、この部分で抽出するかしないかを判断しています。是非print文等を挟んだりして確認してみて下さい。
その他はコード内のテキスト説明を参照して下さい。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
import cv2 import numpy as np def m_slice(path, dir, step, extension): movie = cv2.VideoCapture(path) # 動画の読み込み Fs = int(movie.get(cv2.CAP_PROP_FRAME_COUNT)) # 動画の全フレーム数を計算 path_head = dir + '\out_' # 静止画のファイル名のヘッダー ext_index = np.arange(0, Fs, step) # 静止画を抽出する間隔 for i in range(Fs - 1): # フレームサイズ分のループを回す flag, frame = movie.read() # 動画から1フレーム読み込む check = i == ext_index # 現在のフレーム番号iが、抽出する指標番号と一致するかチェックする # frameを取得できた(flag=True)時だけ処理を行う if flag == True: # もしi番目のフレームが静止画を抽出するものであれば、ファイル名を付けて保存する if True in check: # ファイル名は後でフォルダ内で名前でソートした時に連番になるようにする if i < 10: path_out = path_head + '0000' + str(i) + extension elif i < 100: path_out = path_head + '000' + str(i) + extension elif i < 1000: path_out = path_head + '00' + str(i) + extension elif i < 10000: path_out = path_head + '0' + str(i) + extension else: path_out = path_head + str(i) + extension cv2.imwrite(path_out, frame) # i番目のフレームが静止画を抽出しないものであれば、何も処理をしない else: pass else: pass return # 関数実行:引数=(ファイル名のパス、保存先のフォルダパス、ステップ数、静止画拡張子) m_slice('Scroll.mp4', 'dir', 50, '.png') |
条件によってはframeが取得できないパターンがあって、flag=Falseになってしまうことがあります。
根本解決はしていませんが、if flag=True:の部分で処理を入れれば問題はありません。
サンプル動画に対する実行結果
さて、実際にプログラムを実行して結果を見てみましょう!
サンプルはiPhoneで当ブログを閲覧した時の、スクロールしている様子をキャプチャした動画を用意しました。
こちらが実行結果です。フォルダの中身をキャプチャしました。動画全体としては1000フレームを超えるサイズでしたが、ステップを50に設定したことで50フレームに1枚静止画が保存されています。
…計画通り!
まとめ
PythonのOpenCVを使えば簡単に動画ファイルへアクセスすることができました。
そして動画から静止画を任意のステップ数で保存するコードを紹介し、実行結果を確かめました。
抽出した静止画は再度動画にすることもできますので、スマホで撮影した動画を、違和感の無い間隔で間引いて容量を軽くすることも可能です。
ステップ数を1にして全フレームを抽出し、何らかの画像処理を施して再度動画にすることもできるので、動画全体のリサイズや動画に対する科学技術計算の適用等、利用範囲は広いと思います。
動画の処理も意外と簡単にできたぞ!これまで覚えた画像処理技術がそのまま動画にも適用できそうだ!
Twitterでも関連情報をつぶやいているので、wat(@watlablog)のフォローお待ちしています!
製造業に努めていますが、会社の仕事で利用させていただきました。助かりました。ありがとうございます。
ご連絡ありがとうございます!このようなお言葉は大変励みになります!
これからも色々な記事を投稿しますので、よろしくお願いします。