【Python】OpenCVでエッジ検出 – Canny法

Pythonの応用
スポンサーリンク

OpenCVを使ったPythonでの画像処理について、ここではエッジ検出(Edge Detection)について扱っていきます。

エッジ検出とは画像から端の枠線を取り出す手法です。ここではその代表的な手法であるCannyエッジ検出を扱います。

このCanny法は、ガウシアンフィルタで画像を平滑化してノイズを除去し、sobelフィルタでエッジの勾配の大きさと方向を求め、勾配方向と大きさを元に細線化することでエッジと無関係の部分を取り除き、 閾値化でエッジを検出するという流れです。OpenCVを使えばこれらを一度の処理で行えます。

ではエッジ検出を行っていきましょう。

スポンサーリンク

Cannyエッジ検出

エッジ検出のCanny法はCanny()で処理は簡単に行えます。

jupyter notebookを使って処理をしていきたいと思います。まずは各種ライブラリのインポートです。

import cv2
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

これはおきまりのインポート。

ここで使う画像を読み込みます。

img = cv2.imread('images/golden-retriever.jpg')
plt.imshow(img)

imread()で画像を読み込み、imshow()で表示します。

カラーは変換していません。グレースケールで読み込んでも良いと思います。

Canny()を使ってエッジ検出をしてみます。

edges = cv2.Canny(image=img, threshold1=127, threshold2=127)
plt.imshow(edges)

Canny()に画像を渡し、第2、第3引数に閾値を渡します。最小値、最大値の閾値を渡しますが、ここではどちらも0と255の中間である127を設定してみました。

imshow()で画像を表示します。

閾値を変えて再度処理してみます。

edges = cv2.Canny(image=img, threshold1=0, threshold2=255)
plt.imshow(edges)

閾値を0と255の両端の値をここでは使って検出してみます。

この閾値の最小値と最大値を調整していけばエッジの表現が変わっていくということになります。

そこで、画像の画素データの中央値をnp.median()を使って求めて、そこから閾値を調整してみることにします。

med_val = np.median(img) 
lower = int(max(0, 0.7* med_val))
upper = int(min(255,1.3 * med_val))

median()を使って中央値を求めます。閾値の下限の値をmax()を使って、0か中央値の70%の値を指定してみます。上限は255か中央値の30%増しの値を指定してみます。

edges = cv2.Canny(image=img, threshold1=lower , threshold2=upper)
plt.imshow(edges)

先ほど求めたlowerとupperをCanny()に渡しして検出してみます。

多少違っているのはわかりますね。でも境界をはっきりさせるにはもう少し別の処理も加える必要もあるようです。

ここで、ぼかし処理も加えてみます。小さなエッジは境界を捉えるのに不要でもあるので、それにはぼかしが役に立ってきます。

ぼかし、画面の平滑化についてはこちらで扱いました。

【Python】OpenCVで画像のぼかしと平滑化
OpenCVを使ってPythonで画像を処理する方法について、ぼかしや平滑化について扱います。filter2D()、blur()、GaussianBlur()、medianBlur()、bilateralFilter()の処理を見て行きます。

ここではblur()を使ってみます。

blurred_img = cv2.blur(img,ksize=(5,5))
edges = cv2.Canny(image=blurred_img, threshold1=lower , threshold2=upper)
plt.imshow(edges)

blur()で使う箱型フィルタのカーネルサイズは5×5にしてみました。このぼかし処理を行った画像をCanny()で処理しています。

表示するとこうなります。

だいぶ境界が出てくるようになりました。

あとは色々と閾値を操作して最終的なエッジ検出の画像を求めるだけです。カーネルサイズを7×7などにしてみるのもいいでしょう。

edges = cv2.Canny(image=blurred_img, threshold1=lower , threshold2=upper+50)
plt.imshow(edges)

ここではupperの値に50を加えてやってみます。

だいぶエッジ検出らしくはなったとは思います。扱う画像によって違ってくるので、色々と数字を調整して試してみることが必要ですね。

スポンサーリンク

最後に

ここではOpenCVを使ったPythonでの画像処理について、ここではエッジ検出(Edge Detection)について扱いました。

エッジ検出とは画像から対象の端の枠線を取り出す手法で、その代表的な手法であるCannyエッジ検出をここでは触れました。

フィルターや閾値を操作して、目的の検出ができるように色々と試していく必要があります。

タイトルとURLをコピーしました