着彩済イラストから綺麗に線画を抽出する方法
機械学習のテーマの一つとして自動着彩があります。この中で、特にイラストの自動着彩を考えると 未着彩と着彩済みのペアが学習用サンプルとして大量に必要となりますが、まとまった量を入手するのはなかなか難しいという問題があります。
すると、カラーイラストから線画を抽出することを考えたくなるのですが、 一般的な輪郭検出を用いると「輪郭線自体の輪郭」が抽出されてしまい、線がぼやけてしまうという問題があります。
例えば に対して輪郭検出を実施すると、 となります。 (拡大)
右頬の輪郭線に対して、肌側、背景側それぞれの境界が検出されてしまい、線が2本引かれてしまっていることがわかります。
で、綺麗な輪郭抽出ができず困っていたのですが、ピーFN(一体何FNなんだ...)のtaizanさんが投稿されたこちらのエントリ
では非常に綺麗に線画抽出ができており、どのようにやっているか気になっていたところ
との情報が。ということでやってみました。
拡大
線がだぶることなく、綺麗に抽出できているようです。すごい!
(ここまでの絵は村田蓮爾氏のものを引用させていただいています)
手順詳細
以下、手法の詳細についてです。
以降の絵はpixivで見つけたLpipさんのイラスト を例にさせていただいてます。
今回使ったのはcv2のpythonライブラリです。
画像を開く
I = cv2.imread('data/before.png')
dilationする
kernel = np.ones((5,5), np.uint8) dilation = cv2.dilate(I, kernel, iterations = 1)
元画像とのdiffを取る
diff = cv2.subtract(I, dilation)
白黒反転する
diff_inv = 255 - diff
グレースケール化して書き出し
diff_inv_binarized = cv2.threshold(diff_inv, 100, 255, cv2.THRESH_BINARY) cv2.imwrite('after.png', diff_inv)
まとめると
I = cv2.imread('data/before.png') kernel = np.ones((5,5), np.uint8) dilation = cv2.dilate(I, kernel, iterations = 1) diff = cv2.subtract(I, dilation) diff_inv = 255 - diff diff_inv_binarized = cv2.threshold(diff_inv, 100, 255, cv2.THRESH_BINARY) cv2.imwrite('after.png', diff_inv)
です