Yabu.log

ITなどの雑記

ポスタリゼーションとCannyのエッジ検出アルゴリズムの組み合わせでイラストから下絵の作成に挑戦

いらすとやの画像を借りて試してみました。

www.irasutoya.com

f:id:yuyubu:20181227190046p:plain
対象画像

1.Gaussianオペレータを適用することによりエッジをぼかす
2.Sobelオペレータを適用し画像を微分する
3.微分画像を繊細化する
4.繊細化した結果の連結性を上げるために、2つの閾値を用いた2値化を行う

と複雑な手順が必要ですが、opencvなら関数一個で処理できます。

image = cv2.Canny(image,0,0,3)

f:id:yuyubu:20181227185311p:plain
普通にCannyアルゴリズムを適応

Cannyアルゴリズムをそのままイラストに適応するとうまく行きませんでした。 これはイラストやのイラストは肌や副部分にフェルト生地のような質感を感じさせる着色がなされているためだと思います。 また、イラストやの画像は問題ありませんが、ネットで拾ってきた野良画像は結構ノイズが乗っていることが多いのでそちらの影響も受けてしまいます。

例えば私のアイコン画像でそのまま試すと以下のようになりました。

f:id:yuyubu:20181227193002p:plain
Cannyアルゴリズムはノイズの影響に弱い

このフェルトのような質感をポスタリゼーションで均一化すればうまく行くのではないかと思い試してみました。

結果、posterlizationとdenoiseをCannyアルゴリズムの前に実施するとうまく行きました。

# denoiseのためのフォーマット変換
img_src = cv2.cvtColor(img_src,cv2.COLOR_GRAY2BGR)

# denoise
img_src = cv2.fastNlMeansDenoisingColored(img_src,None,10,10,7,21)

# ルックアップテーブルの生成

look_up_table = np.ones((256, 1), dtype = 'uint8' ) * 0

for i in range(256):
    if i <= 0:
       look_up_table[i][0] = 0
    elif i < 32:
       look_up_table[i][0] = 32
    elif i < 64:
       look_up_table[i][0] = 64
    elif i < 96:
       look_up_table[i][0] = 96
    elif i < 128:
       look_up_table[i][0] = 128
    elif i < 160:
       look_up_table[i][0] = 160
    elif i < 192:
       look_up_table[i][0] = 192
    elif i < 224:
       look_up_table[i][0] = 224
    else:
       look_up_table[i][0] = 255

#postrization実行
img_src = cv2.LUT(img_src, look_up_table)

#Canny

img_dst = cv2.Canny(img_src,0,0,3)

#bit反転
img_dst = cv2.bitwise_not(img_dst)

f:id:yuyubu:20181227184432p:plain
Canny関数適応前にdenoise処理とポスタリゼーション処理を実施

ですがこのプログラムは私のアイコン画像に対してはうまく動きませんでした。

f:id:yuyubu:20181227194213p:plain
うまく行かなかった例

なぜでしょうか。理由はポスタリゼーションで腕と背景の色が同一化されてしまったためです。 ポスタリゼーションの度合いを変えることで、こちらの画像もうまくエッジ検出できました。

f:id:yuyubu:20181231155411p:plain
うまくいった画像

ですがこのエッジ検出にはまだまだ課題があります。飛び出し坊やくんの

  • 手と顔
  • 手とズボン

の境界が検出できていません。この件に関しましてはまた後日描きたいと思います。

ちなみに今回のエントリのようなエッジ検出は画像の性質を見てうまく動くようなポスタリゼーションを実施する必要があります。