2016-09-25 6 views
1

3x3,5x5,7x7マトリックスのJavaでガウスブラーを実装する必要があります。私が間違っている場合、あなたは私を修正することができますJava:ガウスブラーの実装

  1. 私は行列(M)3×3(中央値はM(0、0))しました:

    1 2 1 
    2 4 2 
    1 2 1 
    
  2. を、私は1つのピクセルを取ります(P)画像から、それぞれ最も近い画素について:

    s = M(-1, -1) * P(-1, -1) + M(-1, 0) * P(-1, 0) + ... + M(1, 1) * P(1, 1) 
    
  3. アン次いで分割してマトリックスの合計値:

    P'(i, j) = s/M(-1, -1) + M(-1, 0) + ... + M(1, 1) 
    

これは私のプログラムが行うすべてのことです。私は極端なピクセルを変更しないままにします。

私のプログラム:

for(int i = 1; i < height - 1; i++){ 
    for(int j = 1; j < width - 1; j++){ 
     int sum = 0, l = 0; 
     for(int m = -1; m <= 1; m++){ 
      for(int n = -1; n <= 1; n++){ 
       try{ 
        System.out.print(l + " "); 
        sum += mask3[l++] * Byte.toUnsignedInt((byte) source[(i + m) * height + j + n]); 
       } catch(ArrayIndexOutOfBoundsException e){ 
        int ii = (i + m) * height, jj = j + n; 
        System.out.println("Pixels[" + ii + "][" + jj + "] " + i + ", " + j); 
        System.exit(0); 
       } 
      } 
      System.out.println(); 
     } 
     System.out.println(); 
     output[i * width + j] = sum/maskSum[0]; 
    } 
} 

私はこのようなBufferedImageからsourceを得る:

int[] source = image.getRGB(0, 0, width, height, null, 0, width); 

だから、このイメージのために: : Picture before

結果がこれです

私には、私のプログラムで何が問題なのですか?

+2

彼らの宣言? Byte.toUnsignedInt((byte)source [(i + m)* height + j + n])でバイトへの変換を行っているため、カラー画像がピクセルを1バイトに収めるとは思えません。切り捨てによって最大255の値が得られます。これは、3バイト/サンプルのRGBカラースペースに変換された場合、結果が青(RおよびG成分が欠けている)の理由が説明されます。 –

+0

'int [] source = image.getRGB(0、0、width、height、null、0、width);' '出力 'は' source'のコピーですので、3回フィルタリングする必要がありますか? RとGについて?どうしたらいいですか? – Wiszen

+1

r、g、bの値を個別に取得するには、(ColorModel)[https://docs.oracle.com/javase/7/docs/api/java/awt/image/ColorModel。html] データがどのように格納されているか知っていれば、そのピクセルのint値から4バイトを抽出できます。 –

答えて

1

まず、ソース配列のインデックスを計算するための式が間違っています。画像データは、アレイの1つの画素行に次々に格納される。したがって、インデックスxを与えられ、yこのように計算される:これは他のチャンネルに影響を与えるチャネルを可能にするため

index = x + y * width 

さらにカラーチャネルがintの異なるビットに格納されているが、単に、全体intで計算を行うことができません。

次のソリューションは、(それだけで透明境界の画素を残していても)動作するはずです:

あなた `source`と` output`で、私たちが見ることができるどのような種類
public static BufferedImage blur(BufferedImage image, int[] filter, int filterWidth) { 
    if (filter.length % filterWidth != 0) { 
     throw new IllegalArgumentException("filter contains a incomplete row"); 
    } 

    final int width = image.getWidth(); 
    final int height = image.getHeight(); 
    final int sum = IntStream.of(filter).sum(); 

    int[] input = image.getRGB(0, 0, width, height, null, 0, width); 

    int[] output = new int[input.length]; 

    final int pixelIndexOffset = width - filterWidth; 
    final int centerOffsetX = filterWidth/2; 
    final int centerOffsetY = filter.length/filterWidth/2; 

    // apply filter 
    for (int h = height - filter.length/filterWidth + 1, w = width - filterWidth + 1, y = 0; y < h; y++) { 
     for (int x = 0; x < w; x++) { 
      int r = 0; 
      int g = 0; 
      int b = 0; 
      for (int filterIndex = 0, pixelIndex = y * width + x; 
        filterIndex < filter.length; 
        pixelIndex += pixelIndexOffset) { 
       for (int fx = 0; fx < filterWidth; fx++, pixelIndex++, filterIndex++) { 
        int col = input[pixelIndex]; 
        int factor = filter[filterIndex]; 

        // sum up color channels seperately 
        r += ((col >>> 16) & 0xFF) * factor; 
        g += ((col >>> 8) & 0xFF) * factor; 
        b += (col & 0xFF) * factor; 
       } 
      } 
      r /= sum; 
      g /= sum; 
      b /= sum; 
      // combine channels with full opacity 
      output[x + centerOffsetX + (y + centerOffsetY) * width] = (r << 16) | (g << 8) | b | 0xFF000000; 
     } 
    } 

    BufferedImage result = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); 
    result.setRGB(0, 0, width, height, output, 0, width); 
    return result; 
} 
int[] filter = {1, 2, 1, 2, 4, 2, 1, 2, 1}; 
int filterWidth = 3; 
BufferedImage blurred = blur(img, filter, filterWidth); 
+0

ありがとうございました!その仕事はとてもうまいです:) – Wiszen