画像中の明るさが急に変化する部分を抽出するのがエッジ抽出。
連続した値の場合であれば、微分によって抽出したい部分の接線を求めてその傾きから変化の具合を読み取ることができる。画像の場合は連続値ではないため、画素値間の差をとることで微分の近似として扱う。
1次微分フィルタ
エッジを抽出する微分フィルタの基本は以下のようなもの
\left(
\begin{matrix}
0 & 0 & 0 \\
0 & -1& 1 \\
0 & 0 & 0
\end{matrix}
\right)
,
\left(
\begin{matrix}
0 & 0 & 0 \\
-1 & 1& 0 \\
0 & 0 & 0
\end{matrix}
\right)
注目画素とその左隣との左隣との差を取るか、右隣との差を取るかでちょっと変わってくる。また、左右両方の平均値をとってそれを微分の値とするという流派もあるみたい。こっちのほうが左右の画素値の変化の傾きをとっているというのが分かりやすいかもしれない。計算しやすさを求めて -1/2の要素を-1に、1/2の要素を1にとるものもある。ただしその時に出てきた微分の値は2倍になる。
\left(
\begin{matrix}
0 & 0 & 0 \\
-1/2 & 0& 1/2 \\
0 & 0 & 0
\end{matrix}
\right)
これらのフィルタは左右の画素値から微分値を求めていたので、横方向の微分値だけが出てくる。画素値をプロットしてエッジを見えるようにすると、エッジは縦方向のもののみがでてくることになる。横方向のエッジを抽出したいのであれば、縦方向の微分値が必要になるため、縦方向の微分を求められる以下のようなフィルタを使うことになる。
\left(
\begin{matrix}
0 & 0 & 0 \\
0 & -1& 0 \\
0 & 1 & 0
\end{matrix}
\right)
,
\left(
\begin{matrix}
0 & -1 & 0 \\
0 & 1& 0 \\
0 & 0 & 0
\end{matrix}
\right)
,
\left(
\begin{matrix}
0 & -1/2 & 0 \\
0 & 0& 0 \\
0 & 1/2 & 0
\end{matrix}
\right)
Prewittフィルタ
じゃあこの行列を使えばオールオッケーかと言うとそうでもない。上の微分フィルタだと、画像に含まれるノイズもそのまま明るさの急な変化として抽出されてしまう。なので、ノイズを低減しながらエッジを抽出するといううまい方法がないといけない。そのために作られたのがPrewittフィルタ。
横方向の微分値を求めれば、縦方向のエッジが抽出できる。なので縦方向に平滑化を施してノイズを低減してその後に微分をする。
\left(
\begin{matrix}
1 \\
1 \\
1
\end{matrix}
\right)
\left(
\begin{matrix}
-1 & 0 & 1
\end{matrix}
\right)
=
\left(
\begin{matrix}
-1 & 0 & 1 \\
-1 & 0 & 1 \\
-1 & 0 & 1
\end{matrix}
\right)
縦方向の場合はこれらの値を転置したものを使う。
ぼかしを微分を1つの行列に詰め込んでやる必要はあるのか?確かに1つの行列に詰め込んだほうが簡単で良さそうだけど、別々にしたって良いんじゃないのか?という疑問もあるけどそこら辺はこちらを参照。
http://nodamushi.hatenablog.com/entry/20140102/1388669333
Sobelフィルタ
Prewittフィルタに中央に重みをつけた上での平均化を行ったのがSobelフィルタ
\left(
\begin{matrix}
1 \\
2 \\
1
\end{matrix}
\right)
\left(
\begin{matrix}
-1 & 0 & 1
\end{matrix}
\right)
=
\left(
\begin{matrix}
-1 & 0 & 1 \\
-2 & 0 & 2 \\
-1 & 0 & 1
\end{matrix}
\right)
重み付けをしているあたりはSobelフィルタのほうがPrewittフィルタよりも精度が高そうな感じがする。OpenCVにもSobelフィルタの関数しかないあたり実際そうなんだろうけど、それが果たしてどれくらいなのかは不明。
ラプラシアンフィルタ
微分の微分をとれば2次微分になってさらに詳しい変化の情報が得られる。PrewittフィルタやSobelフィルタは左右の画素値の差分をとっていたので1次微分になるわけなので、微分の微分をとるなら差分の差分をとることで近似できることになる。
一番最初に出てきた微分フィルタ同士の差を取れば差分の差分をとることになって2次微分フィルタが出来上がる。
\left(
\begin{matrix}
0 & 0 & 0 \\
1 & -1 & 0 \\
0 & 0& 0
\end{matrix}
\right)
-
\left(
\begin{matrix}
0 & 0 & 0 \\
0 & 1 & -1 \\
0 & 0 & 0
\end{matrix}
\right)
\equiv
\left(
\begin{matrix}
0 & 0 & 0 \\
1 & -2 & 1 \\
0 & 0 & 0
\end{matrix}
\right)
さらにラプラシアンを考えれば、ラプラシアンは
\frac{\partial^2 f}{\partial x^2} + \frac{\partial^2 f}{\partial y^2}
で表せるので、x方向の2次微分とy方向の2次微分を足し合わせればいいことになる。なので上の2次微分のフィルタをあわせて以下のようになる。ラプラシアンはよく分かってないけどなんかこうなるらしい…
\left(
\begin{matrix}
0 & 1 & 0 \\
1 & -4 & 1 \\
0 & 1 & 0
\end{matrix}
\right)
参考:ラプラシアンフィルタとSobelフィルタ(とその他のフィルタ)の違い。
https://www.researchgate.net/post/What_are_the_differences_in_first_order_derivative_edge_detection_algorithms_and_second_order_edge_detection_algorithms