第10回 様々なフィルタ処理


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

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


エンボス処理


課題 1

    ベースのプログラム (このままではマウスボタンとキーの特定の組み合わせで黒い画像ができるだけ)
    PImage img;    // 元画像の変数
    float sx, sy;  // モーションブラーの方向決めのためのドラッグ開始場所
    
    // 4近傍の鮮鋭化フィルタのマスク
    float[] maskS4 = {
      0, -1, 0, 
      -1, 5, -1, 
      0, -1, 0
    };
    
    // 8近傍の鮮鋭化フィルタのマスク
    float[] maskS8 = {
    };
    
    void setup() {
      size(400, 300);
      img = loadImage("1元.jpg");
      image(img, 0, 0, width, height);
    }
    
    void draw() {
    }
    
    // ずれ幅diffのエンボス画像を表示し、ファイルに保存
    void emboss(int diff){
      PImage outputImg = createImage(img.width-diff, img.height-diff, ARGB);
      for (int j=0; j<img.height-diff; j++){
        for (int i=0; i<img.width-diff; i++){
          // 元画像の(i+diff, j+diff)のピクセルの明るさをfloat f1に入れる
          // 元画像の(i, j)のピクセルの明るさを反転させてfloat f2に入れる
          // 出力画像の(i, j)のピクセルの明るさを(f1+f2-128)にする
        }
      }
      outputImg.updatePixels();
      image(outputImg, 0, 0, width, height);
      outputImg.save("data/1エンボス" + diff + ".jpg");
    }
    
    // neighbor個の近傍ピクセルを使って鮮鋭化した画像を表示し、ファイルに保存
    void sharpen(int neighbor){
      PImage outputImg = createImage(img.width-2, img.height-2, ARGB);
      outputImg.updatePixels();
      image(outputImg, 0, 0, width, height);
      outputImg.save("data/2鮮鋭化" + neighbor + ".jpg");
    }
    
    // タイプに応じて鮮鋭化処理後のピクセルの色を返す
    color getSharpenedColor(int x, int y, int neighbor) {
      // ピクセル色とマスクの積を足し上げた値を入れる変数
      float br=0;
      float bg=0;
      float bb=0;
      return color(br, bg, bb); // br, bg, bbから作った色を返す
    }
    
    // 画素半径raのモーションブラー画像を表示し、ファイルに保存
    void motionBlur(int ra){
      PImage outputImg = createImage(img.width-ra*2, img.height-ra*2, ARGB);
      outputImg.updatePixels();
      image(outputImg, 0, 0, width, height);
      outputImg.save("data/3モーションブラー" + ra + ".jpg");
    }
    
    // 画素半径に応じてモーションブラー処理後のピクセルの色を返す
    color getBluredColor(int x, int y, int ra) {
      // ピクセル色とマスクの積を足し上げた値を入れる変数
      float br=0;
      float bg=0;
      float bb=0;
      return color(br, bg, bb); // br, bg, bbから作った色を返す
    }
    
    // 左右ボタンを押したときはキーに応じてフィルタ処理を実行、中央ボタンならドラッグ開始
    void mousePressed() {
      if (!keyPressed) {
        return;
      }
      if (mouseButton==LEFT) {
        if (key>='1' && key<='3') {
          emboss(key-'0');
        }
      } else if (mouseButton==RIGHT) {
        if (key=='4' || key=='8') {
          sharpen(key-'0');
        }
      } else {
        if (key=='5' || key=='9') {
          sx = mouseX;
          sy = mouseY;
        }
      }
    }
    
    // 中央ボタンドラッグ中にドラッグ方向を赤線で表示
    void mouseDragged() {
      if (mouseButton == CENTER && keyPressed && (key=='5' || key=='9')) {
        image(img, 0, 0, width, height);
        strokeWeight(2);
        stroke(255, 0, 0);
        line(sx, sy, mouseX, mouseY);
      }
    }
    
    // 中央ボタンドラッグ終了時にモーションブラー処理を実行
    void mouseReleased() {
      if (mouseButton == CENTER && (key=='5' || key=='9')) {
        motionBlur(key-'0');
      }
    }
    

  1. Processingのエディタに上のサンプルプログラムのコードをコピー&ペーストする。
  2. 「img10」という名前で保存する。
  3. 適当に画像検索してサンプル用の画像(ざらつきの少ないノッペリした被写体で、エッジがなるべくクッキリしているもの。小物を室内で単体で撮った写真などがよい)を用意する。
  4. 画像の形式に応じて以下の変更を加える。
  5. 画像の横幅が400ピクセルになるようにリサイズする (画像サイズが大きいとメモリ不足でエラーになることがある。また、課題3のモーションブラーの効果が確認しにくい)。
  6. 「1元.jpg」をProcessingのウインドウにドラッグ&ドロップする。
  7. emboss関数の「// 元画像の(i+diff, j+diff)のピクセルの明るさをfloat f1に入れる」と「// 元画像の(i, j)のピクセルの明るさを反転させてfloat f2に入れる」の下に、それぞれ対応するコードを入れる。

  8. emboss関数の「// 出力画像の(i, j)のピクセルの明るさを(f1+f2-128)にする」の下に対応するコードを入れる。

  9. 実行して普通に左クリックしてから、「1」「2」「3」のキーを押しながら左クリックする。
  10. ここで作る提出物
    ※ うまくいかないときは最終的なemboss関数とコードを見比べる。

鮮鋭化フィルタ

課題 2

  1. getSharpenedColor関数の「// ピクセル色とマスクの積を足し上げた値を入れる変数」の上に、以下のコードを追加する。
  2.   float[] mask = new float[0];
      if (neighbor==4){
        mask = maskS4;
      }else{
        mask = maskS8;
      }
    


  3. getSharpenedColor関数の「return color(br, bg, bb); // br, bg, bbから作った色を返す」の上に、以下のコードを追加する。
  4.   int n=0;
      for (int j=y-1; j<=y+1; j++) {
        for (int i=x-1; i<=x+1; i++) {
          // br, bg, bbに「元画像の(i, j)の位置のピクセルの赤・緑・青成分」×「マスクn番目の値」を加える
          br += red(img.pixels[i+j*img.width]) * mask[n];
          bg += green(img.pixels[i+j*img.width]) * mask[n];
          bb += blue(img.pixels[i+j*img.width]) * mask[n];
          n++;
        }
      }
    


  5. sharpen関数の「outputImg.updatePixels();」の上に、以下のコード、コメント文を追加する。
  6.   for (int j=1; j<img.height-1; j++){
        for (int i=1; i<img.width-1; i++){
          // 出力画像の(i-1, j-1)のピクセルの色を、getSharpenedColor関数で調べた「近傍数neighborで鮮鋭化した、元画像(i, j)の位置のピクセルの色」にする
        }
      }
    


  7. 「3.」で追加したコメント文の下に、対応するコードを入れる。


  8. 実行し、実行画面内で普通にクリック(どのマウスボタンでもよい)したあと、「4」を押しながら右クリックする。


  9. プログラム先頭部分のmaskS8に、然るべき値を入れる。


  10. 実行し、実行画面内で普通にクリック(どのマウスボタンでもよい)したあと、「8」を押しながら右クリックする。


  11. ここで作る提出物
    ※ うまくいかないときは最終的なプログラム先頭部分最終的なsharpen関数最終的なgetSharpenedColor関数とコードを見比べる。

モーションブラー

課題 3

  1. getBluredColor関数の「// ピクセル色とマスクの積を足し上げた値を入れる変数」の上に、以下のコードをコピー&ペーストする。
  2.   float[] mask = new float[(ra*2+1)*(ra*2+1)];
      float sum = 0;
      int n = 0;
      PVector d = new PVector(mouseX-sx, mouseY-sy); // ドラッグの方向ベクトル
      d.normalize(); // 長さを1にする
      // 中心からの距離に応じた値を入れる
      for (int j=-ra; j<=ra; j++) {
        for (int i=-ra; i<=ra; i++) {
          mask[n] = exp(-(i*d.y-j*d.x)*(i*d.y-j*d.x));
          sum += mask[n];
          n++;
        }
      }
      // 総和が1になるように修正
      for (int i=0; i<mask.length; i++) {
        mask[i] /= sum;
      }
    

  3. getSharpenedColor関数の「int n=0;」から「return color(br, bg, bb); // br, bg, bbから作った色を返す」の1行上までのコードを、getBluredColor関数の「return color(br, bg, bb); // br, bg, bbから作った色を返す」の上にコピー&ペーストする。

  4. getBluredColor関数の「int n=0;」から「int 」を削除する。

  5. その下の2つのfor文の「1」(4箇所)を「ra」に書き換える。

  6. sharpen関数の「for (int j=1; j<img.height-1; j++){」から「outputImg.updatePixels();」の1行上の行まで(つまり、2重ループの構文6行分)を、motionBlur関数の「outputImg.updatePixels();」の上にコピー&ペーストする。

  7. コピーした2つのfor文の「1」(4箇所)を「ra」に書き換える。

  8. 「5.」でコピーしたコードの中のコメント文を「// 出力画像の(i-ra, j-ra)のピクセルの色を、getBluredColor関数で調べた「画素半径raでモーションブラーをかけた、元画像(i, j)の位置のピクセルの色」にする」に変更し、その下の行のコードをそれにあわせて変更する。

  9. motionBlur関数の「outputImg.updatePixels();」の下に以下のコードを追加する。
  10.   save("data/3モーションブラー" + ra + "向き.jpg"); // スクリーンショットを画像として保存
    
    これでドラッグ終了時の画面の状態が画像として保存されるようになる(ブラーをかけた方向の確認用に使う)。

  11. 実行して、実行画面内で普通にクリック(どのマウスボタンでもよい)したあと、「5」のキーを押しながら中央ボタンで「ブラーをかけたい方向に」ドラッグする。

  12. 同様に、「9」のキーを押しながら中央ボタンでブラーをかけたい方向にドラッグする。
  13. ここで作る提出物
    ※ うまくいかないときは最終的なmotionBlur関数最終的なgetBluredColor関数とコードを見比べる。

提出

理解度確認テスト予告



戻る inserted by FC2 system