Main Content

スライディング近傍演算

スライディング近傍演算は、対応する入力ピクセルの "近傍" の値にアルゴリズムを適用して決まった出力イメージ内のピクセル値を使用して、一度に 1 ピクセルを処理する演算です。ピクセルの近傍は、そのピクセルに対する位置によって定義されるピクセルの集合で、"中心ピクセル" と呼ばれます。近傍は四角形ブロックで、イメージ行列内である要素から次の要素に移動すると、近傍ブロックは同じ方向に移動します (一度に 1 ピクセルではなく一度に 1 ブロックのイメージに対して演算を行うには、個別ブロック処理関数を使用します。詳細については、個別ブロック処理を参照してください)。

次の図は、6 行 5 列の行列内の要素をもつ 2 行 3 列のスライディング ブロックを示しています。各近傍の中心ピクセルには、点で印が付いています。中心ピクセルの決め方は、中心ピクセルの決定を参照してください。

6 行 5 列の行列内の近傍ブロック

中心ピクセルの決定

中心ピクセルは、演算で処理される入力イメージの中に存在する実際のピクセルです。近傍が奇数の行や列である場合、中心ピクセルは実際の近傍の中心になります。いずれかの次元が偶数の場合、中心ピクセルは中心から左または上にずれます。たとえば、2 行 2 列の近傍では中心ピクセルは上左隅になります。

mn 列の近傍では、中心ピクセルは次のようになります。

floor(([m n]+1)/2)

前の図で示される 2 行 3 列のブロックでは、中心ピクセルは (1,2) で、近傍の上の行の 2 番目の列のピクセルになります。

スライディング近傍演算の一般的なアルゴリズム

スライディング近傍演算は、次のように処理します。

  1. 1 つのピクセルを選択します。

  2. ピクセルの近傍を決定します。

  3. 近傍内のピクセル値に関数を適用します。この関数はスカラーを返さなければなりません。

  4. 入力イメージの中心ピクセルの位置に対応する出力イメージのピクセルを特定します。この出力ピクセルを、関数により出力される値として設定します。

  5. 入力イメージの各ピクセルに対して、手順 1 ~ 4を繰り返します。

たとえば、関数が近傍ピクセルの値の和を計算し、その結果を近傍内のピクセルの数で除算して平均を計算するものであるとします。この計算結果が出力ピクセル値になります。

スライディング近傍演算での境界パディング動作

近傍ブロックがイメージ上をスライドするとき、特に中心ピクセルがイメージの境界上に位置する場合に、近傍内のピクセルの一部が欠落する場合があります。たとえば、中心ピクセルがイメージの左上隅のピクセルである場合、近傍にイメージの一部ではないピクセルが含まれていることになります。

このような近傍を処理するため、スライディング近傍演算ではイメージの境界付近に通常 0 を "パディング" します。つまり、これらの関数はイメージが 0 を要素とする付加的な行と列で囲まれていると仮定することにより、境界のピクセルを処理します。これらの行と列は出力イメージを作成することはなく、イメージ内の実際のピクセルの近傍の一部として使用されるだけです。

スライディング近傍演算としての線形および非線形フィルター処理の実装

スライディング近傍演算を使用して、さまざまなフィルター演算を実装できます。スライディング近傍演算の 1 つの例に畳み込みがあります。これは線形フィルター処理を実装するときに使用されます。MATLAB® には畳み込みを実行する関数 conv および filter2 が用意されており、ツールボックスには関数 imfilter が用意されています。これらの関数の詳細については、空間領域でのイメージのフィルター処理とはを参照してください。

畳み込みだけでなく、スライディング近傍処理を通して実装できる多くの他のフィルター演算があります。これらの演算の多くは、一般には非線形です。たとえば、出力ピクセルの値が入力ピクセルの近傍内のピクセル値の標準偏差に等しくなるようにスライディング近傍演算を実装する場合などです。

さまざまなスライディング近傍演算を実装するには、関数 nlfilter を使用します。nlfilter はイメージ、近傍サイズ、およびスカラーを返す関数を入力引数として取り、入力イメージと同じサイズのイメージを出力します。nlfilter は、対応する入力ピクセルの近傍を関数に渡すことにより、出力イメージ内の各ピクセルの値を計算します。

メモ

関数 nlfilter で実装できる多くの演算では、四角形近傍でなく列行列になっていると、計算が非常に速く実行されます。この方法の詳細については、列方向の処理を使用して、スライディング近傍または個別ブロック演算を高速化するを参照してください。

たとえば、次のコードでは入力ピクセルの 3 行 3 列の近傍 (ピクセル自体と周りの 8 点) の値の標準偏差を計算して、各出力ピクセルを計算します。

I = imread("tire.tif");
I2 = nlfilter(I,[3 3],"std2");

また、特別な関数を実装するようにコードを記述し、この関数を nlfilter と共に使用することもできます。たとえば、次のコマンドは、myfun.m と呼ばれる関数を使用して、2 行 3 列の近傍で行列 I を処理します。構文 @myfun は、関数ハンドルの例です。

I2 = nlfilter(I,[2 3],@myfun);

特定の関数を実装するのにコードを記述しない場合は、無名関数を使用することができます。uint8 データ型では平方根関数は定義されないため、この例ではイメージを double クラスに変換します。

I = im2double(imread("tire.tif"));
f = @(x) sqrt(min(x(:)));
I2 = nlfilter(I,[2 2],f);

関数ハンドルの詳細については、関数ハンドルの作成を参照してください。無名関数の詳細については、無名関数を参照してください。

次の例では、各ピクセルを 3 行 3 列の近傍内の最大値に設定するために nlfilter を使用します。

メモ

この例は、nlfilter の使用法を示すことだけを目的にしています。この局所的最大値演算をさらに速く実行するには、imdilate を使用します。

I = imread("tire.tif");
f = @(x) max(x(:));
I2 = nlfilter(I,[3 3],f);
imshow(I);
figure, imshow(I2);

入力近傍の最大値に設定された各出力ピクセル