【Google Colab】OpenCVで画像をペンシルスケッチ変換
はじめに
インスタグラムをはじめ、SNSで写真をシェアする方も多いのではないでしょうか。
その際、アプリを使用して画像を加工することもあるかと思います。
明るさや色味の調整、肌をキレイに見せるためのレタッチ、写真をスケッチ風に加工するなど、様々な機能があります。
今回は、OpenCVを用いて簡単な鉛筆画風の画像加工に挑戦してみました。
OpenCVで画像をペンシルスケッチ変換
環境
環境はGoogle Colaboratoryを使用します。
Pythonのバージョンは以下です。
import platform
print("python " + platform.python_version())
# python 3.6.9
画像の表示
では、早速コードを書いていきましょう。
まずは、画像の表示に必要なライブラリのインポートと設定を行います。
import cv2
import matplotlib.pyplot as plt
import matplotlib
%matplotlib inline
matplotlib.rcParams['image.cmap'] = 'gray'
サンプルの画像も用意しておきましょう。
今回は、Pixabayのフリー画像を使用します。
それでは、用意したサンプル画像を表示してみましょう。
image = cv2.imread(input_file) # input_fileは画像のパス
plt.figure(figsize=[10,10])
plt.axis('off')
plt.imshow(image[:,:,::-1])
結論
それではOpenCVを使用して、この画像を鉛筆画風に加工してみましょう。
元画像とあわせて表示してみました。
def pencilSketch(image):
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
median = cv2.medianBlur(gray, 5)
laplacian = cv2.Laplacian(median, cv2.CV_8U, ksize=5)
_, thresh = cv2.threshold(laplacian, 100, 255, cv2.THRESH_BINARY_INV)
pencilSketchImage = cv2.cvtColor(thresh, cv2.COLOR_GRAY2BGR)
return pencilSketchImage
pencilSketchImage = pencilSketch(image)
plt.figure(figsize=[20,10])
plt.subplot(121);plt.imshow(image[:,:,::-1]);plt.axis('off')
plt.title("original image")
plt.subplot(122);plt.imshow(pencilSketchImage[:,:,::-1]);plt.axis('off')
plt.title("pencil sketch image")
鉛筆画風に加工する処理は、pencilSketch関数として定義しています。
pencilSketch関数の処理の流れは以下になります。
- グレースケール
- 平滑化(medianBlur)
- 画像の微分(Laplacian)
- 二値化
各処理の説明
以下、各処理について説明していきます。
グレースケール
グレースケール(Gray Scaleまたはgrayscale)とは、色の表現方法の一種です。
簡単に言うと、カラー画像を白黒画像にすることです。
グレースケールのコードは以下です。
image = cv2.imread(input_file) # 元画像の読み込み
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # グレースケール
plt.figure(figsize=[20,10])
plt.subplot(121);plt.axis('off');plt.imshow(image[:,:,::-1])
plt.subplot(122);plt.axis('off');plt.imshow(gray)
cv2.cvtColorを使用して、カラーからグレースケールに変換しています。
cv2.cvtColorの用法は以下です。
- dst = cv2.cvtColor(src, code)
- src:インプット画像
- dst:アウトプット画像
- code:色空間の変換方法
平滑化(medianBlur)
平滑化(へいかつか)、あるいはスムージング処理とは、簡単に言うと画像をぼかすことです。
画像をぼかすということは、画素値の変化を滑らかにすることとも言えます。
ノイズやエッジは、画素値の急激な変化です。
平滑化により、ノイズやエッジを消したり、目立たなくすることができます。
平滑化にはいくつかの方法が存在し、medianBlurはそのうちの一つです。
medianとは「中央値」のことで、指定したカーネル内に含まれる画素から中央値を取り出し、その値でカーネル全体を塗りつぶします。
※「カーネル」とは、着目する画像の領域ですが、難しければ「箱」のイメージで構いません。
平滑化についての詳細は、こちらを参照下さい。
medianBlurのコードは以下です。
median = cv2.medianBlur(gray, 5) # medianBlur
plt.figure(figsize=[20,10])
plt.subplot(121);plt.axis('off');plt.imshow(gray)
plt.subplot(122);plt.axis('off');plt.imshow(median)
画像がぼやけているのが確認できます。
cv2.medianBlurを使用して、グレースケールの画像をぼかしました。
cv2.medianBlurの用法は以下です。
- dst = cv2.medianBlur(src, ksize)
- src:インプット画像
- dst:アウトプット画像
- ksize:カーネルサイズ(ただし、3以上の奇数)
画像の微分(Laplacian)
画像の微分では、画素値の変化が急激な部分、つまりエッジを検出します。
画像の微分にはいくつかの方法が存在し、Laplacianはそのうちの一つです。
Laplacianフィルターは二回微分であり、一回微分のSobelフィルターより細かいエッジ検出をしたい場合に有効です。
画像の微分についての詳細は、こちらを参照下さい。
Laplacianのコードは以下です。
laplacian = cv2.Laplacian(median, cv2.CV_8U, ksize=5) # Laplacian
plt.figure(figsize=[20,10])
plt.subplot(121);plt.axis('off');plt.imshow(median)
plt.subplot(122);plt.axis('off');plt.imshow(laplacian)
エッジが検出されていることが確認できます。
cv2.Laplacianを使用して、画像を微分しました。
cv2.Laplacianの用法は以下です。
- dst = cv2.Laplacian(src, ddepth, ksize)
- src:インプット画像
- dst:アウトプット画像
- ddepth:アウトプット画像の型(ビット深度)
- ksize:カーネルサイズ(奇数)
二値化
二値化とは、画像を白と黒の2つの値(二値)に変換する処理のことです。
白と黒の間も段階的に表示するグレースケールとは異なります。
閾値(しきいち、threshold)と呼ばれる値を決め、画素の値がそれより大きければ白、小さければ黒に変換します。
画像の二値化にはいくつかの方法が存在します。
今回は、一般的な二値化を行いました。
二値化についての詳細は、こちらを参照下さい。
二値化のコードは以下です。
_, thresh = cv2.threshold(laplacian, 100, 255, cv2.THRESH_BINARY_INV) # 二値化
plt.figure(figsize=[20,10])
plt.subplot(121);plt.axis('off');plt.imshow(laplacian)
plt.subplot(122);plt.axis('off');plt.imshow(thresh)
画素値が比較的高いものだけを残すことができました。
cv2.thresholdを使用して、画像を二値化しました。
cv2.thresholdの用法は以下です。
- ret, dst = cv2.threshold(src, thresh, maxVal, method)
- src:インプット画像(グレースケール)
- ret:使用した閾値の値
- dst:アウトプット画像
- thresh:閾値
- maxVal:最大値(閾値以上の値)
- method:閾値処理
- cv2.THRESH_BINARY
- cv2.THRESH_BINARY_INV など
今回、閾値は100としています。
今回、戻り値の閾値(100)は使用しないので、_(アンダースコア)としています。
閾値処理では、cv2.THRESH_BINARY_INVを使用して白黒反転しています。
cv2.THRESH_BINARY_INVは、閾値(今回100)を超えるピクセルは0(黒)に、それ以外のピクセルはmaxVal(今回255)にする処理です。
まとめ
いかがだったでしょうか。
今回は、OpenCVを使用して鉛筆画風のスケッチに挑戦してみました。
処理のフローをおさらいしておきます。
- グレースケール
- 平滑化(medianBlur)
- 画像の微分(Laplacian)
- 二値化
閾値やカーネルサイズなどパラメーターを変更することで、線の細かさなどを変えることができます。
パラメーターを色々と変えて、画像を出力してみると面白いと思います。
Author And Source
この問題について(【Google Colab】OpenCVで画像をペンシルスケッチ変換), 我々は、より多くの情報をここで見つけました https://qiita.com/shoku-pan/items/aed8dbbf6cde77658d57著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .