第09回 エッジ抽出


今回のプログラムの最終的な機能

はじめに、これから作るプログラムが完成した時点の機能をざっと見ておく。


縦方向のエッジの抽出


課題 1

    ベースのプログラム (このままでは左クリックしたときに画面が黒くなるだけ)
    PImage img;       // 元画像の変数
    
    // X方向のプレウィットフィルタのマスク
    float[] maskPX = {
      -1, 0, 1, 
      -1, 0, 1, 
      -1, 0, 1
    };
    
    // X方向のソーベルフィルタのマスク
    float[] maskSX = {
    };
    
    // Y方向のプレウィットフィルタのマスク
    float[] maskPY = {
    };
    
    // Y方向のソーベルフィルタのマスク
    float[] maskSY = {
    };
    
    void setup() {
      size(800, 600);
      img = loadImage("1元.jpg");
      img.filter(GRAY);
      image(img, 0, 0, width, height);
    }
    
    void draw() {
    }
    
    // タイプと方向に応じてエッジを抽出し、ファイルとして保存
    void distilEdge(String type, String dir) {
      PImage outputImg = createImage(img.width, img.height, ARGB);
      for (int j=1; j<img.height-1; j++) {
        for (int i=1; i<img.width-1; i++) {
          // 方向が「X」か「Y」のとき
          if (dir.length()==1) {
            outputImg.pixels[i+j*img.width] = color(getFilteredBrightness(i, j, type+dir));
          }
          // 方向が「複合」のとき
          else {
          }
        }
      }
      outputImg.updatePixels();
      image(outputImg, 0, 0, width, height);
      String prefix; // 課題番号
      switch(dir) {
      case "X":
        prefix = "1";
        break;
      case "Y":
        prefix = "2";
        break;
      default:
        prefix = "3";
        break;
      }
      outputImg.save("data/"+prefix+type+dir+".png");
    }
    
    // タイプと方向に応じてフィルタ処理後のピクセルの明るさを返す
    float getFilteredBrightness(int x, int y, String typedir) {
      float[] mask = new float[0]; // typeに応じたフィルタのマスク
      switch(typedir) {
      case "プレウィットX":
        mask=maskPX;
        break;
      }
      float b=0; // ピクセルの明るさとマスクの積を足し上げた値を入れる変数
      int n=0;
      for (int j=y-1; j<=y+1; j++) {
        for (int i=x-1; i<=x+1; i++) {
          // bに「元画像の(i, j)の位置のピクセルの明るさ」×「マスクn番目の値」を加える
          n++;
        }
      }
      return abs(b); // bの絶対値を返す
    }
    
    // 押したボタン、キーに応じてフィルタ処理を実行
    void mousePressed() {
      String type, dir;
      if (keyPressed) {
        type = "ソーベル";
      } else {
        type = "プレウィット";
      }
      if (mouseButton==LEFT) {
        dir = "X";
      } else if (mouseButton==RIGHT) {
        dir = "Y";
      } else {
        dir = "複合";
      }
      distilEdge(type, dir);
    }
    

  1. Processingのエディタに上のサンプルプログラムのコードをコピー&ペーストする。
  2. 「img09」という名前で保存する。
  3. 適当に画像検索してサンプル用の画像(水平・鉛直に近いエッジを両方含むもの。建物などを正面から撮った写真などがよい)を用意する。
  4. 画像の形式に応じて以下の変更を加える。
  5. 「1元.jpg」をProcessingのウインドウにドラッグ&ドロップする。
  6. getFilteredBrightness関数の「// bに「元画像の(i, j)の位置のピクセルの明るさ」×「マスクn番目の値」を加える」の下に対応するコードを入れる。

  7. 実行して左クリックする。

  8. プログラム先頭近くの配列maskSXに然るべき値を入れる。

  9. getFilteredBrightness関数の中のswitch構文に、「変数typedirの値が"ソーベルX"なら、マスクとしてmaskSXを使う」という処理を追加する。
  10. 実行し、普通に左クリックした後で、キーボードのいずれかのキーを押しながら左クリックする。
  11. ここで作る提出物
    ※ うまくいかないときはこの時点のプログラム先頭部分この時点のgetFilteredBrightness関数、とコードを見比べる。

横方向のエッジの抽出

課題 2

  1. プログラム先頭部分のmaskPY, maskSYに然るべき値を入れる。
  2. getFilteredBrightness関数の中のswitch構文に、「変数typedirの値が"プレウィットY"なら、マスクとしてmaskPYを使う」「変数typedirの値が"ソーベルY"なら、マスクとしてmaskSYを使う」という処理を追加する。
  3. 実行し、実行画面内で右クリックする。
  4. さらにつづけてキーボードの何かのキーを押しながら、実行画面内で右クリックする。
  5. ここで作る提出物
    ※ うまくいかないときは最終的なプログラム先頭部分最終的なgetFilteredBrightness関数、とコードを見比べる。

全方向のエッジの抽出

課題 3

  1. distilEdge関数の「else {」の下に、以下のコメント文をコピー&ペーストする。
  2.         // X方向の、そのタイプのマスクでフィルタをかけたときの(i, j)の明るさを変数bxに入れる
            // Y方向の、そのタイプのマスクでフィルタをかけたときの(i, j)の明るさを変数byに入れる
            // 出力画像の(i, j)のピクセルの明るさをbx, byから求めた値にする
    

  3. 3行のうち上の2行分の下に、それぞれ対応するコードを入れる。

  4. コメント文「// 出力画像の(i, j)のピクセルの明るさをbx, byから求めた値にする」の下に、対応するコードを入れる。

  5. 実行し、実行画面内で中央クリックする。
  6. さらにつづけてキーボードの何かのキーを押しながら、実行画面内で中央クリックする。
  7. ここで作る提出物
    ※ うまくいかないときは最終的なdistilEdge関数とコードを見比べる。

提出

小テスト予告



戻る inserted by FC2 system