DCGANを使って生成した画像でVJ映像を作成してみました


先日とある都合でVJをすることになったのですが、自分自身は映像を作るのが苦手だし、そもそもVJなんてほとんどよく知らないので、DCGANを使ったDeepLearningでの画像生成を上手く使って、VJ映像を作ることが出来ないかと思って試したことを書かせていただきます。機械学習初心者なので割と泥臭いことしてます。

こんなものを大量に作ってVJしてきました。

DCGANでVJの生成を試してみた動画その4。
なんかこういううごめく感じが、AIならではの表現な気もする。人間にも似たようなものが作れるとは思うけど。確信はない。 pic.twitter.com/H1NZA5Xj3P

— aki (@buchayaty) 2016年5月24日

概要

  • Deep Convolutional Generative Adversarial Networks を使ってVJ映像を学習させた.
  • 学習させている際に、1step学習が終わる度に画像を出力させた。
  • 最終的にそれらを30fpsになるようにつなぎ合わせて、学習過程を映像にして作成した.
  • 先日それらを使ってVJのようなことをさせていただいた。

ちなみにDCGANやChainerでの実装については、Chainerで顔イラストの自動生成や、Chainerを使ってコンピュータにイラストを描かせるをとても参考にさせていただきました。どちらの記事もとてもわかり易いので、DCGANのアルゴリズムや実装の仕方について興味のある方は上記を覗いてみてください。

開発環境

  • MacbookPro(データ加工用に使用)
  • Python2.7
  • Ubuntu 14.04 のデスクトップPC(学習に使用)
     └ NVIDIAのTesla K40を搭載

やったこと

データ収集

機械学習をすると言ったら、まずは何より学習データの収集からです。
個人的にはどういうデータセットを作るかで生成物のクオリティがかなり変わる気がしています。今回はVJ映像をvimeo上で自分で検索して、FreeDownload出来るもののみを集めました。けっこうたくさんあって割とささっと動画データの収集は出来ました。

データをジャンル別に分ける

今回は狙った方向性の映像が作れるか試してみたかったので、集めた動画データを動画ジャンルに分けて学習させました。フォトリアル系、モーションタイポ系、MAD系などなど、完全に個人的な主観で分けました。各ジャンル10~30ぐらいの動画数になりました。

学習前のデータの加工

機械学習をするときにもう一つ大事なのはデータの加工。
今回は下記手順を行いました。

  • 動画データを30fpsで画像連番に分割する。
  • 分割した画像をプログラム的に扱いやすいようにリネーム。
  • 分割した画像をDCGANで学習させるために96x96ピクセルにリサイズ。

●動画データを30fpsで画像連番に分割する。
動画の分割は下記みたいな感じでffmpegを使いました。

ffmpeg -i movie/01.mp4 -an -r 30 01/%05d.png

●分割した画像をプログラム的に扱いやすいようにリネーム。
手元にファイル操作のツールがあったのでそれを使いましたが特にオススメとかはないです。

●分割した画像をDCGANで学習させるために96x96ピクセルにリサイズ。
詳しくは試せていないのですが、画像サイズが大きいと計算時間が異常にかかってしまうので、今回は参考に習って96x96ピクセルにしました。自分でリサイズ用のPythonをかなり適当に書いて変換しています。なので動画データは大体HDサイズなのですが、中央部分のみを切り取って学習させる形にしてしまいました。今回は実験だったので良しとしました。

resize.py
for infile in glob.glob(os.path.join(FROM_DIR, "*.png")):
    im = Image.open(infile)

    aspect = im.size[1]/cropsize;
    resizeWidth = im.size[0]/aspect
    resizeHeight = cropsize
    resized = im.resize((resizeWidth,resizeHeight),Image.ANTIALIAS)

    box = (resized.size[0]/2-cropsize/2,0,resized.size[0]/2+cropsize/2,cropsize)
    croped = resized.crop(box)

    croped.save(os.path.join(TO_DIR, os.path.basename(infile)))

1ジャンル全ての動画を分割した画像枚数を合わせると、5万〜10万枚ぐらいになりました。

学習開始

ここまで来るのに地味に時間かかるし大変でしたが、いざ学習です。
学習時のChainer実装はmattyaさんのがGithubで公開してくださっているものを超絶参考にしながら、自分用に書き換えさせていただきました。

epoch数は1000、train数は5000とし、
1epoch学習が終了する度に学習結果を画像として書き出すようするなどいくつか細かく変更しています。
大体1ジャンルを生成し終わるまで2~3日かかりました。

生成結果をつなぎ合わせて映像化

学習が進む度に書き出した画像を、つなぎ合わせて映像化します。
つまり今回生成する映像は、「データセット内画像のVJらしさを学習する過程の映像」という形になります。
画像をつなぎあわせてGifにするのにはImageMagickを使いました。
映像として見るに耐えうるものにするために30fpsは確保したいので下記のようにしました。

convert -delay 3 test/*.png output.gif

そうしてつなぎあわせた後に、mp4化した動画が下記になります。
これはVJ映像でよく出てくる、パーティクル表現がたくさん使われているような映像を学習させたモデルから生成した映像です。

DCGANでVJの生成を試してみた動画です。 pic.twitter.com/5Ajl0uYr63

— aki (@buchayaty) 2016年5月24日

下記はフォトリアル系を学習させたモデルで生成した映像。

DCGANでVJの生成を試してみた動画その2。
フォトリアル系を学習させた映像。
この間のDEDEMOUSEさんのLiveで使いました。 pic.twitter.com/QE70PpMNA5

— aki (@buchayaty) 2016年5月24日

下記はモーションタイポ系を学習させたモデルで生成した映像。
なんとなく文字のようなものが出てはきている。。

DCGANでVJの生成を試してみた動画その3。
モーションタイポ系を学習させた映像。
文字らしきものが出てはいる。。 pic.twitter.com/k3q7tN9spn

— aki (@buchayaty) 2016年5月24日

そもそもの解像度的な問題はありますが、なんとなくVJっぽい映像になっているのでは、と個人的には思います。(ほんとか?とも思いつつww)
もちろん人間が作った映像には統一感や美しさでは勝てませんが、
AIで生成した独特な映像の感じが思っていたよりも良かったので、他にもたくさんのジャンルで映像を生成して、実際VJをした場ではもっと多くの映像でVJさせていただきました。

やってみて思ったこと

  • データの容量がつらすぎ。動画データを集めて加工してみたいなことをたくさんやっていたらあっという間に1TBを余裕で越えてMacもLinuxも悲鳴をあげてた。
  • データセットの工夫次第ではかなり狙った方向性の映像が簡単に作れる。
  • 今回は時間の制約上、かなり学習回数を少なくしたのでもっと多くすればクオリティが上がるかもしれない。
  • 一度学習してしまえば生成はそこまで大変でないので大量生産できてうれしい。
  • 今回はアルゴリズムの部分をさらっとしか触れなかったので、次回はもっとクオリティ高いものが生成できるようそのあたりをちゃんと理解していじりたい気持ち

せっかくたくさん作ったのでVimeoとかでFreeDownloadで公開しようと思います。
あんまり使う人いないかもですが、なんか変わったVJ映像の素材として貰えたらうれしみ。

ちなみにほんとにVJ映像として使う際は、音声同期でグリッチやエフェクトかけるなどしないとちょっとつらかったです。