0

私はメディアンフィルターでプログラムをやっています。私が達成しようとしているのは、1つのピクセル値を取り、その隣接ピクセルを見つけて、それらを配列に格納し、その配列をソートし、中間値を取ることです(サイズ9の配列の場合、中間値はインデックス位置4です)。検討中のピクセルとまったく同じ座標にこの値を代入します。

コンテンツを削除して の値を出力するだけで、ループは正常に機能しますi,j,x,y。ステートメントを追加するとneighborhoodVal.add(imageRaster.getSample(x, y, 0));java.lang.ArrayIndexOutOfBoundsException: Coordinate out of bounds!エラーが発生します。

私が観察したことから、 の値が にjなるとの1値が にiなることがわかりました。これ264は奇妙です。画像内のすべてのピクセルのみをループするため、外側の 2 つのループ (i と j) は、エッジにあるものを除くすべてのピクセルをループします。画像の。内側のループ ( x& y) は、番目のピクセルの 8 つの隣接ピクセルすべてをループします[i][j]

私が使用している画像には と がwidth = 265ありheight=269ます。コードは次のとおりです。

public class MedianFilter {

    
    public static void main(String[] args) throws IOException {

        int i, j, x, y;
        ArrayList<Integer> neighborhoodVal = new ArrayList<Integer>();
        ;
        String imagePath = "images/assignment10/noisyShapes.jpg";
        BufferedImage inputImage = convertToGrayScale(ImageIO.read(new File(
                imagePath)));
        WritableRaster imageRaster = inputImage.getRaster();
        BufferedImage filteredImage = new BufferedImage(inputImage.getWidth(),
                inputImage.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
        WritableRaster newWRaster = filteredImage.getRaster();



        for (i = 1; i < imageRaster.getHeight()-1; i++) {
            for (j = 1; j < imageRaster.getWidth()-1; j++) {
                for (x = Math.max(0, i - 1); x <= Math.min(i + 1,imageRaster.getWidth()); x++) {
                    for (y = Math.max(0, j - 1); y <= Math.min(j + 1,imageRaster.getHeight()); y++) {
                        
                        System.out.println(i+","+j+"------->"+x+","+y);
                        
                        neighborhoodVal.add(imageRaster.getSample(x, y, 0));
                        Collections.sort(neighborhoodVal);
                    }
                }
                newWRaster.setSample(i, j, 0, (neighborhoodVal
                                .get((neighborhoodVal.size() / 2) + 1)));
                neighborhoodVal.clear();
            }

        }

        File f = new File("images/assignment10/medianFilterOutput.jpg");
        ImageIO.write(filteredImage, "JPG", f);

    }
    public static BufferedImage convertToGrayScale(BufferedImage givenImage)
            throws IOException {
        // TODO Auto-generated method stub
        BufferedImage image = new BufferedImage(givenImage.getWidth(),
                givenImage.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
        Graphics grp = image.getGraphics();
        grp.drawImage(givenImage, 0, 0, null);
        return image;
    }
}

そして、私はこの画像を使用しています:

ここに画像の説明を入力

どうやっjて1になるの?これでどこが間違っているのですか?

4

1 に答える 1

1

外側のループでは .getHeight() で "i" を使用していますが、内側のループでは .getWidth() で "x" を使用しています。したがって、i と j の境界を交換する必要があるようです。おそらく疲れからのタイプミスです。以下のサンプルコードで自分でやるかもしれません。

また、外側のループはすでに境界ピクセルを無視しているため、内側のループは "for(x = i - 1; i <= i + 1; i++" および "for(y = j - 1; y <= j + 1; j++)」であり、範囲内にあることが保証されています。

そして、私が推奨する場合:画像処理では、最も外側のループで行ごとに(つまり、「y」で)スキャンし、次にxでスキャンし、ピクセル座標に(x、y)を使用し、( i,j) オフセット用。例えば:

int r = 1;  //radius, in case you want to use median over a larger kernel

for(int y = r; y < height - r; y++)
{
   for (int x = r; x < width - r; x++)
   {
      for(int j = y - r; j <= y + r; j++)
      {
         for(i = x - r; i <= x + r; i++)
         {
            //get all neighborhood values 
         } 
      }    

      //find median
   }
}

とはいえ、慣例を使用したら、それに固執してください。getWidth() と getHeight() の境界を誤って交換するのは簡単ですが、ループを常に y、x、j、i の同じ順序でネストすると、何も考えずに正しい境界を入力する可能性が少し高くなります。 .

于 2012-10-12T04:23:01.473 に答える