2014年10月2日木曜日

C#+OpenCvで静止画を動画にする

タイムラプス撮影とかした場合に問題になるのが、大量の静止画をどうやって動画にするか
安い動画編集ソフトだと静止画は最短で0.1秒表示みたいな感じで望む再生速度にならない

ということでC#で動画化するアプリを書いてみた

今回はC#のコンソールアプリとして作る
もちろんフォームアプリを作ってオープンファイルダイアログでファイルを選択するようにしてもいいわけだが、今回は上位のプログラムから起動して処理させたかったのでこのような方式にした

それと動画ファイルを作るのにOpenCvを使う
C#で走らせるのでOpenCvSharpが必要になる
これの準備は他のブログとかにちゃんと説明されてるのでそっちを参照。。

/* *** */

まず静止画の一覧を獲得する必要がある
今回はコンソールアプリの1個目のオプションに画像の一覧を書いたテキストファイルを渡すようにする


画像ファイルはList<string>で扱う
リストに突っ込むときは片っ端から突っ込んでそのファイルが存在するかとか、そもそもそれは正しいファイルパスなのかとかは気にしない

それとdouble型でフレームパーセックの変数を用意しておく
とりあえず double FPS = 30; を作り、オプションが2個以上であれば2個目をdoubleの文字列として読ませるようにした これでファイルのリストだけが与えられたら30fpsの動画を作り、それ以外の速度にしたければ引数で与えればその速度になる


それと画像ファイルの解像度を獲得する関数を作る
引数に渡された画像をBitmapで開いてWidthとHeightを返すだけ
そして GetPictureSize(PictureFilePaths[0], out SizeX, out SizeY); のような感じで画像の解像度を得る
この解像度で動画を作成することになる


最後に動画ファイルを作成する

最初に処理時間の目安を計測するためにStopwatchを確保する

次にCv.CreateVideoWriter関数を呼ぶ
第一引数:ファイル名
第二引数:エンコード方式
第三引数:フレームパーセック
第四引数:解像度
なのでそれぞれに変数を渡すなりして適切な値を与えてやる
なお、FileExte = "avi"; EncodedFormat = "MJPG"としてstringの変数を作ってある
これはAViコンテナにモーションJPGの動画を入れるということ
エンコードはH.264とかやろうと思ったけどどうやらウチのマシンは対応していないようなのでMJPGになった
fpsはさっき作ったdoubleをそのまま渡す
解像度もさっき調べた解像度をそのまま渡せばOK

あとはCv.WriteFrameで動画を書き込んでいけば動画ファイルを作成することができる

forで0からPictureFilePaths.countまでを回して、まずFile.Existsでファイルが存在するかを確認する
そしてCv.LoadImageで読み込んで渡す


本来はもっとまじめにエラー対策とかする必要がある
けど面倒なので読み込むファイルのチェック程度しかしていない

出力されるコンテナはaviなので、youtubeに投げる場合は別のコンテナにエンコードし直す必要がある
その辺りは動画編集ソフトに突っ込んでBGMつけて書き出せばいいので気にしないで置く


ということで、面倒な大量の静止画を動画にする作業が簡単になった
静止画のリストはCygwinとかで ls *.jpg > list.csv とかで簡単に作れるし、あとはそれを引数に渡せばいい
もしもGUIが必要なら最初からGUIで作ってもいいし、GUIはファイルの選択とリストの作成だけで、それ以外はCUIに投げてもいい

今回はコンソール用に作ってるのでファイルが存在するかの確認とか、解像度を調べるとかを除けばそのままCとかC++のOpenCvにも移植できるはず

0 件のコメント:

コメントを投稿