[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 마스크를 적용하였다.








[안드로이드] 두번째 스마트폰 "아고라"

코간((Kogan) 테크놀로지스가 두 번째 구글폰인 ‘아고라’와 ‘아고라 프로’를 공개하고 호주에서 온라인 예약판매에 들어갔다고 한다.

2.5인치 터치스크린 LCD가 탑재된 ‘아고라’는 QWERTY 키보드, 마이크로SD 슬롯, 블루투스 2.0 등이 지원되고 200만화소 카메라를 장착하고 있으며, WIFI와 GPS 기능도 있다고 한다.

구글 검색을 비롯해 G메일, 유튜브 동영상 플레이어, 구글 맵스 등 구글의 각종 서비스를 편리하게 이용할 수 있다. ‘아고라’와 ‘아고라프로’의 가격은 각각 194달러, 399달러로 예상되고, 내년 1월 29일 정식 출시될 것이라고 한다. 외형은 블랙베리와 흡사하나 액정화면이 더 큰 것같다.

더 많은 구글 폰이 나오길 기대한다.



Interesting/ANDROID | Posted by hyena0 2008. 12. 4. 23:54

[안드로이드] 컬러 마스크 MASK





[Android] 컬러 마스크 MASK

이전에 엠보싱 효과는 녹색에 대해서만 처리할 수 있도록 Mask를 생성했었다.

여러번의 시행착오 끝에 RGB 전체를 MASK 할 수 있게 하는 코드를 작성했다.

MASK 호출 함수에 배열을 너무 크게 생성해 놓으면, 임베디드 디바이스에 적용되는 것이라 그런지 무지하게 느려지는 것을 알 수 있었다.

기존 마스크에 RGB를 구분 할 수 있는 인자를 넣어두고, 호출함수에는 부담을 줄인 뒤 메인함수에서 RGB를 각각 처리하는 방식으로 작성해 보았다.

private int[] mask2Colors(Bitmap bitmapO, int sltColor) {
     int W,H,ST;
     int orgColor=0;
     int greenColor=0;
     //get Height and Width
     H=bitmapO.getHeight();
     W=bitmapO.getWidth();
     ST = W;
     
     int[] colors = new int[ST * H];
     int avrColor=0;
     int[] masks = {1,1,1,1,1,1,1,1,1};//blurring 처리를 위한 배열 1/9 값을 넣어야 하나 1만 넣고 나중에 9를 나눔
    
      int Mh = 3; int Mw =3;
     int var =0;//MASK 계산될 색의 픽셀값
                  
     //get bitmap color
      for (int y = 0; y < H; y++) {
             for (int x = 0; x < W; x++) {
              if(sltColor == 0){// 0 이면 적색
               orgColor = Color.red(bitmapO.getPixel(x, y));
              }
              if(sltColor == 1){// 1 이면 녹색
               orgColor = Color.green(bitmapO.getPixel(x, y));
              }
              if(sltColor == 2){// 2 이면 파란색
               orgColor = Color.blue(bitmapO.getPixel(x, y));
              }
              colors[y * ST + x] = orgColor;
             }
         }
      //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];
        
        var = var/9; //1/9 효과를 나타냄
        //blur일 경우는 평균값 더하지 않기
        //var +=avrColor;
        colors[i]=var;
        var =0;//var 초기화       
     }
     
     //make argb style
        for (int y = 0; y < H; y++) {
            for (int x = 0; x < W; x++) {
             if(sltColor ==0){// 0 이면 적색
              orgColor = colors[y * ST + x];
              orgColor = orgColor<<16;//red shift
              orgColor = 0x00FF0000 & orgColor;
             }
             if(sltColor ==1){// 1 이면 녹색
              orgColor = colors[y * ST + x];
              orgColor = orgColor<<8;//green shift
              orgColor = 0x0000FF00 & orgColor;
             }
             if(sltColor == 2){// 2 이면 파란색
              orgColor = colors[y * ST + x];
             }
             colors[y * ST + x] = orgColor;
            }
        }
      return colors;
    }

아래는 적용해 본 엠보싱 이미지와 Blurring 이미지 이다. 원본 이미지를 볼려면 여기를 보면 된다.

<<엠보싱>>

<<Blurring>>(3x3)