next up previous
Next: 5.3 色抽出処理 Up: 5 画像処理 Previous: 5.1 空間フィルタ処理

5.2 メディアンフィルタ

以下に知能機械情報学専攻修士TAの鈴木義久君による 画像処理プログラムの例を紹介する.
図 10: メディアンフィルタ
\includegraphics[width=7.8cm]{/home/inaba/eps/lecture/fig/MedianFilter1.eps} \includegraphics[width=7.8cm]{/home/inaba/eps/lecture/fig/MedianFilter2.eps}
// MedianFilter.java
import java.applet.Applet;
import java.awt.*;
import java.io.*;
import java.awt.event.*;
import java.awt.image.*;
import java.lang.Math.*;

/*<applet code="MedianFilter.class"
  width="967" height="747">
  <param name="img_" value="aiboakira.jpg">
  </applet>*/

public class MedianFilter extends Applet {
  Image img_;
  Image img;
  MediaTracker mt;
  int w=410,h=307;
  int[][] color;
    
  public void init(){
    mt=new MediaTracker(this);

    setBackground(Color.white);

    img_ = getImage(getDocumentBase(),
                    getParameter("img_"));
    mt.addImage(img_,0);    
    try {
      mt.waitForID(0);
    } catch(InterruptedException e) {
    }
    w = img_.getWidth(this);
    h = img_.getHeight(this);
    color= new int[w*h][3];

    getColor(img_, color, w, h);
    img=img_;

    Button btn_med = new Button("メディアンフィルタ");
    Button btn_noise = new Button("ノイズ付加");
    Button btn_reset = new Button("リセット");
        
    this.add(btn_med);
    this.add(btn_noise);
    this.add(btn_reset);

    // メディアンフィルタボタン設定
    btn_med.addActionListener(
      new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            img_ = median(color, w, h);
            repaint();
            getColor(img_, color, w, h);
          }
        });
    
    // ノイズ付加ボタン設定
    btn_noise.addActionListener(
      new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            img_ = noise(color, w, h);
            repaint();
            getColor(img_, color, w, h);
          }
        });
    
    // リセットボタン設定
    btn_reset.addActionListener(
      new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            img_ = reset();
            repaint();
            getColor(img_, color, w, h);
          }
        });
  }

  public void paint(Graphics g) {
    g.drawImage(img_,0,0,this);                
  }


  // メディアンフィルタ処理
  // 色情報(0~255)をしまう配列 color[h*w][3]
  public Image median(int color[][],
                      int w,   // 画像の幅
                      int h   // 画像の高さ
  ){
    int[][] sort = new int[9][9];
    int[] mat = new int[9];
    // 3X3フィルタの座標
    // mat[0] mat[1] mat[2]
    // mat[3] mat[4] mat[5]
    // mat[6] mat[7] mat[8]

    int[][] color2 = new int[w*h][3];
    int[] gray = new int[h*w];

    for(int i=0;i<h;i++){
      for(int j=0;j<w;j++){
        gray[j+i*w]=0;
        for(int k=0;k<3;k++){
          gray[j+i*w]+=color[j+i*w][k];
        }
      }
    }
        
        
    for(int i=0;i<h;i++){
      for(int j=0;j<w;j++){
        int i1,i2,i3;
        int j1,j2,j3;
                
        if(i-1<0) i1=i; else i1=i-1;
        if(j-1<0) j1=j; else j1=j-1;
        i2=i;
        j2=j;                
        if(i+1>h-1) i3=i; else i3=i+1;
        if(j+1>2-1) j3=j; else j3=j+1;

        mat[0]=j1+i1*w;
        mat[1]=j2+i1*w;
        mat[2]=j3+i1*w;
        mat[3]=j1+i2*w;
        mat[4]=j2+i2*w;
        mat[5]=j3+i2*w;
        mat[6]=j1+i3*w;
        mat[7]=j2+i3*w;
        mat[8]=j3+i3*w;

        sort[0][0]=mat[0];
        for(int l=1;l<9;l++){
          for(int m=0;m<l;m++){
            if(gray[sort[l-1][m]] <
               gray[mat[l]]){
              sort[l][m]=sort[l-1][m];
            } else{
              sort[l][m]=mat[l];
                            
              for(int n=m+1;n<=l;n++){
                sort[l][n]=sort[l-1][n-1];
              }
              break;
            }
            sort[l][l]=mat[l];
          }
        }
                
        for(int k=0;k<3;k++){
          color2[j+i*w][k]=
            color[sort[8][4]][k];
        }
      }
    }

    return makeImage(color2, w , h);
  }

  // リセット
  public Image reset() {
    return img;
  }

  // ノイズ付加処理
  // 色情報(0~255)をしまう配列 color[h*w][3]
  public Image noise(int color[][],
                     int w,   // 画像の幅
                     int h   // 画像の高さ
  ){
    double rand;
    int[] pix2= new int[w*h];

    for(int i=0;i<h;i++){
      for(int j=0;j<w;j++){
        for(int k=0;k<3;k++){                
          rand = Math.random();                
          if(rand<0.05){
            rand = Math.random();
            color[j+i*w][k]= (int)(rand*255);                
          }
        }
      }
    }

    return makeImage(color, w , h);
  }

  // 色情報から画像をつくる。
  // 色情報(0~255)をしまう配列 color[h*w][3]
  Image makeImage(int color[][],
                  int w,   // 画像の幅
                  int h   // 画像の高さ
  ){
    int[] pix = new int[w*h];
        
    for(int i=0;i<h;i++){
      for(int j=0;j<w;j++){
        pix[j+i*w]=(255<<24)|
          (color[j+i*w][0]<<16)|
          (color[j+i*w][1]<<8)|
          (color[j+i*w][2]);
      }
    }
    return createImage(new MemoryImageSource(w,h,pix,0,w));
  }

  // 画像から色情報を取り出す。
  void getColor(Image img_,  // 元の画像
                int color[][],
  // 色情報(0~255)をしまう配列 color[h*w][3]
                int w,   // 画像の幅
                int h   // 画像の高さ
  ) {
    int[] pix= new int[w*h];

    PixelGrabber pg=
      new PixelGrabber(img_,0,0,w,h,pix,0,w);
    try{pg.grabPixels();}catch(Exception e){}

    for(int i=0;i<h;i++){
      for(int j=0;j<w;j++){
        color[j+i*w][0]=
          (pix[j+i*w] & 0xff0000)>>16;   // 赤色
        color[j+i*w][1]=
          (pix[j+i*w] & 0xff00)>>8;   // 緑色
        color[j+i*w][2]=
          pix[j+i*w] & 0xff;   // 青色
      }
    }
  }
}


generated through LaTeX2HTML. M.Inaba 平成18年5月7日