スポンサードリンク
こんにちは、ももやまです。
前回の「うさぎでもわかる画像処理 Part02」では、画像処理の中でも最も基本的な画像内の各画素値を自身の画素値のみを使って、一定のルールを用いて変換していく方法(トーンカーブ)について説明していきました。
(トーンカーブ)
トーンカーブを用いた画像処理でも、様々な画像処理ができるのですが、自身の画素値のみを書き換えていく画像処理では出来ることに限りがあります。
そこで今回と次回の2回にわたって、画像内の各画素値を変換していく際に自身の画素値だけでなく、周りの画素の画素値を利用しながら画像処理をしていく方法(フィルタ、空間フィルタリングなどと呼ばれます)について学習していきましょう。

(フィルタ・空間フィルタリング)
今回の記事では、フィルタの中でも線形フィルタに着目してみていきます。
目次 [hide]
スポンサードリンク
1. 線形フィルタのいろは
(1) 線形フィルタとは
画像処理の世界で出てくるフィルタは、
- 線形フィルタ
- 非線形フィルタ
の2つに分けることができます。
さらに、入力画像
例えば、下のフィルタは3×3行列で表されていますね。

(2) 線形フィルタの計算の様子を見てみよう
では、(1)の例で出したフィルタ

このように線形フィルタでは、着目した画素とその周囲の各画素値ごとに対応するフィルタの係数を掛け、それらをすべて足したものを着目した画素の新たな画素値とする計算を各画素ごとに行っているのです!

※ 端の画素をどうするかについては、様々な考え方がありますが、本記事では端の画素は画像処理をしない(=画素値0)としたいと思います。
(3) 例題で確認!
図1で表される元画像、および図2で示されるフィルタ(a), (b)がある。
(1), (2)の問いに答えなさい。


(1) フィルタ (a) を適用したときの、図3のアに当てはまる画素値を答えなさい。ただし、小数点以下を四捨五入し、整数値で答えること。
(2) フィルタ (b) を適用したときの、図3のイに当てはまる画素値を答えなさい。ただし、小数点以下を四捨五入し、整数値で答えること。

(1)
フィルタ (a)

よって [ ア ] の画素値は181となる。
(2)
フィルタ (b)


よって [ イ ] の画素値は149となる。
(4) 線形フィルタの演算をする関数(ソースコード)
実際に入力画像と線形フィルタを設定すると、画像処理を行う関数をPythonとMATLABで作成しました。
Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | def applyFilter(img,filt): # 入力画像のサイズ取得 img_row = img.shape[0] img_col = img.shape[1] # フィルタのサイズ取得 (適さないフィルタサイズの場合はエラーを返す) filt_row = filt.shape[0] filt_col = filt.shape[1] if (filt_row % 2 == 0) or (filt_col % 2 == 0): print("フィルタサイズ設定に誤りがあります。") return img # 結果画像初期化 result_img = np.zeros( (img_row,img_col) ) # フィルタの中心部分算出 filt_mid = int(filt_row / 2) # フィルタ適用 for row in range(img_row): for col in range(img_col): if (row - filt_mid < 0) or (col - filt_mid < 0) or ( (row + filt_mid >= img_row) ) or ( (col+ filt_mid >= img_col) ): continue # 端の画素は無視 (画素値0) tmp_result = img[row - filt_mid:row + filt_mid + 1,col - filt_mid:col + filt_mid + 1] # 計算に使う周りの画素取得 tmp_result = tmp_result * filt result_img[row,col] = round(np.sum(tmp_result)) return result_img |
MATLAB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | function [result_img] = applyFilter(img,filt) img_row = size(img,1); img_col = size(img,2); filt_row = size(filt,1); filt_col = size(filt,2); if mod(filt_row,2) == 0 || mod(filt_col,2) == 0 disp("フィルタサイズ設定に誤りがあります。"); result_img = img; return end result_img = zeros(img_row,img_col,'uint8'); filt_mid = uint32(filt_row / 2) - 1; % MATLABは要素が1スタートなのでPythonに慣れている人は注意! for row = 1:img_row for col = 1:img_col if (row - filt_mid < 1) || (col - filt_mid < 1) || (row + filt_mid > img_row) || (col + filt_mid > img_col) continue % 端は無視 (画素値0とする) end tmp_result = img(row - filt_mid:row + filt_mid,col - filt_mid:col + filt_mid); % 計算に使う周りの画素取得 tmp_result = double(tmp_result) .* filt; result_img(row,col) = uint8(sum(tmp_result,'all')); end endend |
フィルタについての確認ができたところで、ここからは画像処理の世界によく出てくる代表的なフィルタを見ていきましょう。
スポンサードリンク
2. 平滑化
ここでは、元の画像の画素値変化(濃淡変化)を小さくするフィルタを紹介します。
平滑化フィルタを適用することで、画像の濃淡変化を小さくした画像(=元画像をぼかした画像)を生成することができます。
(1) 平均化フィルタ (移動平均フィルタ)
各画素を「自分自身とその周りの画素値の平均値」を新たな画素値とするフィルタです。
「自分自身とその周りの画素値の平均」をとるため、隣り合う画素同士の画素値の差が減り、濃淡変化が緩やかになるため、元画像をぼかした画像が生成されます。
例えば下の変換は、自分+周り1画素の平均値をとった3×3の平均化フィルタを表します。

「自分+周り2画素」をとった5×5のフィルタを使った平均化も見てみましょう。

2つの変換を比べてみると、より広い周囲の画素値の平均をとった5×5フィルタの方が、よりぼかされた画像が生成されているのが特徴です。

(2) 加重平均化フィルタ [重み付き平均化]
平均化をする際に単純に平均化するのではなく、下のように「自分自身の画素(フィルタの中心)に近いほど重み大、遠いほど重み小」なフィルタを使って平均化をすることがあります。

このようなフィルタのことを加重平均化フィルタと呼び、加重平均化フィルタを使って平均化をすることを重み付き平均化と呼びます。
また、フィルタの重みをガウス分布(正規分布)
(3) 特定方向への平滑化
特定方向へ画像をぼかすことができるフィルタもあります。
(i) 横方向へ平滑化
横方向のみに対して画素値の平均を取っていきます。

例えば上の例の場合、自分自身の画素と横±10画素の画素値の平均
※注意(以後同様)
が元画像、 が変換後の 行 列の画素値を表しています。- 横方向を
、縦方向を としています。
(ii) 縦方向へ平滑化
縦方向のみに対して画素値の平均を取っていきます。

例えば上の例の場合、自分自身の画素と縦±10画素の画素値の平均
(iii) 斜め方向へ平滑化
左上方向から右下方向に対して画素値の平均を取っていきます。

例えば上の例の場合、基準に左上方向から右下方向に向かって±自分自身の画素10画素の画素値の平均
スポンサードリンク
3. 鮮鋭化
「3. 平滑化」で出てきたフィルタ、 元の画像の画素値変化(濃淡変化)を小さくすることで、元画像をぼかした画像を生成するフィルタでしたね。
鮮鋭化は、「3. 平滑化」とは反対に元の画像の画素値変化(濃淡変化)を大きくする変換をするフィルタです。
鮮鋭化フィルタを適用することで、画像の濃淡変化を大きくした画像(=元画像のエッジを強調した画像)を生成することができます。
具体的には、各画素ごとに、「自分自身の画素を定数倍(=強調)し、周りの画素値を一定量引いたもの」を新たな画素値にしていきます。
「自分自身の画素値を定数倍+周りの画素値を一定値引く」ため隣り合う画素同士の画素値の差が増え、濃淡変化が大きくなるため、元画像のエッジを強調した画像が生成されます。

なお、「3. 平滑化」のときと同じように、範囲が広いフィルタの方が、よりフィルタが強く作用します。

4. 1次微分によるエッジ抽出
皆さんは高校時代に「微分」について学びましたね。
ここで、「画像処理の世界でも微分って出てくるの?」と思った人も多いと思います。実は、微分
(1) 画素の微分とは
ある関数
日本語でいうと、「
なので、画像を微分すると「画素値の変化の度合い」が得られそうな感じがしますね。さらに、「画素値の変化の度合い」を得ることで、特に画素値が変化している部分(=エッジ)を得ることができます。
しかし、微分をフィルタとして取り入れるためには、以下の2つの問題を解決する必要があります。
- 画像
を関数として見る場合、1変数 ではなく、横方向 、縦方向 の2変数関数 で表現する必要があること という極限操作が画像処理の世界ではできないこと
というわけで、1つずつ順番に解決していきましょう。
(i) 2変数関数の微分とは
2変数関数
※ 偏微分についてもっと知りたい人は、偏微分についての記事のリンクを貼っているので是非こちらのリンクをご覧ください。
[注意]
単に
を で微分した場合 → を で微分した場合 →
と表記することにします[1]なお、偏微分を正式に表す場合は、
(ii) 画像処理での微分の表現
画像処理は、1画素単位での処理となるため、
そこで、画像処理で微分を表現する場合は
実際に
[
[
(2) 1次微分フィルタ
(1)で導出した式
| 方向 | 式 | フィルタ |
|---|---|---|
| 横方向( | ||
| 縦方向( |
[横方向 (

横方向の1次微分フィルタを適用すると、横方向の画素値変化が可視化されるため、出力画像には縦方向のエッジが強く出てきます。
一方、縦方向の画素値変化は可視化されないため、横方向のエッジは出力画像にあまり出てきません。

[縦方向 (

縦方向の1次微分フィルタを適用することで、縦方向の画素値変化が可視化されるため、出力される画像には横方向のエッジが強く出てきます。
一方、横方向の画素値変化は可視化されないため、縦方向のエッジは出力画像にあまり出てきません。

(3) 様々な1次微分フィルタ
画像の微分は、各画素ごとに「隣り合う画素の差分を取る」ことで求めることができるのですが、差分を取り方として、
f_x(x,y) = f(x,y) - f(x-1,y)
\]
そのため、1次微分フィルタを下のように書くこともできます。
| 方向 | 式 | フィルタ |
|---|---|---|
| 横方向( | ||
| 縦方向( |
また、2つの差分のとり方
この方法の場合の1次フィルタは、下のようになります。
| 方向 | 式 | フィルタ |
|---|---|---|
| 横方向( | ||
| 縦方向( |
このように、同じ「横(縦)方向の1次微分」でも、フィルタの書き方が3通りもあるのです。

※ 3番目のフィルタの係数
5. プレヴィットフィルタ
(1) 1次微分フィルタの欠点
「5. 1次微分フィルタ」では、エッジ(=画素値が特に変化している部分)を得ることができるのでしたね。
しかし、同時に画像に含まれるノイズも1次微分フィルタにより強調されてしまいます。
そこで、
(2) プレヴィットフィルタの仕組み [横方向]
1次微分フィルタと同じようにプレヴィットフィルタにも横方向(
横方向の1次微分フィルタでは、次の2つの式の
プレヴィットフィルタでは、この2つの式に加え、縦方向の前後の画素
これら6つの式の平均
をとったフィルタが、プレヴィットフィルタ

(3) プレヴィットフィルタの仕組み [縦方向]
縦方向のプレヴィットフィルタも、横方向のときと同じように1次微分で使った2つの式
合計6つの式の平均
をとったものが縦方向のプレヴィットフィルタとなります。

6. ソーベルフィルタ
横/縦方向のブレットフィルタでは、下の6種類の方法で「隣り合う画素の差分を取る」ことをし、それらの平均をとっていましたね。
横方向ブレットフィルタ:平均化する数式一覧
| 着目する | 数式 |
|---|---|
| | |
縦方向ブレットフィルタ:平均化する数式一覧
| 着目する | 数式 |
|---|---|
ソーベルフィルタでも、同じように6種類の方法で「隣り合う画素の差分を取る」のですが、ソーベルフィルタの場合は、着目している画素と同じ方向に対して2倍の重みをつけてから平均化をします。
横方向ソーベルフィルタ:平均化する数式一覧
| 着目する | 数式 |
|---|---|
| | |
縦方向ブレットフィルタ:平均化する数式一覧
| 着目する | 数式 |
|---|---|
2倍の重みをつけたあとは、平均を取ればOKです。
[横方向ソーベルフィルタ]
導出)
結果)
変換例)

[縦方向ソーベルフィルタ導出]
結果)
変換例)

7. 2次微分フィルタ
(1) 2次微分が表すものとは
2次微分は、微分したもの
日本語で説明すると
の変化量を表したものが → 1次微分 の変化量を表したものが → 2次微分
といえますね。
そのため、画像を2次微分すると「画素値の変化度合いの大小」が得られそうな感じがしますね。「画素値の変化度合いの大小」を得ることで、特に画素値が変化している部分(=エッジ)を1次微分に比べて正確に得ることができます。
(2) 2次微分フィルタの導出
ここからは、(3×3の)2次微分フィルタを導出してみましょう。
方向 (縦方向) の2次微分
2変数関数の
ただし、画像処理の世界では極限計算
ここで、1次微分
よって、2次微分を
[実際に横方向の2次微分フィルタを適用すると…?]

横方向の2次微分フィルタを適用することで、横方向の画素値変化が可視化されます。可視化された画像には縦方向のエッジが入っているのが特徴です。
方向 (横方向) の2次微分
ただし、先程も言った通り画像処理の世界では極限計算
ここで、1次微分
よって、2次微分を

縦方向の2次微分フィルタを適用することで、縦方向の画素値変化が可視化されます。可視化された画像には横方向のエッジが入っているのが特徴です。
8. ラプラシアンフィルタ
「7. 2次微分フィルタ」では、横方向・縦方向それぞれの画素値変化の度合いを可視化することができますが、一度に「横方向と縦方向両方」の画素値の度合いを可視化することができます。
そこで、
ここで、

9. 練習問題
最後に、練習問題で軽くフィルタについておさらいしておきましょう。
ある画像に対して、次の(1)~(3)で示されるフィルタを加えたときの出力画像を表した説明として、正しいものを1つずつ選び番号で答えなさい。

[選択肢]
- 元画像のエッジが強調された画像が出力された。
- 元画像がぼやけた画像が出力された。
- 元画像のエッジ部分だけが出力された。
[解説]
(1) 2 → 平滑化
(2) 1 → 鮮鋭化
(3) 3 → ラプラシアンフィルタ
関連広告・スポンサードリンク
