'gaussian filter'에 해당되는 글 1

  1. 2009.01.06 [Android] Gaussian filter 와 마스크 형식 변경 6


[Android] Gaussian filter 와 마스크 형식 변경

이전의 마스크 필터는 배열을 선언하면서 값을 직접 입력하는 방식이었는데, 5x5, 7x7 등의 마스크표현과 Gaussian 필터 설정을 위해서 마스크 형식을 바꾸기로 했다.

우선 마스크는 이미지 배열과 곱하는 부분이 항상 같은 위치에 있으므로 convolution 계산을 하는 커널의 위치가 같아서 계산방식을 변경하였다. 기존의 convolution 계산은 미리 커널의 크기만큼을 계산식에 넣어놓아서 고정되어 있었지만 반복적 계산을 적용하여 커널의 크기가 변경되어도 계산될 수 있도록 하였다.

마스크는 double 형식으로 해서 향후 가우시안을 적용하거나 블러링 적용시 계산이 되도록 하였고, 값이 초과될 경우 색의 기준이 변하므로 최대, 최소를 각각 255, 0 으로 고정하여 녹색 이미지로 되도록 하였다.

private int[] mask(int[] colors, int W, int H) {
       int ST;
       int orgColor=0;
       int greenColor=0;
             
       ST = W;
             
       int avrColor=0;
       int Mh, Mw;
       Mh = Mw = 5;
       //double[] masks = makeMask(Mh);//블러링 mask
       double[] masks = GaussianMask(0.8);//Gaussian Mask 적용

       double var=0;
              
       //get bitmap color
        for (int y = 0; y < H; y++) {
               for (int x = 0; x < W; x++) {
                greenColor = 0x0000FF00 & colors[y * ST + x];
                  greenColor = greenColor>>8;
                colors[y * ST + x] = greenColor;
               }
           }
        //calc. average value of colors
       for (int i=0;i<H*W;i++){
        avrColor += colors[i];
       }
       avrColor /= H*W;
       //mask the color
       //i는 계산될 높이 계산될 폭만큼의 반복범위임
       for (int i=0;i<(H-Mh)*(W-Mw);i++){
        
         //기존 mask 계산
          //var = colors[i]*masks[0]      + colors[i+1]*masks[1]      + colors[i+2]*masks[2]
          //     +colors[W+i]*masks[3]    + colors[W+i+1]*masks[4]    + colors[W+i+2]*masks[5]
          //     +colors[(W+1)+i]*masks[6]+ colors[(W+1)+i+1]*masks[7]+ colors[(W+1)+i+2]*masks[8];
          for(int m=0;m<Mh;m++){
           for(int n=0; n<Mw;n++){
            var += (double)colors[i+W*m+n]*masks[Mh*m+n];  
           }
          }
          
                    
          if(var>255)var=255;
          if(var<=0)var=0;
          
          colors[i]=(int)var;
          var = 0;//var 초기화       
       }
       
       //make argb style
          for (int y = 0; y < H; y++) {
              for (int x = 0; x < W; x++) {
               greenColor = colors[y * ST + x];
               greenColor = greenColor<<8;
               greenColor = 0x0000FF00 & greenColor;             
               colors[y * ST + x] = greenColor;
              }
          }
        return colors;
      }

마스크는 아래와 같다. 해당마스크는 블러링을 적용하기 위한 것이다.

private double[] makeMask(int maskSize) {
          int Mh, Mw;
          Mh = Mw = maskSize;
          double[] RetMask = new double[Mh*Mw];
          
          for(int m=0;m<Mh;m++){
     for(int n=0; n<Mw;n++){
      RetMask[Mh*m+n] = 1.0/(Mh*Mw);  //블러링 적용을 위한 생성값
     }
    }
          return RetMask;
          
         }
         
가우시안 마스크는 아래와 같다. 표준편차인 시그마 값에 의해 커널의 크기가 결정된다. 

         private double[] GaussianMask(double sigma) {
          int length = (int)(6*sigma)+1;
          int center = length / 2;
          
          int Mh, Mw;
          Mh = Mw = length;
          double[] RetMask = new double[Mh*Mw];
          
          for(int m=0;m<Mh;m++){
     for(int n=0; n<Mw;n++){
      RetMask[Mh*m+n] = (1.0/(2.0*Math.PI*sigma*sigma))*Math.exp(-((m-center)*(m-center)+(n-center)*(n-center)*(1.0/(2.0*sigma*sigma))));  //가우시안 함수
     }
    }
          return RetMask;
          
         }

가우시안 필터를 적용한 결과는 아래와 같다. 시그마 값은 0.8을 적용하여 5x5 마스크를 적용하였다.