第15回 疑似カラー・空間フィルタリング・そのほかの処理

今回はテキスト5-2-10(143ページ)の「疑似カラー」、5-3(145~)の「空間フィルタリング」、5-4(154~)の「そのほかの処理」についての実践を行う。
オンラインで受講でPCにProcessingが入っていない場合は、まず Processing をダウンロードしてインストールしてから以下の課題を行う。

準備

まず2枚の元画像を用意する。
  1. 1枚目の画像 (「元a.jpg」としてデスクトップに保存する)
  2. 2枚目の画像 (「元b.jpg」としてデスクトップに保存する)

課題 1 (疑似カラー)

143ページの図5.20のトーンカーブを使った疑似カラー画像を作る。
元画像のそれぞれのピクセルの明るさに応じて、出力画像の赤、緑、青成分の明るさを下のトーンカーブによって決める。
  1. Processingを起動する。
  2. 以下のプログラムのコードをコピーし、Processingのエディタに貼り付け、「ex15_1」という名前で保存する。
  3. PImage img;
    img = loadImage("元a.jpg"); // 画像を読み込む
    img.resize(800, int(img.height*800.0/img.width)); // 横幅が800pxになるようにリサイズ
    img.filter(GRAY); // グレースケール化
    // 疑似カラー化
    float r, g, b;
    for (int i=0; i<img.pixels.length; i++) {
      float br=brightness(img.pixels[i])/255; // i番目のピクセルの明度を取得して0~1に規格化
      if (br<0.25) { // 0~0.25の明るさ
        r=0; 
        g=br*4; 
        b=1;
      } else if (br<0.5) {// 0.25~0.5の明るさ
        r=0; 
        g=1; 
        b=(0.5-br)*4;
      } else if (br<0.75) {// 0.5~0.75の明るさ
        r=(br-0.5)*4; 
        g=1; 
        b=0;
      } else {// 3/4~1の明るさ
        r=1; 
        g=(1-br)*4; 
        b=0;
      }
      img.pixels[i] = color(r*255, g*255, b*255);
    }
    img.save("data/画像1.jpg"); // ファイルに保存
    exit();

  4. 元a.jpgをProcessingのエディタにドラッグ&ドロップする。
  5. プログラムを実行する。
  6. (一瞬だけ小さい実行ウィンドウが出るが、勝手に閉じる)
    (これは画像を作るプログラムで、実行画面上には何も表示しない)
  7. 上のメニューから「スケッチ」→「スケッチフォルダーを開く」を選び、出てきたウインドウで「data」をダブルクリックする。
  8. そのフォルダーにできた「画像1.jpg」を開き、「暗いところは青、明るいところは赤、中間の明るさのところが緑」になっていることを確認する。
  9. 元a.jpg画像1.jpg
    (クリックで拡大)

課題 2 (平滑化)

Processingのライブラリ機能を使って、画像を平滑化する。
  1. Processingのメニューから「ファイル」→「名前をつけて保存」を選び、「ex15_2」という名前で保存する。
  2. コードをすべて消し、以下のコードをコピー&ペーストしてプログラムを実行する。
  3. PImage img;
    img = loadImage("元a.jpg"); // 画像を読み込む
    img.resize(800, int(img.height*800.0/img.width)); // 横幅が800pxになるようにリサイズ
    img.filter(BLUR, 3); // 画像をぼかす
    img.save("data/画像2.jpg"); // ファイルに保存
    exit();

  4. dataフォルダーには元a.jpgをぼやけさせた「画像2.jpg」ができる。
  5. 元a.jpg画像2.jpg
    (クリックで拡大)

課題 3 (エッジ抽出)

テキストの図5.32, 5.35のフィルタを使い、画像からエッジを取り出す。
  1. Processingのエディタのコードを消し、以下のコードをコピー&ペーストする。
  2. PImage img;
    img = loadImage("元a.jpg"); // 画像を読み込む
    img.resize(800, int(img.height*800.0/img.width)); // 横幅が800pxになるようにリサイズ
    float[] outX = new float[img.width*img.height]; // 横の明度差を入れる配列
    float[] outY = new float[img.width*img.height]; // 縦の明度差を入れる配列
    for (int j=0; j<img.height; j++) {
      for (int i=0; i<img.width; i++) {
        int pos=i+j*img.width;
        if (i<img.width-1) outX[pos]=brightness(img.pixels[pos+1])-brightness(img.pixels[pos]); // 横に並んだピクセルの明度の差
        if (j>0) outY[pos]=brightness(img.pixels[pos-img.width])-brightness(img.pixels[pos]); // 縦に並んだピクセルの明度の差
      }
    }
    // 縦横の明度差の2乗の平方根を明度とした画像を作る
    for (int i=0; i<img.pixels.length; i++) {
      img.pixels[i]=color(sqrt(outX[i]*outX[i]+outY[i]*outY[i]));
    }
    img.save("data/画像3.png"); // ファイルに保存
    exit();

  3. プログラムを実行する。
  4. dataフォルダーには元画像の輪郭部分が白い線で抽出された「画像3.png」ができる。
  5. 元a.jpg画像3.png
    (クリックで拡大)

課題 4 (ハーフトーニング)

テキスト156ページの図5.50のディザパターン(Bayer型)を使い、ハーフトーニングした画像を作る。
  1. Processingのエディタのコードを消し、以下のコードをコピー&ペーストする。
  2. PImage img;
    img = loadImage("元a.jpg"); // 画像を読み込む
    img.resize(800, int(img.height*800.0/img.width)); // 横幅が800pxになるようにリサイズ
    int[] bayer={0, 8, 2, 10, 12, 4, 14, 6, 3, 11, 1, 9, 15, 7, 13, 5};
    for (int j=0; j<img.height; j+=4) {
      for (int i=0; i<img.width; i+=4) {
        for (int k=0; k<16; k++) {
          int ci=i+k%4; // チェック位置(横)
          int cj=j+k/4; // チェック位置(縦)
          if (ci>=img.width || cj>=img.height) continue; // チェック位置が画像範囲外なら処理をスキップ
          if (brightness(img.pixels[ci+cj*img.width])>=bayer[k]*16+8) {
            img.pixels[ci+cj*img.width]=color(255);
          } else {
            img.pixels[ci+cj*img.width]=color(0);
          }
        }
      }
    }
    img.save("data/画像4.png"); // ファイルに保存
    exit();
    

  3. プログラムを実行する。
  4. dataフォルダーには明暗を黒い点の密度で表現した画像「画像4.png」ができる。
  5. 元a.jpg画像4.png
    (クリックで拡大)

課題 5 (エンボス)

テキスト159ページの(5.10)式を使い、レリーフのような画像を作る。
  1. Processingのエディタのコードを消し、以下のコードをコピー&ペーストする。
  2. PImage img;
    int d=2; // ずらし幅
    img = loadImage("元a.jpg"); // 画像を読み込む
    img.resize(800, int(img.height*800.0/img.width)); // 横幅が800pxになるようにリサイズ
    PImage imgOut = createImage(img.width-d, img.height-d, RGB); // 出力画像
    for (int j=0; j<img.height-d; j++) {
      for (int i=0; i<img.width-d; i++) {
        float f1=brightness(img.pixels[i+d+(j+d)*img.width]); // 元画像の(i+d, j+d)の位置の明度
        float f2=255-brightness(img.pixels[i+j*img.width]); // 元画像の(i, j)の位置の明度を反転した値
        imgOut.pixels[i+j*imgOut.width]=color(f1+f2-128);
      }
    }
    imgOut.save("data/画像5.jpg"); // ファイルに保存
    exit();

  3. プログラムを実行する。
  4. dataフォルダーには、元画像の明るい部分が盛り上がっていて、左上から光が当たった浮き彫りのような「画像5.jpg」ができる。
  5. 元a.jpg画像5.jpg
    (クリックで拡大)

課題 6 (アルファブレンディング)

テキスト157ページの(5.9)式の重み付けを使い、2つの画像を合成する。
  1. Processingのエディタのコードを消し、以下のコードをコピー&ペーストする。
  2. PImage imga, imgb;
    float alpha=0.5; // 画像の混合比率
    imga = loadImage("元a.jpg"); // 画像を読み込む
    imgb = loadImage("元b.jpg"); // 画像を読み込む
    imga.resize(800, int(imga.height*800.0/imga.width)); // 横幅が800pxになるようにリサイズ
    imgb.resize(imga.width, imga.height); // 元aと同じ大きさにリサイズ
    for(int i=0;i<imga.pixels.length;i++){
      float r=alpha*red(imga.pixels[i])+(1-alpha)*red(imgb.pixels[i]);
      float g=alpha*green(imga.pixels[i])+(1-alpha)*green(imgb.pixels[i]);
      float b=alpha*blue(imga.pixels[i])+(1-alpha)*blue(imgb.pixels[i]);
      imga.pixels[i]=color(r,g,b);
    }
    imga.save("data/画像6.jpg"); // ファイルに保存
    exit();

  3. 最初に用意した「元b.jpg」をProcessingのエディタにドラッグ&ドロップする
  4. プログラムを実行する。
  5. dataフォルダーにできた「5合成.jpg」を開き、2枚の元画像が合成されたものになっていることを確認する。
  6. 元a.jpg元b.jpg
     
    画像6.jpg (クリックで拡大)

提出


戻る

inserted by FC2 system