第11回 収縮・膨張


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

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


ノイズの追加


課題 1

    ベースのプログラム (このままでは元画像とそのネガポジ反転画像が交互に表示されるだけ)
    PImage[] img = new PImage[2];       // 0が「元画像+ノイズ」、1はそのネガポジ反転
    PImage[] outputImg = new PImage[2]; // img[0], img[1]に処理を施したもの(出力・画面表示用)
    
    void setup() {
      size(400, 300);
      img[0] = loadImage("1元.png");
      img[0].filter(THRESHOLD); // 二値化する
      // ピクセル数の1%回の繰り返し
        // pixelsの要素の範囲内の乱数を生成してrに入れる
        // r番目のピクセルの白黒を反転させる
      // img[0]のネガポジ反転画像を作る
      img[1] = img[0].get();
      img[1].filter(INVERT);
      // ファイルに保存
      img[0].save("data/1ノイズ(黒文字).png");
      img[1].save("data/1ノイズ(白文字).png");
      // 画面表示用の画像に同じものをコピー
      outputImg[0] = img[0].get();
      outputImg[1] = img[1].get();
    }
    
    // 2秒ごとに黒文字・白文字の画像を交互に表示
    void draw() {
      image(outputImg[millis()/2000%2], 0, 0, width, height);
    }
    
    // ライブラリの収縮処理
    void erode() {
      for (int i=0; i<2; i++) {
        outputImg[i] = img[i].get();
        // outputImg[i]に収縮処理を行う
      }
      outputImg[0].save("data/2収縮(黒文字).png");
      outputImg[1].save("data/2収縮(白文字).png");
    }
    
    // ライブラリの膨張処理
    void dilate() {
      for (int i=0; i<2; i++) {
        outputImg[i] = img[i].get();
        // outputImg[i]に膨張処理を行う
      }
      outputImg[0].save("data/2膨張(黒文字).png");
      outputImg[1].save("data/2膨張(白文字).png");
    }
    
    // 自前の収縮処理
    void myErode() {
      outputImg[0].save("data/3収縮(黒文字).png");
      outputImg[1].save("data/3収縮(白文字).png");
    }
    
    // 自前の膨張処理
    void myDilate() {
      outputImg[0].save("data/3膨張(黒文字).png");
      outputImg[1].save("data/3膨張(白文字).png");
    }
    
    // マウスの左右ボタンとe, dキーの組み合わせで収縮・膨張処理
    // 中央ボタンでリセット
    void mousePressed() {
      // 左ボタンとe, dキーでライブラリの収縮・膨張処理
      if (mouseButton==LEFT) {
        if (key=='e') {
          erode();
        }
        if (key=='d') {
          dilate();
        }
      }
      // 右ボタンとe, dキーで自前の収縮・膨張処理
      else if (mouseButton==RIGHT) {
        if (key=='e') {
          myErode();
        }
        if (key=='d') {
          myDilate();
        }
      }
      // 中央ボタンで処理前に戻す
      else {
        outputImg[0] = img[0].get();
        outputImg[1] = img[1].get();
      }
      // いずれかのボタンとaキーでライブラリ・自前の画像を両方出力
      if (key == 'a') {
        erode();
        dilate();
        myErode();
        myDilate();
      }
    }
    

  1. Processingのエディタに上のサンプルプログラムのコードをコピー&ペーストする。
  2. 「img11」という名前で保存する。
  3. ペイントを起動して画像サイズを横400、縦300にし、文字入力機能(36ポイント、太字、黒)で適当な文字を書いて、「1元.png」という名前で保存する。

  4. 「1元.png」をProcessingのウインドウにドラッグ&ドロップする。
  5. setup関数の「// ピクセル数の1%回の繰り返し」の下に対応するコードを入れ、その下の2行(「// pixelsの~」「// r番目の~」)を囲む形で「}」を追記する。

  6. setup関数の「// pixelsの要素の範囲内の乱数を生成してrに入れる」の下に対応するコードを入れる。

  7. setup関数の「// r番目のピクセルの白黒を反転させる」の下に対応するコードを入れる。

  8. 実行してみる。
  9. この時点で存在するファイル (この時点のものは提出物ではないので、提出用バックアップなどはしないこと)
    ※ うまくいかないときは最終的なsetup関数とコードを見比べる。

ライブラリを使った収縮・膨張

課題 2

  1. erode関数の「// outputImg[i]に収縮処理を行う」の左に、以下のコードを追加する。
  2.     outputImg[i].filter(ERODE);
    
    ※ これだけでoutputImg[i]に収縮処理が行われる。

  3. dilate関数の「// outputImg[i]に膨張処理を行う」の左に、以下のコードを追加する。
  4.     outputImg[i].filter(DILATE);
    
    ※ これだけでoutputImg[i]に膨張処理が行われる。

  5. 実行し、実行画面内で普通に左クリックしたあと、eキーを押しながら左クリックする。


  6. つづけてdキーを押しながら左クリックする。


  7. この時点で増えるファイル (この時点のものは提出物ではないので、提出用バックアップなどはしないこと)
    ※ うまくいかないときは最終的なerode関数とdilate関数とコードを見比べる。

自前の収縮・膨張処理

課題 3

  1. myErode関数の「outputImg[0].save("data/3収縮(黒文字).png");」の上に、以下のコードをコピー&ペーストする。
  2.   for (int k=0; k<2; k++) {                // 2枚の画像に対する繰り返し
        outputImg[k] = img[k].get();           // 出力画像をノイズ画像と同じ状態にする
        for (int j=0; j<img[k].height; j++) {  // 縦方向繰り返し
          for (int i=0; i<img[k].width; i++) { // 横方向繰り返し
            boolean change = false;
            // 左方向チェック
            if (i>0) { // 自分より左のピクセルが存在していて
              if (brightness(img[k].pixels[i-1+j*img[k].width])==0) { // 左のピクセルが黒なら
                change = true; // 変更フラグをtrueにする
              }
            }
            // 右方向チェック
            // 上方向チェック
            // 下方向チェック
            // 変更フラグがtrueなら出力画像の(i, j)のピクセルを黒にする
            if (change) {
              outputImg[k].pixels[i+j*img[k].width] = color(0);
            }
          }
        }
      }
    

  3. 実行してeキーを押しながらマウスの左右のボタンを交互にクリックしてみる。

  4. 「// 右方向チェック」の下に対応するコードを入れる。

  5. 「// 上方向チェック」の下に対応するコードを入れる。

  6. 「// 下方向チェック」の下に対応するコードを入れる。

  7. 実行してeキーを押しながらマウスの左右のボタンを交互にクリックしてみる。

  8. myErode関数の最後の2行以外の部分をmyDilate関数の「outputImg[0].save("data/3膨張(黒文字).png");」の上にコピー&ペーストする。

  9. myDilate関数のコードを、膨張処理になるように書き換える。

  10. 実行してdキーを押しながらマウスの左右のボタンを交互にクリックしてみる。

  11. aキーを押しながらマウスのいずれかのボタンを押す。
  12. ここで増える提出物
    ※ うまくいかないときは最終的なmyErode関数最終的なmyDilate関数とコードを見比べる。

提出

小テスト予告



戻る inserted by FC2 system