社会人研究者が色々頑張るブログ

pythonで画像処理やパターン認識をやっていきます

Python+Pytorchでイラストの生成

はじめに

ブログを執筆したり職場で研究内容を人に伝える際に、積極的にイラストを用いるようにしています。
イラストを用いる事で、言葉で伝えるにはややこしい内容であっても、直感的に理解してもらえる事が多いためです。

しかしながら僕は,単純な図表などはある程度描くことが出来るのですが、複雑なデザインや可愛らしいキャラクターなどは描くことが出来ません。
以下に自分で描いたイラストの一例を示します。

イラスト例1 イラスト例2
f:id:nsr_9:20211010191340p:plain f:id:nsr_9:20211010191351p:plain

図表で伝える分にはギリギリ最低限の画力はあると思いますが、まだまだ改善の余地が沢山あると思います。
今回は線画からイラストを生成するAIを構築、学習し、画力の改善を図ってみたいと思います。

作るもの

今回は線画を入力するといい感じに着色してくれるCNNを学習してみたいと思います。
f:id:nsr_9:20211010195228p:plain

図中の素敵なイラストは、友人のご好意によりお借りしています。[1]

また,このCNNの仕組みは以前の記事を参照してください。
nsr-9.hatenablog.jp

NetworkのアーキテクチャにはU-Netと呼ばれるEncoder-Decoderモデルを使用します。[2]
このアーキテクチャは入力された画像をダウンサンプリングしながら畳み込むのですが、その後に入力解像度と同等になるようにアップコンバートしていきます。
そのため、今回のような画像(線画)から画像(カラーイラスト)に変換する様なタスクに対して汎用的に用いる事が出来ます。
f:id:nsr_9:20210901150932p:plain

学習データ

また学習データには、カラーイラストのデータ・セットを利用します。
本来ならばカラーイラストと線画のペアを学習に使用したいのですが、その様な都合の良いデータはネット上にもそう多くありません。
そこで今回は、Canny Edge検出と呼ばれる画像処理を用いて、カラー画像から線画に相当するデータを作成しました。

以下にOpenCVでCanny Edgeを求める実装を示します。

import cv2
img = cv2.imread("image.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
canny = cv2.Canny(gray, 100, 200)
cv2.imwrite("canny.jpg", canny)

cv2.Cannyの100と200はエッジ検出の際のしきい値となります。入力画像に応じて適宜調整します。

このプログラムを走らせると次のような出力を得ます。

入力画像 Canny Edge 反転したもの
f:id:nsr_9:20211010211115p:plain f:id:nsr_9:20211010211124j:plain f:id:nsr_9:20211010211324j:plain

なんとなく線画っぽいビジュアルになっていますね!

CNNの学習には大量のデータセットが必要なのですが,今回はanimeface-character-datasetというアニメ画像の公開データセットをお借りしました。
animeface-character-dataset
このデータセットの画像のCanny Edgeを求めると次のようになりました。

学習データ 教師データ
f:id:nsr_9:20211010221624p:plain f:id:nsr_9:20211010221635p:plain

学習データと教師データは次のようにCNNに与えます。
f:id:nsr_9:20211010212259p:plain
図から分かる通り,CannyEdgeを擬似的な線画としてU-Netに与え,オリジナルのカラーイラストを回帰するように学習します.

実験結果

15000枚の画像を20Epoch学習させてみました。
学習時間は3時間くらいだったのですが,GPUのファンがぶおぉおおおおって猛烈に鳴り響き、部屋が排熱で熱くなっていくのを感じました。
学習したモデルに対して、学習に使ったデータで推論すると次のようになりました。

学習に使った入力データ 推論したカラーイラスト 教師データ
f:id:nsr_9:20211010230935j:plain f:id:nsr_9:20211010231003j:plain f:id:nsr_9:20211010231016p:plain
f:id:nsr_9:20211010231033j:plain f:id:nsr_9:20211010231039j:plain f:id:nsr_9:20211010231056p:plain
f:id:nsr_9:20211010231111j:plain f:id:nsr_9:20211010231129j:plain f:id:nsr_9:20211010231120p:plain
f:id:nsr_9:20211010231142j:plain f:id:nsr_9:20211010231149j:plain f:id:nsr_9:20211010231157p:plain

予想に反し色彩がセピア色になっていていますね. カラーになってくれることを期待していたのですが,これはこれでちょっとした味が有りると思います。

学習データは鮮やかな色彩を持っているのですが、なぜこうなったのでしょうか? 一つの仮説をあげるとすると、Canny Edgeの入力から色情報が一意に決定出来ない事が挙げられます。
f:id:nsr_9:20211010233424p:plain
線画(色情報がない)だけだと,このイラストが青い猫なのか,茶色い猫なのか決定する事ができません.
線画では似ているのに色彩が異なっている学習データが多く含まれると,この様に中間色が優先されるのではないかと考えています.

これを解消する為には、色情報を入力に与える必要が有りますが,その様な学習を行うためには、条件付き学習が適していると思います。[3]

学習に使ってないデータで推論した結果を示します。
以下は僕が適当に描いたイラストを入力しました。

推論に使ったデータ(手描き) 推論結果(カラーイラスト)
f:id:nsr_9:20211010235213j:plain f:id:nsr_9:20211010235242j:plain
f:id:nsr_9:20211010235447j:plain f:id:nsr_9:20211010235323j:plain

線画の歪みもいい感じに再現されていて、ちょっと笑いました。
また、友人のイラストで推論すると次のようになります。

推論に使ったデータ(手描き) 推論結果(カラーイラスト)
f:id:nsr_9:20211011001949j:plain f:id:nsr_9:20211011001705j:plain
f:id:nsr_9:20211011002001j:plain f:id:nsr_9:20211011002057j:plain

とても味のあるイラストになりました!
やはり、良い線画だと生成されるイラストも素晴らしいものになるようです。

まとめ

線画からイラストを生成するAIをつくり、実際にイラストを生成してみました。
鮮やかなカラー画像を学習させたのですが、推論結果がセピア色になったのがとても不思議でした。
今後はこの生成器をどんどん拡張していきたいと思います。

[1] 木密るう - pixiv
[2] Ronneberger, Olaf, Philipp Fischer, and Thomas Brox. "U-net: Convolutional networks for biomedical image segmentation." International Conference on Medical image computing and computer-assisted intervention. Springer, Cham, 2015.
[3] Isola, Phillip, et al. "Image-to-image translation with conditional adversarial networks." Proceedings of the IEEE conference on computer vision and pattern recognition. 2017.