画像工学 ― 画像処理プログラミング演習（Processing ver3.3）

変数宣言、型変換、文字出力
void setup() {inta;
float x;整数型変数 a を宣言する
実数型変数 x を宣言する

a = 12;x = 3.0/2;

a に 12 を代入する
x に 3.0/2 の計算結果 1.5 を代入する（3/2 では 1 になる）

println("Hello");println( a );println( a, x );a = x;
a = int( x );println( "a=", a, ",x=", x );文字列「Hello」を表示する
a の値を表示するa と x の値を並べて表示する（間に空白が自動的に入る）
エラー 実数を整数型変数に代入することはできない
int()を使って実数を整数に変換してから、整数型変数に代入する
変数と文字列を並べて表示する

}

画像の表示
PImage f;

画像オブジェクト f を宣言する

void settings() {f = loadImage("image.jpg");size(f.width, f.height);}

画像 f へ画像ファイル（image.jpg）のデータを読み込む
実行画面を原画像と同じサイズにする

void setup() {image(f, 0, 0);}

実行画面に画像 f を貼る

画像の濃淡変換（画像を明るくする）
PImage f;

画像オブジェクト f を宣言する

void settings() {f = loadImage("image.jpg");size(f.width, f.height);}

画像 f へ画像ファイル（image.jpg）のデータを読み込む
実行画面を原画像と同じサイズにする

void setup() {
int
x, y;
float R, G, B;
color c;整数型変数 x, y を宣言する
実数型変数 R, G, B を宣言する
color 型変数 c を宣言する

for(y = 0; y < f.height; y++){for(x = 0; x < f.width; x++){R =red( f.get(x, y) );G = green( f.get(x, y) );B = blue( f.get(x, y) );R += 100;
G += 100;
B += 100;c = color(R, G, B);
f.set(x, y, c);}}f.save("image2.jpg");
image(f, 0, 0);

y を 0 から画像縦幅-1 まで 1 ずつ増やす
x を 0 から画像横幅-1 まで 1 ずつ増やす
R に、座標(x,y)の画素の画素値（赤成分）を代入する
G に、座標(x,y)の画素の画素値（緑成分）を代入する
B に、座標(x,y)の画素の画素値（青成分）を代入する
R を 100 増やす
G を 100 増やす
B を 100 増やす
RGB 値から color 型の値をつくり c に代入する
画像 f の座標(x,y)の画素値を c の色にする

画像 f を画像ファイル（image2.jpg）へ書き出す
実行画面に画像 f を貼る}

ソースコードは下記の Web ページからダウンロードできる
http://cvwww.ee.ous.ac.jp/processing_prog/1

画像工学 ― 画像処理プログラミング演習（Processing ver3.3）

平均値フィルタ
PImage f, g;

画像オブジェクト f, g を宣言する

void settings() {f = loadImage("image.jpg");
画像 f へ画像ファイル（image.jpg）のデータを読み込む
f.filter(GRAY);
画像 f をグレースケール（白黒濃淡）に変換する
g = createImage(f.width, f.height, RGB); 画像 f と同じサイズで画像 g を用意する
size(f.width*2, f.height);
実行画面のサイズを原画像の二つ分（横幅 2 倍）にする}
void setup() {
int
x, y;
float a;整数型変数 x, y を宣言する
実数型変数 a を宣言する

for(y = 1; y < f.height-1; y++){y を 1 から画像縦幅-2 まで 1 ずつ増やす
for(x = 1; x < f.width-1; x++){x を 1 から画像横幅-2 まで 1 ずつ増やす
a =red(f.get(x-1,y-1)) + red(f.get(x,y-1)) + red(f.get(x+1,y-1))+ red(f.get(x-1,y )) + red(f.get(x,y )) + red(f.get(x+1,y ))+ red(f.get(x-1,y+1)) + red(f.get(x,y+1)) + red(f.get(x+1,y+1));
座標(x,y)の近傍 9 画素の画素値の和を a に代入する
a = a / 9;
近傍 9 画素の平均値を a に代入する
g.set(x, y, color(a));
画像 g の座標(x,y)の画素値を a にする
color(a)のように引数を 1 個だけ指定した場合は、赤成分、緑成分、青成分すべての値が a になる。
}}
image(f, 0, 0);
実行画面左に画像 f（原画像）を貼るimage(g, f.width, 0);
実行画面右に画像 g（変換後画像）を貼る}
1 次微分フィルタ
PImage f, g1, g2, g3;

画像オブジェクト f, g1, g2, g3 を宣言する

void settings() {f = loadImage("image.jpg");
f.filter(GRAY);
g1 = createImage(f.width, f.height, RGB);
g2 = createImage(f.width, f.height, RGB);
g3 = createImage(f.width, f.height, RGB);
size(f.width*2, f.height*2);}

画像 f へ画像ファイル（image.jpg）のデータを読み込む
画像 f をグレースケールに変換する
画像 f と同じサイズで画像 g1 を用意する
画像 f と同じサイズで画像 g2 を用意する
画像 f と同じサイズで画像 g3 を用意する
実行画面のサイズを原画像の四つ分（横・縦 2 倍）にする

void setup() {
int
x, y;
float dx, dy, norm;

整数型変数 x, y を宣言する
実数型変数 dx, dy, norm を宣言する

for(y = 1; y < f.height-1; y++){y を 1 から画像縦幅-2 まで 1 ずつ増やす
for(x = 1; x < f.width-1; x++){x を 1 から画像横幅-2 まで 1 ずつ増やす
dx = red(f.get(x+1,y )) - red(f.get(x,y));
座標(x,y)の横方向の微分値を dx に代入する
dy = red(f.get(x ,y+1)) - red(f.get(x,y));
座標(x,y)の縦方向の微分値を dy に代入する
norm = sqrt(dx*dx + dy*dy);
ベクトル(dx,dy)の大きさを norm に代入する
dx = abs(dx);dx を絶対値にする
dy = abs(dy);dy を絶対値にする
g1.set(x, y, color(dx));
画像 g1 の座標(x,y)の画素値を dx にする
g2.set(x, y, color(dy));
画像 g2 の座標(x,y)の画素値を dy にする
g3.set(x, y, color(norm));
画像 g3 の座標(x,y)の画素値を norm にする}}
image(f, 0, 0);
実行画面左上に画像 f（原画像）を貼る
image(g1, f.width, 0);
実行画面右上に画像 g1（横方向１次微分）を貼る
image(g2, 0, f.height);
実行画面左下に画像 g2（縦方向１次微分）を貼るimage(g3, f.width, f.height);
実行画面右下に画像 g3（ベクトルの大きさ）を貼る}

2

画像工学 ― 画像処理プログラミング演習（Processing ver3.3）

ラプラシアン（2 次微分）フィルタ
PImage f, g;

画像オブジェクト f, g を宣言する

void settings() {f = loadImage("image.jpg");
f.filter(GRAY);
g = createImage(f.width, f.height, RGB);
size(f.width*2, f.height);}

画像 f へ画像ファイル（image.jpg）のデータを読み込む
画像 f をグレースケールに変換する
画像 f と同じサイズで画像 g を用意する
実行画面のサイズを原画像の横幅の 2 倍にする

void setup() {
int
x, y;
float a;整数型変数 x, y を宣言する
実数型変数 a を宣言する

for(y = 1; y < f.height-1; y++){y を 1 から画像縦幅-2 まで 1 ずつ増やす
for(x = 1; x < f.width-1; x++){x を 1 から画像横幅-2 まで 1 ずつ増やす
a =+red(f.get(x,y-1))+ red(f.get(x-1,y)) - 4*red(f.get(x,y )) + red(f.get(x+1,y))+red(f.get(x,y+1));
座標(x,y)のラプラシアンの値を a に代入する
a = abs(a);a を絶対値にする
g.set(x, y, color(a));
画像 g の座標(x,y)の画素値を a にする}}
image(f, 0, 0);
実行画面左に画像 f（原画像）を貼る
image(g, f.width, 0);
実行画面右に画像 g（2 次微分）を貼る}

画像の平行移動画像 f を x 軸方向に 80 画素、y 軸方向に 30 画素、平行移動する。
PImage f, g;
画像オブジェクト f, g を宣言する
void settings() {f = loadImage("image.jpg");
f.filter(GRAY);
g = createImage(f.width, f.height, RGB);
size(f.width*2, f.height);}

画像 f へ画像ファイル（image.jpg）のデータを読み込む
画像 f をグレースケールに変換する
画像 f と同じサイズで画像 g を用意する
実行画面のサイズを原画像の横幅の 2 倍にする

void setup() {
int
X, Y;
int
x, y;
float a;整数型変数 X, Y を宣言する 画像 f 上の座標(X,Y)
整数型変数 x, y を宣言する 画像 g 上の座標(x,y)
実数型変数 a を宣言する

for(y = 0; y < g.height; y++){for(x = 0; x < g.width; x++){
X = x - 80;
Y = y - 30;

y を 0 から画像縦幅-1 まで 1 ずつ増やす
x を 0 から画像横幅-1 まで 1 ずつ増やす
座標(x,y)から x 軸方向に-80 画素、y 軸方向に-30画素平行移動した座標を(X,Y)に設定する
画像 f の座標(X,Y)の画素値を a に代入する
get に画像の外側の座標を与えた場合、画素値は 0（黒）が返ってくる。Processing 以外の言語では、メモリアクセス違反のエラーが起きる可能性があるので注意が必要である
画像 g の座標(x,y)の画素値を a にする

a = red(f.get(X, Y));g.set(x, y, color(a));}}
image(f, 0, 0);
image(g, f.width, 0);

実行画面左に画像 f（原画像）を貼る
実行画面右に画像 g（変換後画像）を貼る}

3

画像工学 ― 画像処理プログラミング演習（Processing ver3.3）

画像の拡大縮小（最近隣内挿法）
原点を中心にして画像 f を x 軸方向に 1.5 倍、y 軸方向に 0.8 倍に拡大する。
PImage f, g;
画像オブジェクト f, g を宣言する
void settings() {f = loadImage("image.jpg");
f.filter(GRAY);
g = createImage(f.width, f.height, RGB);
size(f.width*2, f.height);}

画像 f へ画像ファイル（image.jpg）のデータを読み込む
画像 f をグレースケールに変換する
画像 f と同じサイズで画像 g を用意する
実行画面のサイズを原画像の横幅の 2 倍にする

void setup() {
int
X, Y;
int
x, y;
float a, Xf, Yf;

整数型変数 X, Y を宣言する 画像 f 上の座標(X,Y)
整数型変数 x, y を宣言する 画像 g 上の座標(x,y)
実数型変数 a, Xf, Yf を宣言する= int(Xf + 0.5);= int(Yf + 0.5);

y を 0 から画像縦幅-1 まで 1 ずつ増やす
x を 0 から画像横幅-1 まで 1 ずつ増やす座標(x,y)の、x 座標を 1/1.5 倍、y 座標を 1/0.8 倍した座標を(Xf,Yf)に設定する
Xf を四捨五入して整数にした値を X に代入する
Yf を四捨五入して整数にした値を Y に代入する

a = red(f.get(X, Y));g.set(x, y, color(a));

画像 f の座標(X,Y)の画素値を a に代入する
画像 g の座標(x,y)の画素値を a にする

for(y = 0; y < g.height; y++){for(x = 0; x < g.width; x++){Xf = x / 1.5;
Yf = y / 0.8;
XY}}
image(f, 0, 0);
image(g, f.width, 0);

実行画面左に画像 f（原画像）を貼る
実行画面右に画像 g（変換後画像）を貼る}
画像の拡大縮小（バイリニア補間）
原点を中心にして画像 f を x 軸方向に 1.5 倍、y 軸方向に 0.8 倍に拡大する。
PImage f, g;
画像オブジェクト f, g を宣言する
void settings() {f = loadImage("image.jpg");
f.filter(GRAY);
g = createImage(f.width, f.height, RGB);
size(f.width*2, f.height);}

画像 f へ画像ファイル（image.jpg）のデータを読み込む
画像 f をグレースケールに変換する
画像 f と同じサイズで画像 g を用意する
実行画面のサイズを原画像の横幅の 2 倍にする

void setup() {
int
X, Y;
int
x, y;
float a, Xf, Yf, s, t;

整数型変数 X, Y を宣言する 画像 f 上の座標(X,Y)
整数型変数 x, y を宣言する 画像 g 上の座標(x,y)
実数型変数 a, Xf, Yf, s, t を宣言する

for(y = 0; y < g.height; y++){for(x = 0; x < g.width; x++){Xf = x / 1.5;
Yf = y / 0.8;

y を 0 から画像縦幅-1 まで 1 ずつ増やす
x を 0 から画像横幅-1 まで 1 ずつ増やす
座標(x,y)の、x 座標を 1/1.5 倍、y 座標を 1/0.8 倍した座標を(Xf,Yf)に設定する

XY= int(Xf);= int(Yf);

Xf を整数化（小数点以下切り捨て）した値を X に代入する
Yf を整数化した値を Y に代入する

st= Xf - X;= Yf - Y;

内分比 s を求める（Xf の小数部）
内分比 t を求める（Yf の小数部）

a =(1-s)*(1-t) * red(f.get(X , Y ))+s *(1-t) * red(f.get(X+1, Y ))+ (1-s)*t * red(f.get(X , Y+1))+s *t * red(f.get(X+1, Y+1));
g.set(x, y, color(a));

座標(Xf,Yf)の隣接 4 画素の画素値から座標(Xf,Yf)の画素値をバイリニア補間で求めて a に代入する
画像 g の座標(x,y)の画素値を a にする}}
image(f, 0, 0);
image(g, f.width, 0);

実行画面左に画像 f（原画像）を貼る
実行画面右に画像 g（変換後画像）を貼る}

4

画像工学 ― 画像処理プログラミング演習（Processing ver3.3）

画像の回転原点を中心にして画像 f を 20 度回転する。
PImage f, g;

画像オブジェクト f, g を宣言する

void settings() {f = loadImage("image.jpg");
f.filter(GRAY);
g = createImage(f.width, f.height, RGB);
size(f.width*2, f.height);}

画像 f へ画像ファイル（image.jpg）のデータを読み込む
画像 f をグレイスケールに変換する
画像 f と同じサイズで画像 g を用意する
実行画面のサイズを原画像の横幅の 2 倍にする

void setup() {
int
X, Y;
int
x, y;
float a, Xf, Yf, s, t;
float rad;

整数型変数 X, Y を宣言する 画像 f 上の座標(X,Y)
整数型変数 x, y を宣言する 画像 g 上の座標(x,y)
実数型変数 a, Xf, Yf, s, t を宣言する
実数型変数 rad を宣言する

rad = radians(20);

角度 20 度をラジアン単位に変換した値を rad に代入する

for(y = 0; y < g.height; y++){for(x = 0; x < g.width; x++){Xf = x*cos(rad) + y*sin(rad);Yf = -x*sin(rad) + y*cos(rad);y を 0 から画像縦幅-1 まで 1 ずつ増やす
x を 0 から画像横幅-1 まで 1 ずつ増やす
座標(x,y)を、原点を中心にして-20 度回転したときの座標を(Xf,Yf)に設定する

XY= int(Xf);= int(Yf);

Xf を整数化（小数点以下切り捨て）した値を X に代入する
Yf を整数化した値を Y に代入する

st= Xf - X;= Yf - Y;

内分比 s を求める（Xf の小数部）
内分比 t を求める（Yf の小数部）

a =(1-s)*(1-t) * red(f.get(X , Y ))+s *(1-t) * red(f.get(X+1, Y ))+ (1-s)*t * red(f.get(X , Y+1))+s *t * red(f.get(X+1, Y+1));
g.set(x, y, color(a));

座標(Xf,Yf)の隣接 4 画素の画素値から座標(Xf,Yf)の画素値をバイリニア補間で求めて a に代入する
画像 g の座標(x,y)の画素値を a にする}}
image(f, 0, 0);
image(g, f.width, 0);

実行画面左に画像 f（原画像）を貼る
実行画面右に画像 g（変換後画像）を貼る}

2 値図形の面積を求める
PImage f;void settings() {f = loadImage("image.jpg");
f.filter(GRAY);
size(f.width*2, f.height);}
void setup() {int x, y;
int S = 0;
image(f, 0, 0);f.filter(THRESHOLD, 0.47);

for(y = 0; y < f.height; y++){for(x = 0; x < f.width; x++){if( red(f.get(x, y)) == 255 ){
S++;
}
}
}
println("Image Area =", f.width*f.height);
println("Object Area =", S);
image(f, f.width, 0);

画像オブジェクト f を宣言する
画像 f へ画像ファイル（image.jpg）のデータを読み込む
画像 f をグレースケールに変換する
実行画面のサイズを原画像の横幅の 2 倍にする

整数型変数 x, y を宣言する
整数型変数 S を宣言し、0 で初期化する
実行画面左に画像 f（原画像）を貼る
filter 関数を用いて画像 f を 2 値画像に変換する
filter 関数では、しきい値を 0～1 の実数で与える
しきい値を画素値 120 にする場合は、120÷255=0.47 にする
y を 0 から画像縦幅-1 まで 1 ずつ増やす
x を 0 から画像横幅-1 まで 1 ずつ増やす
画像 f の座標(x,y)の画素が白画素であれば、S の値を 1 増やす

画像 f の全画素数を表示する
物体の面積 S を表示する
実行画面右に 2 値化後の画像 f を貼る}5

画像工学 ― 画像処理プログラミング演習（Processing ver3.3）

相違度 SSD（Sum of Squared Differences 差分 2 乗和）の計算
PImage f, t;
画像オブジェクト f, t を宣言する
void settings() {f = loadImage("image1.jpg");t = loadImage("image2.jpg");
f.filter(GRAY);
t.filter(GRAY);
size(f.width*2, f.height);

画像 f へ画像ファイル（image1.jpg）のデータを読み込む
画像 t へ画像ファイル（image2.jpg）のデータを読み込む
画像 f と t は同じサイズでなければならない
画像 f をグレイスケール（白黒濃淡）に変換する
画像 t をグレイスケール（白黒濃淡）に変換する
実行画面のサイズを原画像の横幅の 2 倍にする}
void setup() {
int
x, y;
float a, ssd = 0;
for(y = 0; y < f.height; y++){for(x = 0; x < f.width; x++){a = red(f.get(x,y)) - red(t.get(x,y));ssd += a*a;}}println("SSD=", ssd);
image(f, 0, 0);
image(t, f.width, 0);

整数型変数 x, y を宣言する
実数型変数 a, ssd を宣言し、ssd の初期値を 0 にする
y を 0 から画像縦幅-1 まで 1 ずつ増やす
x を 0 から画像横幅-1 まで 1 ずつ増やす
座標(x,y)における画像 f と t の画素値の差を a に代入する
a の 2 乗を ssd に加える計算された SSD の値を表示する
実行画面左に対象画像 f を貼る
実行画面右にテンプレート画像 t を貼る}

相違度 SSD を用いたテンプレートマッチング 画像サイズが大きいほど処理時間が長くなるので注意せよ。
PImage f, t;
画像オブジェクト f, t を宣言する
void settings() {f = loadImage("image.jpg");
対象画像 f へ画像ファイル（image.jpg）のデータを読み込む
t = loadImage("template.jpg");
テンプレート画像 t へ画像ファイル（template.jpg）のデータを読み込む
f.filter(GRAY);
画像 f をグレイスケール（白黒濃淡）に変換する
t.filter(GRAY);
画像 t をグレイスケール（白黒濃淡）に変換する
size(f.width+t.width, f.height);
実行画面の横幅を画像 f と t を合わせたサイズにする}
void setup() {intx, y, X, Y;
整数型変数 x, y, X, Y を宣言する
int
mx=0, my=0;
整数型変数 mx, my を宣言する
float a, ssd, ssdmin = 3e+38;
実数型変数 a, ssd, ssdmin を宣言し、ssdmin の初期値を充分に大きな値（3e+38 = 3×1038）にする
for(Y = 0; Y < f.height-t.height; Y++){Y を 0 から(画像 f 縦幅-画像 t 縦幅-1)まで 1 ずつ増やす
for(X = 0; X < f.width-t.width; X++){
X を 0 から(画像 f 横幅-画像 t 横幅-1)まで 1 ずつ増やす
ssd = 0;ssd を 0 で初期化する
for(y = 0; y < t.height; y++){y を 0 から画像 t 縦幅-1 まで 1 ずつ増やす
for(x = 0; x < t.width; x++){x を 0 から画像 t 横幅-1 まで 1 ずつ増やす
a = red(f.get(x+X,y+Y)) - red(t.get(x,y)); 画像 f の座標(x+X,y+Y)の画素値と画像 t の座標
ssd += a*a;(x,y)の画素値の差を a に代入し、a の 2 乗を ssd}に加える}
if(ssd < ssdmin){
現在の座標(X,Y)における ssd が ssdmin より小さければ、
mx = X; my = Y;
mx, my それぞれに X, Y の値を代入し、
ssdmin = ssd;
ssdmin に ssd の値を代入する}}}
image(f, 0, 0);
実行画面左に対象画像 f を貼る
image(t, f.width, 0);
実行画面右にテンプレート画像 t を貼る
stroke(255, 0, 0);
線を赤色（R=255, G=0, B=0）に設定する
noFill();
図形塗り潰しを無しに設定する
rect(mx, my, xtmp, ytmp);
テンプレート画像と最もマッチングした箇所を四角形で囲む}
6