OpenCVを使ったPythonでの画像処理について、ここでは画像の勾配を検出する方法を見ていきます。
画像の勾配とは濃度勾配とも言われ、各画素の値の変化の度合を示します。これは画素の位置を変数とした場合の微分値であると言われますが、ここではその数学的な厳密な意味には触れませんが、エッジのような個所を表す画像と見なしてオブジェクトの検出や認識、輪郭追跡の前処理などに利用されます。
ここでは、cv2.Sobel()、cv2.Laplacian()などを見ていきましょう。
勾配検出フィルタ- cv2.Sobel()、cv2.Laplacian()
いつものように各種ライブラリをインポートします。jupyter notebookを使って見ていきます。
import cv2
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
ここは、お決まりのライブラリのインポートです。
画像を読み込みます。
img = cv2.imread('images/stairs.jpg',0)
imagesフォルダにstairs.jpgを用意して、これをimread()で読み込んでいます。0を指定してグレースケールで読み込みます。
読み込んだ画像を表示する関数を定義してみます。
def display_img(img):
fig = plt.figure(figsize=(8,6))
ax = fig.add_subplot(111)
ax.imshow(img,cmap='gray')
figure()でアスペクト比を指定し、add_subplot()で111を指定して画像を左上の端を基準に表示します。
display_img(img)
画像を表示してみます。
この画像を基準に勾配処理をしていきます。
次のように処理してみます。
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=5)
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=5)
laplacian = cv2.Laplacian(img,cv2.CV_64F)
cv2.Sobel()、cv2.Laplacian()をそれぞれ処理しています。以下で見ていきましょう。
Sobel()
Sobel()関数はノイズ耐性がある処理です。上の処理の第2引数のcv2.CV_64Fは画素の型の種類を与えています。ここでは64ビットの倍精度実数浮動小数点数です。
勾配を計算する方向は、引数yorderとxorderで指定します。第3引数(yorder)を1にするとx方向の勾配、第4引数(xorder)を1にするとy方向の勾配を計算します。第5引数(ksize)に勾配を計算するカーネルのサイズを指定できます。ここでは5を指定しています。
display_img(sobelx)
display_img(sobely)
それぞれ表示するとこうなります。
第3引数を1にした場合。
第4引数を1にした場合。
Laplacian()
Laplacian()関数は、Sobel()を使って計算されるx、yに関する2次微分を足し合わせることで処理すると数学的には説明されますが、細かい意味合いには立ち入りません。
上で処理をした結果だけ見ておきましょう。
display_img(laplacian)
表示するとこうなります。
処理を組み合わせる
これまで、別のところでも色々な処理を見て来ました。ここで、これらの処理を組み合わせて使ってみることにしましょう。
画像を合成する
ここまで扱ったことと、addWeighted()を使って合成してみます。
addWeighted()についてはこちらを参照してください。
このように合成するコードを書いてみました。
blended = cv2.addWeighted(src1=sobelx,alpha=0.5,src2=sobely,beta=0.5,gamma=0)
display_img(blended)
addWeighted()を使って、上で求めたsobelxとsobelyを合成しています。
モルフォロジー勾配
次はモルフォロジー勾配と組み合わせてみます。
モルフォロジー勾配の処理についてはこちらを参照してください。
morphologyEX()で上の合成で作ったblendedを処理してみます。
kernel = np.ones((4,4),np.uint8)
gradient = cv2.morphologyEx(blended,cv2.MORPH_GRADIENT,kernel)
display_img(gradient)
カーネルを4×4にして、cv2.MORPH_GRADIENTでモルフォロジー勾配処理を行います。
2値化 – 閾値処理
今度は画像の2値化処理を組み合わせてみます。
2値化、閾値処理についてははこちらを参照してください。
threshold()を使って色々と処理してみましょう。
ret,th1 = cv2.threshold(img,100,255,cv2.THRESH_BINARY)
display_img(th1)
ここでは処理する画像にimgを使ってみます。閾値をここでは100を指定してみます。2値化の最大値を255として、THRESH_BINARYで処理してみます。
次は、上で処理した画像のgradientを使ってやってみましょう。
ret,th1 = cv2.threshold(gradient,200,255,cv2.THRESH_BINARY_INV)
display_img(th1)
閾値をここでは200にして、THRESH_BINARY_INVで処理してみます。
今度は、上で処理したblendedを使ってみます。
ret,th1 = cv2.threshold(blended,100,255,cv2.THRESH_BINARY_INV)
display_img(th1)
閾値を100に設定し、THRESH_BINARY_INVで処理してみます。
以上、画像の勾配を色々な処理と組み合わせてみました。
最後に
ここではOpenCVを使ったPythonでの画像処理について、画像の勾配を検出して処理する方法を扱いました。
画像の勾配とは濃度勾配とも言われ、エッジのような個所を表す画像と見なしてオブジェクトの検出や認識、輪郭追跡の前処理などに利用されます。
数学的な細かい処理はすっ飛ばして動きだけを扱いました。細かい数学的意味などは検索などで確認してください。(初心者にとっては、ここで説明があるとややこしいだけですよね)
ここでは、cv2.Sobel()、cv2.Laplacian()の処理と、以前に行った処理との組み合わせを見てきました。
ここで扱った処理は、数字の画像認識などにも繋がる処理ですので覚えておきましょう。