Introduction
pix2pixを用いた線画着色では大量の線画と着色画像のペアのデータが必要となりますが、着色画像から線画を生成する手法としてはopencvを用いたものが簡単に出来ます。具体的には輪郭線を細くして元画像との差を取ることで、輪郭線のみを抽出するというものです。しかし、この手法では以下のように線に濃淡が出来てしまい、線画としては不自然なものになります。そこで、今回は自然な線画を生成するためUnetを用いて試してみました。すんなりといけそうだと思っていましたが、意外とハマったのでここにまとめます。
Dataset
pixivの塗ってみたタグのついた画像から着色画像と線画を120ペアほど集めました。この時、
- 余計なものが着色されていないか(例えば線画では白背景なのに着色画像の方には背景に多様な色が塗ってあったり、線画にはないものが書き込まれていたりしてないか)
- 着色画像と線画で位置のズレがないか
の2点をチェックしました。次に、これらの120ペアからランダムに128*128サイズを3枚ずつcropし、それぞれに対して90, 180, 270度回したものをデータ水増しとして用意しました。従って、合計120*3*4 = 1440ペア生成されたことになります。
Result
以上のように作成したデータセットに対して、入力データを着色画像、教師データを線画(グレースケール)としてUnetを用いて学習を行いました。損失関数は平均絶対値誤差を用いました。学習したネットワークを用いて、テスト用画像を線画変換したものを以下に示します。尚、今回ネットワーク出力後の画像データの値は[0,1]に収まっているのですが値が0.9未満の場合0として、それ以外の場合は1を出力するようにしています。二値化することで余計なノイズを無くすためです。
どのサイズでも、均等な濃淡を持つ線画が形成されていることが分かります。多少線が形成されていない部分があるものの、大まかにはうまくいっています。
Trouble
詰まった所が2点あるので、戒めとして残しておきます。
- 1点目は、データセットの用意においてです。初めのうちは、画像サイズを圧縮したものを学習用データとして用いていたため、以下のようにギザギザ状態が残ったものが出力されました。これは、データセットの部分で述べたように圧縮せずに元画像からcropすることで解決しました。
- 2点目は、学習用ネットワークについてです。今回の例ではUnetを用いていましたが初めのうちは単なるAutoEncoderを用いていました。しかし、これではうまく出力されなかったためUnetを用いました。やはり、着色画像と線画のように、色は異なるものの構造は同じペアにはUnetを用いるのが良いのでしょうか….
Summary
今回は、Unetを用いて着色画像から線画へ変換することを行いました。大まかにはうまくいっています。しかし、実用として大量の画像を線画へ変換することを考えると、一枚の画像でさえGPUを用いても数秒はかかるので、冒頭で述べたopencvを用いた方が荒削りではあるものの高速であることは確かです。
今回の手法で作成した線画とopencvを用いて作成した線画で、pix2pixで着色した時に違いが出るのかも試してみたいですね。
Environment
OS : Ubuntu 16.04 LTS (64-bit)
CPU : Intel(R) Core(TM) i5–4590 CPU @ 3.30 GHZ
GPU : NVIDIA GTX970
メモリ : 8GB