PythonでOpenCVを使って動画を入出力する方法について解説します。
Contents
OpenCVによる動画入出力
OpenCVは、有名なコンピュータービジョンのライブラリです。OpenCVのPythonバインドであるcv2
モジュールを使用することで、PythonでOpenCVの機能を使用することができます。
OpenCVでは、動画の入出力のためのクラスとして、VideoCapture
とVideoWriter
というクラスが用意されています。AVIファイル等多くのフォーマットをサポートしますが、対応可能な動画フォーマットはOSやOpenCVの構成により異なります。これらのクラスは、動画ファイルをBGRフォーマットのフレーム画像として取得します。
この記事では、PythonでOpenCVを使って画像を入出力する方法について紹介します。
画像の読み込みやOpenCVでの画像表現(BGR)については「OpenCVによる画像入出力の基本 ~imread, imwrite~」でまとめているので参考にしてください。
VideoCapture、VideoWriterによる動画の読み込み、書き込み
ここでは、VideoCapture
クラス及びVideoWriter
クラスを用いた動画の読み込みや書き込みについて紹介します。
基本的な使い方
VideoCapture
クラスを使用して動画を読み込み、VideoWriter
クラスを使用して別の動画ファイルとして書き込みを行ってみましょう。VideoCapture
やVideoWriter
は、以下のように使用します。
import cv2 # VideoCaptureのインスタンスを生成 video_capture = cv2.VideoCapture("sample.avi") if not video_capture.isOpened(): print("ファイルが開けませんでした。") exit() # FPSの取得 fps = video_capture.get(cv2.CAP_PROP_FPS) # サイズの取得 (width, height) size = ( int(video_capture.get(cv2.CAP_PROP_FRAME_WIDTH)), int(video_capture.get(cv2.CAP_PROP_FRAME_HEIGHT)), ) print(f"fps: {fps}") print(f"Width: {size[0]}, Height: {size[1]}") # VideoWriteのインスタンスを生成 video_writer = cv2.VideoWriter( "output_i420_sample.avi", cv2.VideoWriter_fourcc(*"I420"), fps, size ) if not video_writer.isOpened(): print("VideoWriterの生成に失敗しました。") video_capture.release() exit() # 動画の読み込み success, frame = video_capture.read() # フレームがなくなるまで繰り返しで読み込み while success: video_writer.write(frame) success, frame = video_capture.read() # リソースの解放 video_capture.release() video_writer.release()
【実行結果】 23.976 (720, 528)
上記のプログラムの各ポイントを説明していきます。
【モジュールのインポート】
import cv2
OpenCVの機能を使用するためにcv2
モジュールをインポートしておきます。
【VideoCapture
インスタンス作成と動画情報の取得】
# VideoCaptureのインスタンスを生成 video_capture = cv2.VideoCapture("sample.avi") if not video_capture.isOpened(): print("ファイルが開けませんでした。") exit() # FPSの取得 fps = video_capture.get(cv2.CAP_PROP_FPS) # サイズの取得 (width, height) size = ( int(video_capture.get(cv2.CAP_PROP_FRAME_WIDTH)), int(video_capture.get(cv2.CAP_PROP_FRAME_HEIGHT)), ) print(f"fps: {fps}") print(f"Width: {size[0]}, Height: {size[1]}")
動画ファイルを読み込むには、VideoCapture
のインスタンス生成時に動画ファイルパスを指定します。また、ファイルが開けなかったことの確認に、isOpened
メソッドを使用しています。
動画の情報を取得するにはget
メソッドを使用することができます。例えば、動画で1秒間に表示されるフレーム数はFPS (Frame Per Second)と言いますが「fps = video_capture.get(cv2.CAP_PROP_FPS
)」で取得できます。同様に動画のフレームの幅 (cv2.CAP_PROP_FRAME_WIDTH
)や高さ (cv2.CAP_PROP_FRAME_HEIGHT
)を取得しています。
他にも様々なプロパティとなるenumが用意されていますが、詳細は公式ドキュメントのFlags for video I/OのページにおけるVideoCapturePropertiesを参考にしてください。
【VideoWriter
インスタンス作成】
# VideoWriteのインスタンスを生成 video_writer = cv2.VideoWriter( "output_i420_sample.avi", cv2.VideoWriter_fourcc(*"I420"), fps, size ) if not video_writer.isOpened(): print("VideoWriterの生成に失敗しました。") video_capture.release() exit()
動画書き込み用のインスタンスを作成する際には、上記のように「出力ファイルパス」「fourcc」「FPS」「サイズ (幅, 高さ)」をVideoWriter
の引数で指定します。今回は読み込んだファイルを別名で出力しているのでfps
やsize
は上記においてget
で取得した元ファイルのFPSとサイズをそのまま指定しています。
ここで、fourccは「Four Character Code」の略で、ビデオファイルのコーデックを指定するための4文字のコードのことです。cv2.VideoWriter_fourcc(*"I420")
は、AVIファイルの指定でよく使用されるもので、非圧縮のYUVエンコーディングを使用します。また、この引数の部分に0
を指定すると非圧縮の生データとなります。
cv2.VideoWriter_forcc
は、4つの引数を受け取る関数ですが「*
」を使って文字列を分解して渡しています。つまり「cv2.VideoWriter_fourcc("I", "4", "2", "0")
」と同じ意味になります。
また、インスタンスが生成できなかったことの確認に、isOpened
メソッドを使用しています。
【動画フレームの読み込みと動画の書き込み】
# 動画の読み込み success, frame = video_capture.read() # フレームがなくなるまで繰り返しで読み込み while success: video_writer.write(frame) success, frame = video_capture.read()
上記の部分は、動画を読み込みつつ動画を別ファイルに書き込んでいる部分です。
読み込みには、VideoCapture
のread
メソッドを使用します。read
は、読み込みが成功したか否かのフラグとフレームが返却され、再び実行すると次のフレームを取得します。フレームが取得成功する限りwhile
で読み込みを続けることで、元データのフレームをすべて取得しています。
読み込みと並行してVideoWriterのwrite
メソッドで、読み込んだフレームを指定することで動画ファイルを書き込んでいます。
【リソースの解放】
# リソースの解放 video_capture.release() video_writer.release()
プログラムの終わりでは、VideoCapture
とVideoWriter
のオブジェクトを適切に開放することが重要です。リソースの解放は、release
メソッドを使用することで実行できます。
MP4ファイルでの書き込み
上記では、AVIファイルで"I420"
(非圧縮のYUVエンコーディング)を使用しました。これは、広く使用されるものですが、ファイルサイズが大きくなります。
VideoWriter
は、様々なビデオコーデックに対応します。例えばMP4ファイルは出力サイズを制限したいときによい選択肢です。MP4ファイルでの書き込みをする場合には、以下のようにavc1
(Advanced Video Coding 1)等を指定することが可能です。
# VideoWriteのインスタンスを生成 video_writer = cv2.VideoWriter( "output_avc_sample.mp4", cv2.VideoWriter_fourcc(*"avc1"), fps, size )
avc1
は、H.264コーデックを使用するものでMP4ファイル形式に出力する際には一般的に使用されます。非常に効率的な圧縮がされ、広く互換性があります。
エラーが出た場合の対処法
avc1
を指定した場合には、以下のようなエラーが出る場合があります。
Failed to load OpenH264 library: openh264-1.8.0-win64.dll Please check environment and/or download library: https://github.com/cisco/openh264/releases
このエラーは、openh264-1.8.0-win64.dll
の読み込みに失敗したとあるため、必要な環境が整っていないことを意味しています。エラーもあるようにhttps://github.com/cisco/openh264/releasesから必要なDLLをダウンロードして対応します。
openh264-1.8.0-win64.dll.bz2
というバージョンをダウンロードし、ファイルを解凍してください。BZ2形式で圧縮されているので7-ZipやWinRAR等の解凍ソフトで解凍が必要です。
解凍して取得したファイル(openh264-1.8.0-win64.dll
)をアプリケーションが参照できるパスに配置します。もっとも簡単な方法は実行プログラムと同じフォルダに配置することですが、その他にもPATHが設定されているフォルダを使用することが可能です。
様々なコーデックへの対応
今回は、AVIファイルを出力する際の"I420"
やMP4ファイルを出力する際の"avc1"
を例にしましたが、コーデックは他にも色々と使用することができますので色々と調べてみてください。例えば、OGVファイル("THEO"
)、FLVファイル("FLV1"
)のようなものもあります。
ただし、上記MP4の例でエラーが発生したように各コーデックで適切に出力できるかどうかは、お使いのOpenCVのバージョンやOSの種類、実行環境において適切なライブラリが存在するかなどに依存することに注意してください。
まとめ
PythonでOpenCVを使って動画を入出力する方法について解説しました。
OpenCVでは、動画の入出力のためのクラスとして、VideoCapture
とVideoWriter
というクラスが提供されています。AVIファイル等多くのフォーマットをサポートしますが、対応可能な動画フォーマットはOSやOpenCVの構成により異なります。
この記事では、VideoCapture
とVideoWriter
を使って基本的な読み込みや書き込みの方法を紹介しました。書き込み例としてはAVIファイルやMP4ファイルを題材にしました。
OpenCVは、非常に強力なコンピュータビジョンのライブラリで、動画の入出力は画像を扱うにあたっての基本となります。しっかりと使い方を理解していただきたいと思います。