※ replitで「You've used up all your Development time」というメッセージが出た人は
こちらを参考にして新しくreplitのアカウントを作ってください。
※ 本題に入る前に、必ず動画の
連絡
を見てください。
- リサイズとノイズ追加
- 移動平均フィルタ
- ガウシアンフィルタ
- メディアンフィルタ
- 双方向フィルタ
元画像の選定
今回は元画像にノイズを入れて、各種のフィルタでそれがどのように変わるかを確認する。また、フィルタによるエッジのぼかされ方の違いも確認したい。
そのため、元画像には「ほぼ単色のエリア」と、「エリア間のくっきりしたエッジ」が含まれるものを選ぶ。
(これは解説動画で使っているサンプル画像なので、課題には使わないこと)
くっきりしたエッジが必要なので、元画像の解像度が極端に低いものは不適切。画像検索のサムネイルをそのままダウンロードしてしまうと縦横が数100ピクセル程度の粗い画像になってしまうので、
その画像があるページにアクセスしてそこからダウンロードするとよい。
移動平均フィルタ
平滑化の処理のうちのひとつである移動平均フィルタでは、あるピクセルのまわりのピクセルの色を平均して変換後の画像のピクセルの色を決める
(実際は赤・緑・青の成分それぞれについて平均をとるが、下の図では話を簡単にするため単色であらわしている)。
このような考慮する範囲のことを
カーネルと呼び、OpenCVで画像 img に3x3の範囲をカーネルにした移動平均フィルタをかけるには、blur関数の第2引数に (3, 3)
を入れて指定する。
cv2.blur(img, (3, 3))
カーネルを5x5の範囲に広げると、3x3のときよりもぼやけ方が強くなる。
cv2.blur(img, (5, 5))
カーネルをもっと大きくすることもできるが、元のピクセルを中心にして上下・左右に対称にするため、一般には奇数の値を指定する。
ガウシアンフィルタ
移動平均フィルタでは周辺のピクセルの色を混ぜて使うので、カーネルを大きくするとエッジがぼやけてしまう。これは、元ピクセルからの距離と関係なく色を混ぜてしまっているためである。
もう少し工夫して、中心のピクセルの影響は強く、そこから離れるにしたがって影響が弱くなるように「重みをつけた平均」を取れば、カーネルを大きくしてもぼやけ方を抑えられる。
このようなフィルタにはいくつか種類があるが、ガウシアンフィルタではその名の通り「ガウス関数」を重みとして使用する。
ガウス関数とは
\(
\begin{eqnarray}
\frac{1}{\sqrt{2\pi\sigma^2}}\exp\left(-\frac{x^2+y^2}{2\sigma^2}\right)
\end{eqnarray}
\)
のような形をした関数 (expはexponentialの略で、ネイピア数 \(e\) の累乗) である。
下のグラフはカーネルが9x9の場合の2種類の \(\sigma\)
についてガウス関数の値を示したものである。\(\sigma\) が大きくなると横に広がり (青)、小さくなると尖った形になる (赤)。
\(\sigma\) が小さいと色の計算で中心の画素の影響がより大きくなるので、ぼやけ方は小さくなり、\(\sigma\) が大きくなると中心と周辺の影響の差が少なくなるので移動平均の結果に近く、ぼやけ方は大きくなる。
OpenCVのガウシアンフィルタの処理を行うのはGaussianBlur関数で、画像 img にカーネルが 9x9, \(\sigma\) が1のフィルタをかける処理は以下の通り。第3引数が \(\sigma\)
に相当する。
cv2.GaussianBlur(img, (9, 9), 1)
メディアンフィルタ
メディアンフィルタでは、平均を取るのではなく、カーネル内のピクセルの色成分の中央値を取って出力画像の色を決める。多くの場合、
ノイズは周囲のピクセルとは大きく色が異なっているので、これが中央値になることはほとんどなく、1ピクセルだけの孤立したノイズならほとんどのケースできれいに消せる。
カーネルが5x5の場合なら、考慮する25個のピクセルの色成分を昇順に並べ替え、中央番目、つまり13番目 (プログラミングの数え方的には12番目) のピクセルの色を採用する。
(図は赤成分。緑・青成分についても同様にして中央番目の値を使う)

OpenCVのメディアンフィルタの処理を行うのはmedianBlur関数で、画像 img にカーネルが 5x5のフィルタをかける処理は以下の通り。
cv2.medianBlur(img, 5)
双方向フィルタ
ガウシアンフィルタでは、中心のピクセルからの距離に応じてそのピクセルの色をどれだけ計算に入れるかという「重み」を決めたが、双方向フィルタでは距離だけでなく色がどれだけ近いかも重みの計算に含める。
つまり、そのピクセルの色が中心のピクセルに近ければ影響が大きく、色の違いが大きければ影響が小さくなるように重みを決める。
このことによって、全体としてはぼかしつつもエッジの情報を保持するようなぼかし方ができる。
OpenCVの双方向フィルタの処理を行うのはbilateralFilter関数で、画像 img にカーネルが 9x9, 色空間の標準偏差が10, 座標空間の標準偏差が75のフィルタをかける処理は以下の通り。
cv2.bilateralFilter(img, 9, 10, 75)
色空間の標準偏差が小さいと似通った色のピクセルのみが計算に含まれ、色空間の標準偏差が大きいと色の違いが大きいものも計算に含まれるようになる。