【Deep Learning 画風変換】ポケモンを大神の世界に連れて行ってみた

みなさんは,画風変換をしてみたい!と思ったことはありませんか?例えばお気に入りの犬の画像を毛筆風にしてみたり,アニメ風にしてみたり・・・

 

僕は,「ポケモンを大神(別のゲーム)の世界に連れて行ったらどんな風にデフォルメされるのかな?」と想像を膨らませることがよくあります。

 

f:id:eeveeTuna:20151122174343p:plain

中には自分の頭の中で想像したものを描ける方もいると思うのですが,僕には中々ハードルが高い・・・
そんなことを考えていると,こんな記事を見つけました。

 画風を変換するアルゴリズム

なぬ!!画風を変換することができる・・だと!?これは気になるぞー

 

このページを見ると,pythonで書かれたプログラム(chainer gogh)が公開されているようなので,さっそくダウンロードして動かしてみました。

 

今回はサンダースを,アマ公の画風に変換してみます。ワクワクしますね!

サンダース「た,たすけてー」

アマ公「おいでおいでー(^^)」

 

その結果がこちら

f:id:eeveeTuna:20151122175127p:plain

かっこいいぞ,サンダース君!!
アマ公の日本画っぽい画風を引き継ぎつつ,サンダースらしさもちゃんと残っています。

 

となるとその仕組みが気になってきますよね。そこで,
画風変換法について,僕なりにひも解いてみたいと思います。

 

/*注***********************************************************
今回の記事では,

スタイル画像」
画風として用いる画像(例: アマ公の画像)

「コンテンツ画像」
元の画像(例: サンダースの画像)

「目的画像」
画風変換によって生成された,今回作りたい画像

と呼ぶことにします。

f:id:eeveeTuna:20151122180155p:plain


*************************************************************/

では本題,どうすれば画風変換した画像が生成できるのでしょうか?

単純に考えると,以下の3つができれば画風変換ができます。

① 「スタイル画像」から画風の抽出
② 「コンテンツ画像」から「コンテンツ画像らしさ」を表す部分の抽出
③ ①②の抽出部分を反映し「目的画像」の生成

f:id:eeveeTuna:20151122182240p:plain

 

①「スタイル画像」から画風の抽出
そもそも「画風」とは何なのでしょう?まずはそこから考えていきましょう。

画風とは・・・

「絵画の作風。絵に現れた画家,または流派の特色や傾向」(コトバンクより)

ということは,

・描かれる線の太さの特徴

・影の付け方の特徴

・色の使い方の特徴

といった画像中に含まれる「特徴」が相互に関係し,組み合わさって「画風」になると言えます。

つまり,「画風」=「画像中に含まれる特徴どうしの相関」と言い換えることができます。

 

 【特徴の抽出】

では,画像中の「特徴」を抽出するにはどうすればよいでしょうか?実はここで,最近話題のDeep Learning(厳密には学習済みのCNN)の力が活用できます。

学習済みのCNNにスタイル画像(アマ公の画像)を入力し,中間層の出力を見てみましょう。

 

f:id:eeveeTuna:20151123115452p:plain

ちょっと見づらいので入力と1層目だけ抜粋してみます

f:id:eeveeTuna:20151122204434p:plain

中間層の出力を見ると,入力画像がそれぞれ「特徴」ごとに分かれることが分かります。例えば,影の特徴であったり,炎の部分の特徴であったり,・・・
そう,学習済みCNNは画像中の「特徴」を抽出できるんですね。

 

【特徴の相関の計算】
では,得られた「特徴」どうしが互いにどのような相関を持っているのか,求めてみましょう。
/**コメント(相関の数学的表現)****************************************************

2つの特徴’の相関は,同じ位置のピクセルどうしの積をもとめて,それをすべて足し合わせることにより求まります。

f:id:eeveeTuna:20151123130818p:plain

例として,炎の特徴と影の特徴の相関をとる場合を考えてみます。炎の特徴と影の特徴が同じ位置にセットで現れやすいなら,相関は上がりますし,炎の特徴と影の特徴が同じ位置にセットで現れにくいなら,炎と影の相関は下がります。つまり,炎に影を付ける特徴があるのか,そうでないのかを数値の大小でチェックできるということになります。

以下では,それぞれの特徴間で相関をとり,特徴の組み合わさり方を見ていきます。

**************************************************************************************/

 

f:id:eeveeTuna:20151123120020p:plain

 

すると,「各特徴に対する他の特徴の相関を表すベクトル」が生成されます。
また,全て特徴についてベクトルを合体すれば,「画像中に含まれる(すべての)特徴間の相関」を表すベクトルになりますね。

 

f:id:eeveeTuna:20151122232454p:plain

そこで,もう一度画風について立ち戻ってみましょう。
「画風」=「画像中に含まれる特徴間の相関」でしたね。
ということはこのベクトルは,「画風を表すベクトル」とも言えます。
以上より,スタイル画像」の「画風」を「画風を表すベクトル」という形で抽出できることが分かりました。

 

② 「コンテンツ画像」から「コンテンツ画像らしさ」を表す部分の抽出
次に,コンテンツ画像(サンダースの画像)についてみていきます。

f:id:eeveeTuna:20151122173754j:plain

 


この画像の「サンダースらしさ」って何でしょう?考えていても中々分からないので,サンダースの画像も学習済みCNNに入力して特徴に分解してみましょう。サンダースらしさを含む成分が見えるはず・・・

f:id:eeveeTuna:20151122194736p:plain

うーん,上の層ほど詳細な特徴,下の層ほど粒度の粗い大雑把な特徴というのは分かりますが,サンダースらしさを表しているかどうかはイマイチ分かりません。

そこで,どの特徴が「サンダースらしさ」を表しているのかを知るために,「CNNが脳を模したモデルである」ということを考慮して,自分の脳と比較しながら検証をしてみましょう。
まず,目をつむってサンダースを思い浮かべてみてください。

以下脳内イメージ------------------------------------------

f:id:eeveeTuna:20151122195005p:plain

うーん,どんなんだったっけな?

 

f:id:eeveeTuna:20151122195142p:plain

こんな感じかな?

-------------------------------------------------------------------

あれ,具体的に思い出せない・・・けど,自分が「サンダース」と認識できる何ふんわりとしたイメージは想像できると思います。

 

このイメージ,色々な特徴は抜け落ちているけど,「サンダースらしさ」だけは残っていると言えますね。ということは,このような特徴の層を取り出せば良いことが分かります。

 

では,この画像に似ている特徴を探してみましょう。おっ,深い層(3層目,4層目あたり)が似ていますね。ということは,深い層の出力を抽出すれば,「コンテンツ画像らしさ」の抽出ができることになります。

 

③「目的画像」の生成
①②を踏まえると,次の条件を満たす画像を作れば「目的画像」が生成できると言えます。

(1)「スタイル画像」と「画風を表すベクトル」が似ている
(2)学習済みCNNに入力したとき,「コンテンツ画像」と深い層の出力が似ている

 よって,ランダムに生成した画像を,(1)(2)を満たすようにを修正していくことで,「目的画像」に近づけていきます。

f:id:eeveeTuna:20151123013655p:plain

では,ランダムに生成した画像から「目的画像」に向かって画像が修正されていく様子を見ていきましょう。下の画像をしばらく眺めてみてください。

f:id:eeveeTuna:20151123014625g:plain

目的画像ができました!やったー!!!

 

まとめ

今回は,chainer goghで使われている,画風変換の仕組みを紹介しました。Deep Learningの一種であるCNNの,画像特徴分解の技術により,画風変換が実現していることが分かります。
色々な画像を合成できるので,ぜひ皆さんも試してみてください!!

 

おまけ

イーブイ イーブイ!!】

イーブイも大神の世界に連れて行ってみました。

f:id:eeveeTuna:20151128232650p:plain

サンダース以外でもうまくいきます!最高です!!

 

【パラメータ変更点】

画風変換をするにあたって,パラメータをいじった部分があるので,記述しておきます。
※変更前

parser.add_argument('--lam', default=0.005, type=float,
help='original image weight / style weight ratio') 

※変更後

parser.add_argument('--lam', default=0.05, type=float,
help='original image weight / style weight ratio') 

 

もとのパラメータ設定よりも,サンダースがより強調される設定になっています。やっぱりポケモンらしさを強く出したいですよね(^^)