そこそこな線画を目指す OpenCV

# <i class="fa fa-cubes"></i> 概要

カラー画像から線画を取る。
線画とはモノクロ画像のことで、2値化ではない(たぶん)
OpenCVでしようと考えると、グレースケールで読み込み→`adaptiveThreshold`で2値化を思いつくんだけど、あんまりよくない。
ので、話題の方のコメントってどんな風にやるのか検証。


# <i class="fa fa-book"></i> 参考

* [初心者がchainerで線画着色してみた。わりとできた。 - Qiita コメント]  
前提知識が無いとよくわからなかった
* [miztiさんのツイート: "イラストに輪郭抽出した時に起こりがちな「輪郭の輪郭」の抽出を避けて、綺麗に線画を抽出できるようになった！（1枚目: オリジナル、2枚目: 普通の輪郭抽出、3枚目: 今回の方法） https://t.co/XJetLxsIc7"]  
わかった気になった
* [Python OpenCV3で画素の膨張処理(dilation)と収縮処理(erosion) (ちょっと解説も) - from umentu import stupid]  
画像の膨張ってなんだよ…ってなっていたので助かった。8近傍定義拝借

# <i class="fa fa-code"></i> コード

```py

# -*- coding: utf-8 -*-
"""
Created on Fri Jan 27 11:30:12 2017

@author: khsk
"""

import numpy as np
import cv2 as c
import glob
import os

# 8近傍の定義
neiborhood8 = np.array([[1, 1, 1],
                            [1, 1, 1],
                            [1, 1, 1]],
                            np.uint8)

for path in glob.glob('./images/eupho/*'):
    if (os.path.basename(path) == 'Thumbs.db'):
        continue
    img = c.imread(path, 0) # 0なしでカラー
    img_dilate = c.dilate(img, neiborhood8, iterations=1)
    img_diff = c.absdiff(img, img_dilate)
    img_diff_not = c.bitwise_not(img_diff)
    #gray = c.cvtColor(img_diff_not, c.COLOR_RGB2GRAY)
    
    #at = c.adaptiveThreshold(img_diff_not, 255, c.ADAPTIVE_THRESH_GAUSSIAN_C, c.THRESH_BINARY, 7, 8) # intをいい感じに調整する
    c.imwrite(os.path.dirname(path) + '_clean_senga_color_gray/' + os.path.basename(path), img_diff_not)
    
c.imshow('test',img)
c.imshow('test2',img_dilate)
c.imshow('test3',img_diff)
c.imshow('test4',img_diff_not)
c.waitKey(10000)

c.destroyAllWindows()

```

基本コード。
コメントアウトしたり変数を変えたりint値をイジイジしたりする。
膨張は4近傍などもあるようだけど、くっきりさせたいなら多めの8近傍かなとなんとなく思ってした。
但し書きがない限り読み込みはグレースケールで。


# <i class="fa fa-cube"></i> 元画像

![still_01.jpg](https://qiita-image-store.s3.amazonaws.com/0/62354/326ddc17-8004-df28-414c-2a1ae6fc8136.jpeg)

機械学習の調べ物中にユーフォなどの名前を見かけた記憶があるが、仔細を忘れた。
機械学習に最適とか？使って作ってるとか？
線画には関係ない。おそらく。

# <i class="fa fa-cube"></i> 2値化

`adaptiveThreshold`のみ

![still_01.jpg](https://qiita-image-store.s3.amazonaws.com/0/62354/9a114c00-257d-c7af-7971-804ef4383147.jpeg)

線がガタガタしているし、これはマシだがゴミのような黒点ができることがある

# <i class="fa fa-cube"></i> 膨張1回

![still_01.jpg](https://qiita-image-store.s3.amazonaws.com/0/62354/2c8a57aa-6747-d731-0e0f-7700c4bba3ae.jpeg)

きれいすぎてビックリした。
気になる点といえば、濃淡があり、かすれかすれの線がよく出る。

![hibikeyufoirasuto01002.jpg](https://qiita-image-store.s3.amazonaws.com/0/62354/b0fe687c-953c-4441-7b63-891b9eddbb82.jpeg)

# <i class="fa fa-cube"></i> 膨張3・5回

![still_01.jpg](https://qiita-image-store.s3.amazonaws.com/0/62354/9fb17758-8ab5-eebc-ca90-68784fabcbc9.jpeg)

![still_01.jpg](https://qiita-image-store.s3.amazonaws.com/0/62354/2cff30aa-c3a6-2c8a-7e35-16da2fe755bf.jpeg)


差分が太くなれば薄い線でもはっきり出るかと膨張回数を増やしたが、
濃い線がより太くなるだけで違和感が広がる。
2回ならまだいい感じかも。


# <i class="fa fa-cube"></i> カラー差分→グレースケール

![still_01.jpg](https://qiita-image-store.s3.amazonaws.com/0/62354/8897b4ce-ca3c-fe9b-4495-5087bc494cc4.jpeg)


![still_01.jpg](https://qiita-image-store.s3.amazonaws.com/0/62354/1574ffe5-3657-393f-60c4-4c9b07497452.jpeg)

参考ツイートが最後にグレースケール化だったので、最初の読み込みをカラーで処理をしてみた。(膨張1回)
誤差程度だと思う。カラー線画に味がある。

# <i class="fa fa-cube"></i> 膨張1回後、2値化

![still_01.jpg](https://qiita-image-store.s3.amazonaws.com/0/62354/1e764a97-87ed-6315-7e7f-63eeffea69a1.jpeg)

きれいな線画だけど2値ではないと思ったので最後に2値化。
2値化から情報量を減らした感じに。

# <i class="fa fa-cube"></i> 2値化後膨張1回

![still_01.jpg](https://qiita-image-store.s3.amazonaws.com/0/62354/565e10a8-c848-82bc-5dfe-e5d359cc5dfe.jpeg)

ここまでして、どうやら膨張は2値化の画像に施すらしいと気づいたので、読み込み→2値化→膨張→差分の手順を踏む。
もはや違いは言葉で表せられない。

# <i class="fa fa-cube"></i> 終わり

そこそこになったと思う。
そもそも「いい線画」が何かわかってないのでなんとも。

データセット作成のために考えていたが、機械学習のためのデータ作りを機械学習で作りたい気分に。
[ラフの線画化もすでに研究されている]ので、曖昧な線も補完されるやも。

ということで、機械学習に片足も踏み込んでませんが、データの準備が一歩前進したかなってところで、[学習済みモデルの公開どころかwebサービス化までされたので]、こっちで遊んでいる方が絶対楽しい。

![QFW455OLKMO3EC3E1OSRTD4T8ID75DNV_0.jpg](https://qiita-image-store.s3.amazonaws.com/0/62354/11dc1e59-6361-d279-9716-6f04e5f9b144.jpeg)

髪の色凄い合ってる。


[初心者がchainerで線画着色してみた。わりとできた。 - Qiita コメント]:http://qiita.com/taizan/items/cf77fd37ec3a0bef5d9d#comment-47d363eadb5c5dbf5b44

[miztiさんのツイート: "イラストに輪郭抽出した時に起こりがちな「輪郭の輪郭」の抽出を避けて、綺麗に線画を抽出できるようになった！（1枚目: オリジナル、2枚目: 普通の輪郭抽出、3枚目: 今回の方法） https://t.co/XJetLxsIc7"]:https://twitter.com/mizti/status/816299793324478464

[Python OpenCV3で画素の膨張処理(dilation)と収縮処理(erosion) (ちょっと解説も) - from umentu import stupid]:https://www.blog.umentu.work/python-opencv3%E3%81%A7%E7%94%BB%E7%B4%A0%E3%81%AE%E8%86%A8%E5%BC%B5%E5%87%A6%E7%90%86dilation%E3%81%A8%E5%8F%8E%E7%B8%AE%E5%87%A6%E7%90%86erosion-%E3%81%A1%E3%82%87%E3%81%A3%E3%81%A8%E8%A7%A3/

[ラフの線画化もすでに研究されている]:http://hi.cs.waseda.ac.jp/%7Eesimo/ja/research/sketch/

[学習済みモデルの公開どころかwebサービス化までされたので]:http://qiita.com/taizan/items/7119e16064cc11500f32?utm_campaign=popular_items&utm_medium=referral&utm_source=popular_items