画像の読み込みができたら動画の処理に進んでいきましょう。そこで、本記事ではC++とOpenCV(Version4)を用いた動画の読み込み、表示、書き出しについて解説します。このとき、書き出しについては、読み込んだ動画を新たな動画ファイルにそのまま書き出します。また、動画ファイルを用いた処理だけでなくカメラからのリアルタイムでの処理についても説明します。なお、本記事については「C++/OpenCVを用いた画像の読み込み、表示、保存について解説」の続きという位置付けなので画像の処理がわからない場合参照してみてください。
動画の処理
動画の処理についてはじめに画像の読み込み、表示、書き出しが一通り実行できるソースコードを紹介して、そのソースコードをもとに解説していきます。
サンプル動画
本記事で使用する動画についてこちらのフリー素材の動画があるサイトの動画(Mountain.mp4)を用います。
**ちなみにこちらの動画はここで紹介するためのgifファイルとなっております。なので、以下の動画を保存するのではなくフリー素材の動画があるサイトからダウンロードして使用してください。
ファイルの階層
本記事で紹介するファイルの階層は以下のようになっています。
VideoCapture ├ Mountain.mp4 └ Video.cpp
説明に用いるソースコード
本記事では以下のソースコードを用いて説明してきます。
#include <opencv2/opencv.hpp> #include <iostream> int main(void) { // 動画ファイルのパスの文字列を格納するオブジェクトを宣言する std::string filepath = "Mountain.mp4"; // 動画ファイルを取り込むためのオブジェクトを宣言する cv::VideoCapture video; // 動画ファイルを開く video.open(filepath); if (video.isOpened() == false) { // 動画ファイルが開けなかったときは終了する return 0; } cv::VideoWriter writer; // 動画ファイルを書き出すためのオブジェクトを宣言する int width, height, fourcc; // 作成する動画ファイルの設定 fourcc = cv::VideoWriter::fourcc('m', 'p', '4', 'v'); // ビデオフォーマットの指定( ISO MPEG-4 / .mp4) double fps; width = (int)video.get(cv::CAP_PROP_FRAME_WIDTH); // フレーム横幅を取得 height = (int)video.get(cv::CAP_PROP_FRAME_HEIGHT); // フレーム縦幅を取得 fps = video.get(cv::CAP_PROP_FPS); // フレームレートを取得 writer.open("CloneVideo.mp4", fourcc, fps, cv::Size(width, height)); cv::Mat image ;// 画像を格納するオブジェクトを宣言する while (1) { video >> image; // videoからimageへ1フレームを取り込む if (image.empty() == true) break; // 画像が読み込めなかったとき、無限ループを抜ける cv::imshow("showing", image); // ウィンドウに動画を表示する writer << image; // 画像 image を動画ファイルへ書き出す if (cv::waitKey(1) == 'q') break; //qを押すと終了 } return 0; }
動画の読み込み
動画の読み込みについて、まずはじめにstd::string型のfilepathオブジェクトを宣言し、ファイル名(Mountain.mp4)を格納します。次にcv::VideoCaputure型のvideoオブジェクトを宣言し、video.open(filepath)で動画ファイルを開きます。また、video.isOpened()で動画ファイルが開けなかったらプログラムが終了するようになっています。
std::string filepath = "Mountain.mp4"; cv::VideoCapture video; video.open(filepath); if (video.isOpened() == false) { return 0; }
動画の書き出しのための準備
動画ファイルを書き出しするためcv::VideoWriter型のwriterオブジェクトを宣言します。そのあと、保存するビデオのフォーマットを指定します。こちらは、読み込む動画のフォーマットと同じにした方が良いです。なので今回はmp4にするため引数を('m', 'p', '4', 'v')にしています。また、その他の引数については「Video Codecs by FOURCC」から確認してください。
cv::VideoWriter writer; // 動画ファイルを書き出すためのオブジェクトを宣言する fourcc = cv::VideoWriter::fourcc('m', 'p', '4', 'v'); // ビデオフォーマットの指定( ISO MPEG-4 / .mp4)
読み込んだ動画を新しく書き出すするために、動画の横幅、高さ、1秒あたりのコマ数(フレームレート)を取得します。
int width, height, fourcc; // 作成する動画ファイルの設定 double fps; width = (int)video.get(cv::CAP_PROP_FRAME_WIDTH); // フレーム横幅を取得 height = (int)video.get(cv::CAP_PROP_FRAME_HEIGHT); // フレーム縦幅を取得 fps = video.get(cv::CAP_PROP_FPS); // フレームレートを取得
動画の表示と書き出し
動画をウィンドウに表示するために、動画から1枚の画像として取り込む必要があります。そのために画像を格納するオブジェクトを宣言します。
cv::Mat image ;// 画像を格納するオブジェクトを宣言する
動画の表示、書き出しについてwhile文を用いて動画から画像を1枚づつ取り出していき処理していきます。ここから動画の表示、書き出しについて重要な部分なので以下のwhile文の中身を一文づつ説明していきます。
while (1) { video >> image; // videoからimageへ1フレームを取り込む if (image.empty() == true) break; // 画像が読み込めなかったとき、無限ループを抜ける cv::imshow("showing", image); // ウィンドウに動画を表示する writer << image; // 画像 image を動画ファイルへ書き出す if (cv::waitKey(1) == 'q') break; //qを押すと終了 }
動画から画像を1枚づつ取り出します。
video >> image; // videoからimageへ1フレームを取り込む
image.empty()に関して、このループを抜けるようにしています。
if (image.empty() == true) break; // 画像が読み込めなかったとき、無限ループを抜ける
imshow関数は画像をウィンドウに表示する関数ですが、while文を組み合わせることで連続で画像を切り替え動画を表現しています。
cv::imshow("showing", image); // ウィンドウに動画を表示する
ここで表示したimageをwriterへ書き出していくことで動画ファイルが新たに作成されます。
writer << image; // 画像 image を動画ファイルへ書き出す
ここではqを押すと終了するようにしています。qを押した時点でウィンドウも閉じて、書き出される動画もここまでになります。
if (cv::waitKey(1) == 'q') break; //qを押すと終了
以上が動画の読み込み、表示、書き出しの一連の流れになります。
動画処理の実装
以下のコマンドを打つことでコンパイルを行います
g++ -std=c++11 -o video Video.cpp `pkg-config --cflags --libs opencv4 `
そして以下のコマンドを打ち実行します。
$ ./video
すると以下のようなウィンドウが立ち上がります。
そして動画が終わると、CloneVideo.mp4というファイルが作成されます。
VideoCapture ├ Mountain.mp4 ├ CloneVideo.mp4 └ Video.cpp
カメラからの読み込み
カメラから読み込むとき、以下の動画ファイルの読み込みの部分を変えます。
// 動画ファイルのパスの文字列を格納するオブジェクトを宣言する std::string filepath = "Mountain.mp4"; // 動画ファイルを取り込むためのオブジェクトを宣言する cv::VideoCapture video; // 動画ファイルを開く video.open(filepath); if (video.isOpened() == false) { // 動画ファイルが開けなかったときは終了する return 0; }
以下のようにVideo.open(0)とすることで内蔵されているPCのカメラが起動しリアルタイムで動画を読み込むことができます。また外付けのカメラを使用したいときはVideo.open(1)とすることで、可能です。
// カメラからの動画を取り込むためのオブジェクトを宣言する cv::VideoCapture video; // カメラを起動する video.open(0); if (video.isOpened() == false) { // カメラが起動しないときは終了する return 0; }
この記事のまとめ
本記事ではC++とOpenCVを用いた動画の処理(読み込み、表示、保存)のやり方を解説しました。
また、カメラを用いたリアルタイムでの動画処理も解説しました。
これができれば、動画の再生アプリが作成できたり、機械学習を用いた人物の行動分析や追跡など幅広く用いることができます。
ぜひOpenCVとC++を用いた動画処理を行なってみてください!