5.13. 線形フィルタと近傍フィルタ¶
この章の前半で扱ったピクセル演算は、2 枚の画像を 1 ピクセルずつ組み合わせるものでした。フィルタ は関連する処理を別の方法で行います。すなわち、出力ピクセルの値を、対応する位置を囲む入力ピクセルの小さな 近傍 から計算します。(x, y) における出力は、(x, y) を中心とする小さな枠内の入力ピクセルについての何らかの統計量 -- 平均値、中央値、最頻値など -- です。
この枠組みのわずかな変化 -- 1 度に 1 ピクセルを扱うことから、1 度にピクセルのウィンドウを扱うことへの移行 -- こそが、有用な処理の一群全体を成り立たせています。小さなウィンドウにわたる単純な平均はセンサーノイズを滑らかに除去します。同じウィンドウにわたる中央値は、エッジをそれほど甘くすることなく単一ピクセルのスペックルを除去します。バイラテラル平均は強いコントラストの境界を越えて平滑化することを拒み、内部のテクスチャをきれいにしながら物体のエッジを保持します。近傍は処理の単位であり、統計量の選択がフィルタの働きを決めます。
5.13.1. カーネルサイズ¶
すべての近傍フィルタは、ウィンドウの 半径 をピクセル単位で設定する size パラメータを取ります。ウィンドウ自体は正方形で、各辺が (2 * size + 1) ピクセルをカバーします -- したがって size=1 は 3×3 の近傍、size=2 は 5×5、size=3 は 7×7、というようになります。
近傍は画像上を 1 ピクセルずつ、左上から右下へとスライドしていきます。各出力ピクセルは、それを中心とする入力近傍にフィルタの統計量を適用した結果です。¶
サイズが大きいほど近傍が大きくなり、より滑らかな(あるいはより積極的な)フィルタリングになります。コストはウィンドウの面積に比例して増加するため、size=3 のフィルタはピクセルあたり size=1 のフィルタの約 9 倍の処理を行います。ほとんどのクリーンアップ作業で実用的なデフォルトは size=1 または size=2 です。小さな近傍ではアプリケーションが抑制しようとしている特徴を十分に抑えられない場合にのみ、より大きなサイズに手を伸ばしてください。
5.13.2. 平均値フィルタ¶
mean() は各ピクセルをその近傍の 算術平均 で置き換えます。この結果はウィンドウのサイズにわたってピクセル間の変動を平滑化するため、センサーノイズのスペックルを抑制する最も安価な方法となります。すなわち、高周波の変動は平均化されて消え、低周波の内容は残ります。
トレードオフは、エッジやその他の鋭い特徴も平均化されてしまうことです。フィルタ前に 1 ピクセル幅だった明るいエッジは、size=1 の平均値フィルタ後には 2〜3 ピクセル幅になり、その肩の部分で明るさがなだらかに落ちていきます。テクスチャの乏しい画像(きれいな壁、色付きマーカーの内部)での純粋なノイズ低減なら、このトレードオフは問題ありません。エッジが重要な込み入ったシーンでは、通常は以下のフィルタのいずれかの方が適しています。
img.mean(1) # 3x3 box average -- fast, gentle smoothing
img.mean(2) # 5x5 box average -- stronger, slower
5.13.3. 中央値、最頻値、中点¶
他の 3 つの統計的近傍フィルタは、単純な算術平均を外れ値に対してより頑健な何かと引き換えにします。
median() は近傍の 中央値 -- ウィンドウのピクセルをソートしたリストの真ん中に来る値 -- を返します。ウィンドウ内の 1 つの非常に明るい、あるいは非常に暗いピクセルは中央値を引っ張りません。それは単に捨てられる両極端の 1 つになるだけです。実用上の効果は、中央値フィルタが mean のようにエッジを甘くすることなく単一ピクセルのスペックルやごま塩ノイズを除去することです。コストはピクセルあたりの計算量が多いこと -- ウィンドウのソートは平均化より遅い -- と、結果が厳密には平均ではないことで、後段の演算によってはこれが問題になることがあります。
percentile パラメータ(デフォルト 0.5)は、選択される値を厳密な中央値からずらします。percentile=0.0 は近傍の最小値を返し、percentile=1.0 は最大値を返します。中間の値はソートされたウィンドウ内でそれらの間を比例的に選びます。これにより median は、順序統計量の外れ値耐性を失うことなく、近傍の暗い部分または明るい部分を強調する能力を持ちます。
mode() は近傍内で 最も多く現れる 値を返します。「ほとんどのピクセルは正しく、いくつかがさまざまな程度に破損している」というノイズモデルで、正しい答えが最も頻繁に現れる値である場合に有用です -- 破損した値がソートされたウィンドウの片側に集中すると、中央値ではこれを取りこぼすことがあります。
midpoint() は近傍の 最小値と最大値の組み合わせ に重みを付けたものを返します -- bias=0.5 はそれらの中点を、bias=0.0 は最小値を、bias=1.0 は最大値を与えます。他のものほど一般的には使われませんが、目的が特に暗いまたは明るい特徴を抽出することである場合には知っておく価値があります。
5.13.4. バイラテラル、エッジ保持版¶
bilateral() は、しっかり理解しておく価値が最も高い近傍フィルタです。これは mean() の平滑化効果を生み出しますが、追加の制約があります。すなわち、近傍ピクセルが中心ピクセルと 異なる ほど、平均への寄与が小さくなります。その結果、すべての一様な領域の内部を平滑化しつつ、それらを隔てるエッジを越えてにじむことがなくなります。これはまさにほとんどのアプリケーションが実際に求めているものです。
2 つのパラメータが、フィルタがどれだけ積極的にピクセルを割り引くかを制御します。
color_sigmaは 色の差 が重み付けにどう影響するかを決めます。値が小さいほど、フィルタは中心と異なるピクセルを割り引くことに対してより厳格になります。space_sigmaは 空間的距離 が重み付けにどう影響するかを決めます。値が小さいほど、中心に近いピクセルにより多くの重みが与えられます。
デフォルト値(color_sigma=0.1、space_sigma=1.0)は妥当な出発点です。これらの調整は通常、サンプルフレームでフィルタを実行し、エッジが鮮明で内部がきれいになるまで調整するという作業になります。
バイラテラルは median() より高価で、mean() よりかなり高価です。したがって、エッジ保持の振る舞いがアプリケーションに必要なものである場合に のみ 手を伸ばす価値があります。
5.13.5. 適応的しきい値処理¶
平均値、中央値、最頻値、中点の各フィルタはすべて、その出力を 2 値のしきい値に変える同じ 1 組のキーワード引数を持っています。
threshold=Trueはフィルタをしきい値処理モードに切り替えます。offset=Nは比較の前にローカルなカットオフをN単位ずらします。
この仕組みはフィルタの通常の振る舞いの上に直接構築されます。threshold=True がない場合、フィルタは近傍にわたって統計量を計算し、その統計量を出力ピクセルに書き込みます。threshold=True がある場合、フィルタは同じ統計量を計算したうえで、同じ位置の 元の ピクセルを統計量にオフセットを加えた値と比較し、元のピクセルの方が大きければそのフォーマットの最大値を、そうでなければゼロを書き込みます。
結果は、カットオフがフレーム全体にわたって ローカルな明るさとともに移動する 2 値画像です。明るい領域は高いカットオフを、暗い領域は低いカットオフを得ます。そして、局所的に周囲より明るい前景ピクセルは、それが明るい領域にあろうと暗い領域にあろうと一致します -- これはまさに、不均一に照らされた画像に対して単一のグローバルしきい値では生み出せなかった振る舞いです。
img.mean(3, threshold=True, offset=5)
offset パラメータは、アプリケーションがテストの 厳しさ を制御する場所です。小さな正のオフセットは、一致とみなす前に元のピクセルが周囲より計測可能なほど明るいことを要求し、これによりセンサーノイズによる誤検出を抑制しますが、その代償としてかすかな前景を取りこぼします。小さな負のオフセットはかすかな前景を捉えますが、その代償として一部のノイズを通してしまいます。この選択は、パイプラインの残りが 2 値出力で何をするかに依存します。
不均一な照明の下では、単一のグローバルしきい値ではすべての位置で前景を表現できません。threshold=True で実行された近傍フィルタは、ローカルな明るさとともに移動するカットオフを生成し、フレーム全体にわたって前景を正しく分類します。¶
フィルタの一群が適応的しきい値処理を実行するため、適切な フィルタを選ぶことが重要です。最も安価な適応的しきい値処理には mean() を、入力にごま塩ノイズがあってローカルなカットオフを計算する前にフィルタで除去すべき場合には median() を使います。