0

Bitmaps を使用して Android に Mean/Average 3x3 フィルターを実装しようとしています。

このフィルターを適用しようとするたびに、アプリケーションがシャットダウンし続けます。このフィルターを画像に適用しようとすると、ArrayIndexOutOfBoundsException というエラーが発生します。

私のコードは次のとおりです。

    for (int x = 0; x < width; x++) {
        for (int y = 0; y < height; y++) {

            int index = 0;

            for (int filterX = -filterWidth / 2; filterX < filterWidth / 2; filterX++) {
                for (int filterY = -filterHeight / 2; filterY < filterHeight / 2; filterY++) {

                    A = (pixels[x+filterX+width*(y+filterY)])>>24 & 0xFF;
                    R = (pixels[x+filterX+width*(y+filterY)] >> 16) & 0xFF;
                    G = (pixels[x+filterX+width*(y+filterY)] >> 8) & 0xFF;
                    B = pixels[x+filterX+width*(y+filterY)] & 0xFF;


                        }
                }
       }
 }
4

1 に答える 1

3

どの行が例外をスローしているかを示すスタック トレースを表示しません (編集: 今はそうです、ありがとう)。

ただし、一見したところ、問題は次のように見えます。

for (int x = 0; x < width; x++) {
    for (int y = 0; y < height; y++) {
        int index = 0;
        for (int filterX = -filterWidth / 2; filterX < filterWidth / 2; filterX++) {
            for (int filterY = -filterHeight / 2; filterY < filterHeight / 2; filterY++) {
                A = (pixels[x+filterX+width*(y+filterY)])>>24 & 0xFF;
                R = (pixels[x+filterX+width*(y+filterY)] >> 16) & 0xFF;
                G = (pixels[x+filterX+width*(y+filterY)] >> 8) & 0xFF;
                B = pixels[x+filterX+width*(y+filterY)] & 0xFF;
                ...
            } 
        }
    }
 }

3x3 フィルターを画像の端に直接適用しようとしているため、ピクセル配列の境界を超えており、フィルターが画像の境界の外に出ています。最初のイテレーションを考えてみましょう:

  • x = 0
  • y = 0
  • filterX = -filterWidth / 2 = -3 / 2 = -1
  • filterY = -filterHeight / 2 = -3 / 2 = -1

そして、アクセスしようとしますpixels[x+filterX+width*(y+filterY)]

  • 0 + -1 + 幅 * (0 + -1)
  • = -1 + -幅

ご覧のとおり、アクセスpixels[-1 + -width]は明らかに範囲外です。filterX/filterY ループが正しければ、上限でも同じことが起こります (この回答の下部にある注を参照してください。現時点では、サイズが 3 の場合、filterX と filterY は 1 ではなく 0 で停止します)。

エッジから filterWidth/2 (または filterHeight/2 垂直方向) ピクセル内でフィルターを適用する必要がないか、画像ピクセルを読み取るときにいくつかの境界チェックを行い、エッジを超える領域を 0 として扱う必要があります。

考えられる最適化の 1 つは、画像の周りに filterWidth/2 (または filterHeight/2 垂直方向) の黒い境界線を作成し、エッジ近くのピクセルを処理しないことです。次に、境界チェック用のブランチは必要ありません。

ちなみに、奇数サイズのフィルターの場合は<= filterWidth / 2、ループで(高さについても同じ)行う必要があります。

for (int filterX = -filterWidth / 2; filterX <= filterWidth / 2; filterX++) {
    for (int filterY = -filterHeight / 2; filterY <= filterHeight / 2; filterY++) {

これは、すべての奇数サイズのフィルターで機能します。

于 2013-08-06T08:06:40.733 に答える