今回はテキスト5-2-10(143ページ)の「疑似カラー」、5-3(145~)の「空間フィルタリング」、5-4(154~)の「そのほかの処理」についての実践を行う。
オンラインで受講でPCにProcessingが入っていない場合は、まず
Processing をダウンロードしてインストールしてから以下の課題を行う。
- 上のリンク先の選択肢から自分の環境にあったものをダウンロードし、zipファイルを展開する
- 展開してできたフォルダの中の「processing.exe」を実行する
- 「WindowsによってPCが保護されました」というメッセージが出た場合は「詳細設定」を選び「実行」を押す
143ページの図5.20のトーンカーブを使った疑似カラー画像を作る。
元画像のそれぞれのピクセルの明るさに応じて、出力画像の赤、緑、青成分の明るさを下のトーンカーブによって決める。
- Processingを起動する。
- 以下のプログラムのコードをコピーし、Processingのエディタに貼り付け、「ex15_1」という名前で保存する。
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(); |
- 元a.jpgをProcessingのエディタにドラッグ&ドロップする。
- プログラムを実行する。
(一瞬だけ小さい実行ウィンドウが出るが、勝手に閉じる)
(これは画像を作るプログラムで、実行画面上には何も表示しない)
- 上のメニューから「スケッチ」→「スケッチフォルダーを開く」を選び、出てきたウインドウで「data」をダブルクリックする。
- そのフォルダーにできた「画像1.jpg」を開き、「暗いところは青、明るいところは赤、中間の明るさのところが緑」になっていることを確認する。
- 出力画像に赤・緑・青の3つの部分がない (元画像の明るさが偏っている) ときは、元画像を変えてやり直す。
 |  |
元a.jpg | 画像1.jpg (クリックで拡大) |
Processingのライブラリ機能を使って、画像を平滑化する。
- Processingのメニューから「ファイル」→「名前をつけて保存」を選び、「ex15_2」という名前で保存する。
- コードをすべて消し、以下のコードをコピー&ペーストしてプログラムを実行する。
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(); |
- dataフォルダーには元a.jpgをぼやけさせた「画像2.jpg」ができる。
- このライブラリでは、ある位置のピクセルの色を、(元画像の)それを囲む正方形の色を平均して決める。プログラムの「img.filter(BLUR, 4);」の「4」のところに入れる数値によってその正方形の大きさが変わる。これを大きくするほどぼやけ方が強くなる。
 |  |
元a.jpg | 画像2.jpg (クリックで拡大) |
テキストの図5.32, 5.35のフィルタを使い、画像からエッジを取り出す。
- Processingのエディタのコードを消し、以下のコードをコピー&ペーストする。
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(); |
- プログラムを実行する。
- dataフォルダーには元画像の輪郭部分が白い線で抽出された「画像3.png」ができる。
 |  |
元a.jpg | 画像3.png (クリックで拡大) |
- このプログラムでは、149ページの(5.6)式の「勾配」を計算し、それを明るさとして使っている。そのおかげで縦、横、斜めの線すべてがきれいに取り出せる。
テキスト156ページの図5.50のディザパターン(Bayer型)を使い、ハーフトーニングした画像を作る。
- Processingのエディタのコードを消し、以下のコードをコピー&ペーストする。
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();
|
- プログラムを実行する。
- dataフォルダーには明暗を黒い点の密度で表現した画像「画像4.png」ができる。
 |  |
元a.jpg | 画像4.png (クリックで拡大) |
- 画像4.pngには真っ黒なピクセル、真っ白なピクセルの2種類しかないが、暗いところは黒い点の密度が高く、明るいところは密度が低くなっているので、一見グレースケールのように見える。
テキスト159ページの(5.10)式を使い、レリーフのような画像を作る。
- Processingのエディタのコードを消し、以下のコードをコピー&ペーストする。
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(); |
- プログラムを実行する。
- dataフォルダーには、元画像の明るい部分が盛り上がっていて、左上から光が当たった浮き彫りのような「画像5.jpg」ができる。
 |  |
元a.jpg | 画像5.jpg (クリックで拡大) |
- 2行目のdの値を変えると「浮き彫りの厚さ」が変わる。
- 画像を斜めにずらして合成しているので、ずらし幅分だけ画像の縦横のサイズは小さくなる。