微分オペレータを使ったエッジ検出の方法と実装

目次

はじめに

今回はエッジ検出フィルタを紹介します。 エッジ検出フィルタとは(edge detect filtering)とは、画像中の画素値が急激に変わる部分を取り出す処理です。もう少しわかりやすく説明すると、画像の輪郭を検出あるいは抽出する処理のようなことです。

ここではエッジ検出の流れと、エッジ検出の1つである微分オペレータの実装について紹介します。

エッジ検出のイメージ

まずは、画像の境界部分がどのように検出されるのか見ていきましょう。 画像の領域境界(輪郭部分)は画素値の変化が大きくなると先ほど述べましたが、その境界部分を検出するために画素値に対して微分演算を行うことにより画像の境界部分を検出します。 具体的な流れは以下の通りです。 ① 画素値に対して微分演算を行う。 ② 画素の勾配を求める。 ③ 大きな勾配を持つ部分を抽出する。(=境界部分の抽出)

例えば図1.1のような周辺が黒(画素値0)、中心に白(画素値255)が集まる正方形の画像があるとします。この画像を例にとって微分演算のイメージを掴んでいきましょう。

図1.1
まず、 y=3におけるx軸方向の画素値 I\left( x,3\right)の変化は図1.2(a)のようになります。 そして、  I'\left( x,3\right) =I\left( x+1,3\right) -I\left( x,3\right) として微分演算を行うと、図1.2(b)のように輪郭部分の画素値が大きくなることが分かると思います。
  
左:図1.2(a) 右:図1.2(b)

また、x軸方向の微分をオペレータで表現した際、図1.4のように3種類となります。それぞれの特徴として、(a)の微分オペレータは注目画素とその右隣との画素値の差を、(b)は注目画素とその左隣との差を、(c)は注目画素とその両隣との画素値の差の平均を、それぞれ注目画素の値として出力します。

図1.4 横方向微分オペレータ K=\left( m,n\right)の例

例えば図1.1に図1.4(a)の微分オペレータを適用させた際には図1.5で示す通り、横方向に注目画素との差を出力していることが分かります。

図1.5 微分オペレータの適用結果

次にこの微分オペレータを実装し、画像がどう変化するかを確認していきます。

微分オペレータの実装

早速Pythonで微分オペレータを実装し、図1.6(a)のエッジを検出していきましょう。結果は、図1.6(b)で示している通り、元画像の縦方向の輪郭をうまく検出することができました。

# 入力画像をグレースケールに変換
img_src = cv2.imread(file_src, cv2.COLOR_BGR2GRAY)

# カーネルの作成(x軸方向の輪郭検出)
# y軸方向の輪郭検出の場合、np.array([[-1], [0], [1]])
kernel = np.array([[-1, 0, 1]])


# 微分計算した画像の作成とデータ型の変換
img_tmp = cv2.filter2D(img_src, cv2.CV_32F, kernel)
img_dst = cv2.convertScaleAbs(img_tmp)

    
図1.6(a) エッジ検出前の画像      図1.6(b) 縦方向のエッジ検出の結果

まとめ

前半にエッジ検出(画像の境界部分の検出)の流れを図とグラフを用いて紹介し、後半に微分オペレータをPythonで実装して実際にある画像の縦方向のエッジを検出しました。 実装自体は簡単にできますが、その中身を理解するとより理解が深まると感じたので、他の画像処理を学ぶ際にも意識していきたいと思います。