講義科目「画像工学」では画像処理の演習課題として、プログラミング言語 Processing を用いてプログラムの作成を行います。ここでは、参考となる画像処理プログラムを記載します。
編集中・・・
プログラムの実行について
Processing version 3.5.4 で動作確認しています。JavaモードとPythonモードの両方のプログラムを記載しています。
プログラムの作成と実行の方法については講義資料のVODを見てください。
画像ファイルは自分で用意してください。このページでは pixabay からダウンロードした画像を使用しています。
プログラム一覧
- 変数の使用、コンソールへの出力
- 演算、型変換
- 画像ファイルの読み込みと画像の表示
- 画像の作成、画素値の読み書き、画像ファイルへの保存
- 画像を明るくする輝度変換
- 画像のガンマ補正
- カラー画像をRGBの各プレーンにわけて表示
- カラー画像をグレイスケール画像に変換
- カラー画像をセピア調画像に変換
- ヒストグラムの計算と描画
- カラー画像のホワイトバランス調整
- Processingの組み込みフィルタ
- 平均値フィルタ
- 1次微分フィルタ
- エンボス加工
- ラプラシアンフィルタ
- 画像の平行移動
- 画像の拡大縮小(最近隣内挿)
- 画像の拡大縮小(バイリニア内挿)
- 画像の回転
- アフィン変換
- 射影変換
- 任意の座標を中心して拡大する合成変換
- アフィン変換を使ったアニメーション
- 判別分析法によるグレイスケール画像の2値化
- モーメント特徴による図形の重心・面積・主軸方向の計測
- 図形の輪郭追跡と円形度の計測
- 2画像の相違度SSD(差分2乗和)の計測
- SSDによるテンプレートマッチング
変数の使用、コンソールへの出力
1 2 3 4 5 6 7 8 9 10 |
void setup() { int a; // 整数型変数aを宣言する float x; // 実数型変数xを宣言する a = 12; // aに12を代入する x = 3.5; // xに3.5を代入する println(a); // aの値をコンソールに出力する println(a, x); // aとxの値を並べてコンソールに出力する println("Hello"); // 文字列「Hello」をコンソールに出力する println("a=", a, ", x=", x); // 文字列と変数を並べてコンソールに出力する } |
1 2 3 4 5 6 7 |
def setup(): a = 12 # aに12を代入する。変数aは整数型になる x = 3.5 # xに3.5を代入する。変数xは実数型になる print a # aの値をコンソールに出力する。()は無くてもよい(Python2の仕様) print a, x # aとxの値を並べてコンソールに出力する print 'Hello' # 文字列「Hello」をコンソールに出力する。囲み記号は'でも"でもよい print "a=", a, ", x=", x # 文字列と変数を並べてコンソールに出力する |
演算、型変換
1 2 3 4 5 6 7 8 9 10 11 12 |
void setup() { int a; // 整数型変数aを宣言する float x; // 実数型変数xを宣言する a = 5; // aに5を代入する println("a=", a); // aの値を出力する println("a/2=", a/2); // a/2の演算結果を出力する。整数同士の演算結果は整数になる println("a/2.0=", a/2.0); // a/2.0の演算結果を出力する。小数点のある数値は実数型になる x = 3.14; // xに3.14を代入する // a = x; // 整数型変数には実数を代入できない【実行するとエラーになる】 a = int(x); // 実数をint()関数で整数に変換すれば整数型変数に代入できる println("a=", a); // aの値を出力する。3が出力される } |
1 2 3 4 5 6 7 8 |
def setup(): a = 5 # aに5を代入する。aは整数型変数になる print "a=", a # aの値を出力する print "a/2=", a/2 # a/2の演算結果を出力する。整数同士の演算結果は整数になる(Python2の仕様) print "a/2.0=", a/2.0 # a/2.0の演算結果を出力する。小数点のある数値は実数型になる x = 3.14 # xに3.14を代入する。xは実数型変数になる a = x # aにxの値を代入する。aは代入される数値の型に合わせて実数型変数に変わる print "a=", a # aの値を出力する。3.14が出力される |
画像ファイルの読み込みと画像の表示
1 2 3 4 5 6 7 8 9 10 |
PImage f; // 画像オブジェクトfを宣言する void setup() { f = loadImage("image.jpg"); // 画像fへファイルimage.jpgのデータを読み込む surface.setSize(f.width, f.height); // 実行画面のサイズを画像fと同じに設定する(size()関数の代替) } void draw() { image(f, 0, 0); // 実行画面に画像fを貼る } |
1 2 3 4 5 6 7 |
def setup(): global f # 変数fのグローバル宣言(draw()関数からも参照できるようにする) f = loadImage("image.jpg") # 画像fへファイルimage.jpgのデータを読み込む this.surface.setSize(f.width, f.height) # 実行画面のサイズを画像fと同じに設定する(size()関数の代替) def draw(): image(f, 0, 0) # 実行画面に画像fを貼る |
画像の作成、画素値の読み書き、画像ファイルへの保存
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
PImage f, g; // 画像オブジェクトf,gを宣言する void setup() { int x, y; // 整数型変数x,yを宣言する color c; // color型変数cを宣言する f = loadImage("image.jpg"); // 画像fへファイルimage.jpgのデータを読み込む g = createImage(f.width, f.height, RGB); // 画像gを画像fと同じサイズで作る surface.setSize(f.width*2, f.height); // 実行画面の横幅を画像fの2倍に設定する // 2重forループでラスタ走査を行う for (y = 0; y < f.height; y++) { // yを0から画像縦幅-1まで1ずつ増やす for (x = 0; x < f.width; x++) { // xを0から画像横幅-1まで1ずつ増やす c = f.get(x, y); // 画像fの座標(x,y)の色の値(color型)をcに代入する g.set(x, y, c); // 画像gの座標(x,y)の色をcに設定する } } g.save("output.jpg"); // 画像gをファイルoutput.jpgに保存する } void draw() { image(f, 0, 0); // 実行画面の左側に画像f(原画像)を貼る image(g, f.width, 0); // 実行画面の右側に画像g(画像fから複製した画像)を貼る } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
def setup(): global f, g # 変数f,gのグローバル宣言(draw()関数からも参照できるようにする) f = loadImage("image.jpg") # 画像fへファイルimage.jpgのデータを読み込む g = createImage(f.width, f.height, RGB) # 画像gを画像fと同じサイズで作る this.surface.setSize(f.width*2, f.height) # 実行画面の横幅を画像fの2倍に設定する # 2重forループでラスタ走査を行う for y in range(0, f.height): # yを0から画像縦幅-1まで1ずつ増やす for x in range(0, f.width): # xを0から画像横幅-1まで1ずつ増やす c = f.get(x, y) # 画像fの座標(x,y)の色の値(color型)をcに代入する g.set(x, y, c) # 画像gの座標(x,y)の色をcに設定する g.save("output.jpg") # 画像gをファイルoutput.jpgに保存する def draw(): image(f, 0, 0) # 実行画面の左側に原画像fを貼る image(g, f.width, 0) # 実行画面の右側に画像g(画像fから複製した画像)を貼る |
画像を明るくする輝度変換
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
PImage f; // 画像オブジェクトfを宣言する void setup() { int x, y; // 整数型変数x,yを宣言する float R, G, B; // 実数型変数R,G,Bを宣言する color c; // color型変数cを宣言する f = loadImage("image.jpg"); // 画像fへファイルimage.jpgのデータを読み込む surface.setSize(f.width, f.height); // 実行画面のサイズを画像fと同じに設定する for (y = 0; y < f.height; y++) { // yを0から画像縦幅-1まで1ずつ増やす for (x = 0; x < f.width; x++) { // xを0から画像横幅-1まで1ずつ増やす c = f.get(x, y); // 画像fの座標(x,y)の色の値(color型)をcに代入する R = red(c); // cから赤の画素値を取り出してRに代入する G = green(c); // cから緑の画素値を取り出してGに代入する B = blue(c); // cから青の画素値を取り出してBに代入する R += 100; // Rに100を加算する G += 100; // Gに100を加算する B += 100; // Bに100を加算する c = color(R, G, B); // R,G,Bからcolor型の値を作ってcに代入する f.set(x, y, c); // 画像fの座標(x,y)の色をcに設定する } } f.save("output.jpg"); // 画像fをファイルoutput.jpgに保存する } void draw() { image(f, 0, 0); // 実行画面に画像fを貼る } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
def setup(): global f # 変数fのグローバル宣言(draw()関数からも参照できるようにする) f = loadImage("image.jpg") # 画像fへファイルimage.jpgのデータを読み込む this.surface.setSize(f.width, f.height) # 実行画面のサイズを画像fと同じに設定する for y in range(0, f.height): # yを0から画像縦幅-1まで1ずつ増やす for x in range(0, f.width): # xを0から画像横幅-1まで1ずつ増やす c = f.get(x,y) # 画像fの座標(x,y)の色の値(color型)をcに代入する R = red(c) # cから赤の画素値を取り出してRに代入する G = green(c) # cから緑の画素値を取り出してGに代入する B = blue(c) # cから青の画素値を取り出してBに代入する R += 100 # Rに100を加算する G += 100 # Gに100を加算する B += 100 # Bに100を加算する c = color(R, G, B) # R,G,Bからcolor型の値を作ってcに代入する f.set(x, y, c) # 画像fの座標(x,y)の色をcに設定する f.save("output.jpg") # 画像fをファイルoutput.jpgに保存する def draw(): image(f, 0, 0) # 実行画面に画像fを貼る |
画像のガンマ補正
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
PImage f; // 画像オブジェクトfを宣言する void setup() { int x, y; // 整数型変数x,yを宣言する float R, G, B; // 実数型変数R,G,Bを宣言する float newR, newG, newB; // 実数型変数newR,newG,newBを宣言する color c; // color型変数cを宣言する float gamma = 2.0; // 実数型変数gammaを宣言して、ガンマ値を2.0に設定する float[] table = new float[256]; // 実数型配列tableを宣言する(ルックアップテーブル用) f = loadImage("image.jpg"); // 画像fへファイルimage.jpgのデータを読み込む surface.setSize(f.width, f.height); // 実行画面のサイズを画像fと同じに設定する for(x = 0; x < 256; x++) { // xを0から255まで1ずつ増やす table[x] = pow(x/255., 1./gamma)*255; // 画素値xに対するガンマ補正の変換値を算出してtable[x]に代入する } for (y = 0; y < f.height; y++) { // yを0から画像縦幅-1まで1ずつ増やす for (x = 0; x < f.width; x++) { // xを0から画像横幅-1まで1ずつ増やす c = f.get(x, y); // 画像fの座標(x,y)の色の値(color型)をcに代入する R = red(c); // cから赤の画素値を取り出してRに代入する G = green(c); // cから緑の画素値を取り出してGに代入する B = blue(c); // cから青の画素値を取り出してBに代入する newR = table[int(R)]; // 赤の画素値に対応する変換値をtableから取り出し、newRに代入する newG = table[int(G)]; // 緑の画素値に対応する変換値をtableから取り出し、newGに代入する newB = table[int(B)]; // 青の画素値に対応する変換値をtableから取り出し、newBに代入する c = color(newR, newG, newB); // newR,newG,newBからcolor型の値を作ってcに代入する f.set(x, y, c); // 画像fの座標(x,y)の色をcに設定する } } f.save("output.jpg"); // 画像fをファイルoutput.jpgに保存する } void draw() { image(f, 0, 0); // 実行画面に画像fを貼る } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
def setup(): global f # 変数fのグローバル宣言(draw()関数からも参照できるようにする) f = loadImage("image.jpg") # 画像fへファイルimage.jpgのデータを読み込む this.surface.setSize(f.width, f.height) # 実行画面のサイズを画像fと同じに設定する gamma = 2.0 # gammaにガンマ値2.0を設定する table = [pow(x/255., 1./gamma)*255 for x in range(0, 256)] # 画素値0~255のガンマ補正の変換値のリストをtableに代入する for y in range(0, f.height): # yを0から画像縦幅-1まで1ずつ増やす for x in range(0, f.width): # xを0から画像横幅-1まで1ずつ増やす c = f.get(x,y) # 画像fの座標(x,y)の色の値(color型)をcに代入する R = red(c) # cから赤の画素値を取り出してRに代入する G = green(c) # cから緑の画素値を取り出してGに代入する B = blue(c) # cから青の画素値を取り出してBに代入する newR = table[int(R)] # 赤の画素値に対応する変換値をtableから取り出し、newRに代入する newG = table[int(G)] # 緑の画素値に対応する変換値をtableから取り出し、newGに代入する newB = table[int(B)] # 青の画素値に対応する変換値をtableから取り出し、newBに代入する c = color(newR, newG, newB) # newR,newG,newBからcolor型の値を作ってcに代入する f.set(x, y, c) # 画像fの座標(x,y)の色をcに設定する f.save("output.jpg") # 画像fをファイルoutput.jpgに保存する def draw(): image(f, 0, 0) # 実行画面に画像fを貼る |
カラー画像をRGBの各プレーンにわけて表示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
PImage f, g1, g2, g3; // 画像オブジェクトf,g1,g2,g3を宣言する void setup() { int x, y; // 整数型変数x,yを宣言する float R, G, B; // 実数型変数R,G,Bを宣言する color c; // color型変数cを宣言する f = loadImage("image.jpg"); // 画像fへファイルimage.jpgのデータを読み込む g1 = createImage(f.width, f.height, RGB); // 画像g1を画像fと同じサイズで作る(赤プレーン用) g2 = createImage(f.width, f.height, RGB); // 画像g2を画像fと同じサイズで作る(緑プレーン用) g3 = createImage(f.width, f.height, RGB); // 画像g3を画像fと同じサイズで作る(青プレーン用) surface.setSize(f.width*2, f.height*2); // 実行画面の縦幅横幅を画像fの2倍に設定する for (y = 0; y < f.height; y++) { // yを0から画像縦幅-1まで1ずつ増やす for (x = 0; x < f.width; x++) { // xを0から画像横幅-1まで1ずつ増やす c = f.get(x, y); // 座標(x,y)の色の値(color型)をcに代入する R = red(c); // cから赤の画素値を取り出してRに代入する G = green(c); // cから緑の画素値を取り出してGに代入する B = blue(c); // cから青の画素値を取り出してBに代入する c = color(R, 0, 0); // 赤の画素値のみでcolor型の値を作ってcに代入する g1.set(x, y, c); // 画像g1の座標(x,y)の色をcに設定する c = color(0, G, 0); // 緑の画素値のみでcolor型の値を作ってcに代入する g2.set(x, y, c); // 画像g2の座標(x,y)の色をcに設定する c = color(0, 0, G); // 緑の画素値のみでcolor型の値を作ってcに代入する g3.set(x, y, c); // 画像g3の座標(x,y)の色をcに設定する } } } void draw() { image(f, 0, 0); // 実行画面の左上に原画像fを貼る image(g1, f.width, 0); // 実行画面の右上に画像g1(赤プレーン)を貼る image(g2, 0, f.height); // 実行画面の左下に画像g2(緑プレーン)を貼る image(g3, f.width, f.height); // 実行画面の右下に画像g3(青プレーン)を貼る } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
def setup(): global f, g1, g2, g3 # 変数f,g1,g2,g3をグローバル宣言 f = loadImage("image.jpg") # 画像fへファイルimage.jpgのデータを読み込む g1 = createImage(f.width, f.height, RGB) # 画像g1を画像fと同じサイズで作る(赤プレーン用) g2 = createImage(f.width, f.height, RGB) # 画像g2を画像fと同じサイズで作る(緑プレーン用) g3 = createImage(f.width, f.height, RGB) # 画像g3を画像fと同じサイズで作る(青プレーン用) this.surface.setSize(f.width*2, f.height*2) # 実行画面を画像fの縦横2倍のサイズに設定する for y in range(0, f.height): # yを0から画像縦幅-1まで1ずつ増やす for x in range(0, f.width): # xを0から画像横幅-1まで1ずつ増やす c = f.get(x,y) # 画像fの座標(x,y)の色の値(color型)をcに代入する R = red(c) # cから赤の画素値を取り出してRに代入する G = green(c) # cから緑の画素値を取り出してGに代入する B = blue(c) # cから青の画素値を取り出してBに代入する c = color(R, 0, 0) # 赤の画素値のみでcolor型の値を作ってcに代入する g1.set(x, y, c) # 画像g1の座標(x,y)の色をcに設定する c = color(0, G, 0) # 緑の画素値のみでcolor型の値を作ってcに代入する g2.set(x, y, c) # 画像g2の座標(x,y)の色をcに設定する c = color(0, 0, G) # 緑の画素値のみでcolor型の値を作ってcに代入する g3.set(x, y, c) # 画像g3の座標(x,y)の色をcに設定する def draw(): image(f, 0, 0) # 実行画面の左上に原画像fを貼る image(g1, f.width, 0) # 実行画面の右上に画像g1(赤プレーン)を貼る image(g2, 0, f.height) # 実行画面の左下に画像g2(緑プレーン)を貼る image(g3, f.width, f.height) # 実行画面の右下に画像g3(青プレーン)を貼る |
カラー画像をグレイスケール画像に変換
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
PImage f, g; // 画像オブジェクトf,gを宣言する void setup() { int x, y; // 整数型変数x,yを宣言する float R, G, B, V; // 実数型変数R,G,B,Vを宣言する color c; // color型変数cを宣言する f = loadImage("image.jpg"); // 画像fへファイルimage.jpgのデータを読み込む g = createImage(f.width, f.height, RGB); // 画像gを画像fと同じサイズで作る surface.setSize(f.width*2, f.height); // 画像fの2倍の幅で実行画面のサイズを設定する for (y = 0; y < f.height; y++) { // yを0から画像縦幅-1まで1ずつ増やす for (x = 0; x < f.width; x++) { // xを0から画像横幅-1まで1ずつ増やす c = f.get(x, y); // 座標(x,y)の色の値(color型)をcに代入する R = red(c); // cから赤の画素値を取り出してRに代入する G = green(c); // cから緑の画素値を取り出してGに代入する B = blue(c); // cから青の画素値を取り出してBに代入する V = .299*R + .587*G + .114*B; // R,G,Bから明度を計算してVに代入する c = color(V); // Vからcolor型の値を作ってcに代入する。赤、緑、青の画素値がすべてVになる g.set(x, y, c); // 画像gの座標(x,y)の画素の色をcに設定する } } f.save("output.jpg"); // 画像fをファイルoutput.jpgに保存する } void draw() { image(f, 0, 0); // 実行画面の左に原画像fを貼る image(g, f.width, 0); // 実行画面の右に変換後画像gを貼る } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
def setup(): global f, g # 変数f,gのグローバル宣言(draw()関数からも参照できるようにする) f = loadImage("image.jpg") # 画像fへファイルimage.jpgのデータを読み込む g = createImage(f.width, f.height, RGB) # 画像gを画像fと同じサイズで作る this.surface.setSize(f.width*2, f.height) # 実行画面の横幅を画像fの2倍の幅に設定する for y in range(0, f.height): # yを0から画像縦幅-1まで1ずつ増やす for x in range(0, f.width): # xを0から画像横幅-1まで1ずつ増やす c = f.get(x,y) # 座標(x,y)の色の値(color型)をcに代入する R = red(c) # cから赤の画素値を取り出してRに代入する G = green(c) # cから緑の画素値を取り出してGに代入する B = blue(c) # cから青の画素値を取り出してBに代入する V = .299*R + .587*G + .114*B # R,G,Bから明度を計算してVに代入する c = color(V) # Vからcolor型の値を作ってcに代入する。赤、緑、青の画素値がすべてVになる g.set(x, y, c) # 画像fの座標(x,y)の色をcに設定する g.save("output.jpg") # 画像fをファイルoutput.jpgに保存する def draw(): image(f, 0, 0) # 実行画面の左に原画像fを貼る image(g, f.width, 0) # 実行画面の右に変換後画像gを貼る |
カラー画像をセピア調画像に変換
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
PImage f, g; // 画像オブジェクトfを宣言する void setup() { int x, y; // 整数型変数x,yを宣言する float R, G, B; // 実数型変数R,G,Bを宣言する float newR, newG, newB; // 実数型変数newR,newG,newBを宣言する color c; // color型変数cを宣言する f = loadImage("image.jpg"); // 画像fへファイルimage.jpgのデータを読み込む g = createImage(f.width, f.height, RGB); // 画像gを画像fと同じサイズで作る surface.setSize(f.width*2, f.height); // 画像fの2倍の幅で実行画面のサイズを設定する for (y = 0; y < f.height; y++) { // yを0から画像縦幅-1まで1ずつ増やす for (x = 0; x < f.width; x++) { // xを0から画像横幅-1まで1ずつ増やす c = f.get(x, y); // 座標(x,y)の色の値(color型)をcに代入する R = red(c); // cから赤の画素値を取り出してRに代入する G = green(c); // cから緑の画素値を取り出してGに代入する B = blue(c); // cから青の画素値を取り出してBに代入する newR = .393*R + .769*G + .189*B; // セピア調の赤の画素値を計算してnewRに代入する newG = .349*R + .686*G + .168*B; // セピア調の緑の画素値を計算してnewGに代入する newB = .272*R + .534*G + .131*B; // セピア調の青の画素値を計算してnewBに代入する c = color(newR, newG, newB); // newR,newG,newBからcolor型の値を作ってcに代入する g.set(x, y, c); // 画像gの座標(x,y)の画素の色をcに設定する } } g.save("output.jpg"); // 画像gをファイルoutput.jpgに保存する } void draw() { image(f, 0, 0); // 実行画面の左に原画像fを貼る image(g, f.width, 0); // 実行画面の右に変換後画像gを貼る } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
def setup(): global f, g # 変数fのグローバル宣言(draw()関数からも参照できるようにする) f = loadImage("image.jpg") # 画像fへファイルimage.jpgのデータを読み込む g = createImage(f.width, f.height, RGB); this.surface.setSize(f.width*2, f.height) # 画像fの2倍の幅で実行画面のサイズを設定する for y in range(0, f.height): # yを0から画像縦幅-1まで1ずつ増やす for x in range(0, f.width): # xを0から画像横幅-1まで1ずつ増やす c = f.get(x,y) # 座標(x,y)の色の値(color型)をcに代入する R = red(c) # cから赤の画素値を取り出してRに代入する G = green(c) # cから緑の画素値を取り出してGに代入する B = blue(c) # cから青の画素値を取り出してBに代入する newR = .393*R + .769*G + .189*B; # セピア調の赤の画素値を計算してnewRに代入する newG = .349*R + .686*G + .168*B; # セピア調の緑の画素値を計算してnewGに代入する newB = .272*R + .534*G + .131*B; # セピア調の青の画素値を計算してnewBに代入する c = color(newR, newG, newB); # newR,newG,newBからcolor型の値を作ってcに代入する g.set(x, y, c) # 画像fの座標(x,y)の画素の色をcに設定する g.save("output.jpg") # 画像fをファイルoutput.jpgに保存する def draw(): image(f, 0, 0) # 実行画面の左に原画像fを貼る image(g, f.width, 0) # 実行画面の右に変換後画像gを貼る |
ヒストグラムの計算と描画
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
PImage f; // 画像オブジェクトfを宣言する int m = 0; // 整数型変数mを宣言して初期値0を代入する int[] histR = new int[256]; // 整数型配列histRを宣言する(赤ヒストグラム用) int[] histG = new int[256]; // 整数型配列histGを宣言する(緑ヒストグラム用) int[] histB = new int[256]; // 整数型配列histBを宣言する(青ヒストグラム用) void setup() { int x, y; // 整数型変数x,yを宣言する float R, G, B; // 実数型変数R,G,Bを宣言する color c; // color型変数cを宣言する f = loadImage("image.jpg"); // 画像fへファイルimage.jpgのデータを読み込む y = max(f.height, 304); // 画像fの縦幅とヒストグラムの縦幅の大きい方をyに代入する surface.setSize(f.width+258, y); // 実行画面を画像fとヒストグラムが並ぶサイズに設定する for (y = 0; y < f.height; y++) { // yを0から画像縦幅-1まで1ずつ増やす for (x = 0; x < f.width; x++) { // xを0から画像横幅-1まで1ずつ増やす c = f.get(x, y); // 座標(x,y)の色の値(カラー型)をcに代入する R = red(c); // cから赤の画素値を取り出してRに代入する G = green(c); // cから緑の画素値を取り出してGに代入する B = blue(c); // cから青の画素値を取り出してBに代入する histR[int(R)]++; // 赤の画素値Rの個数に1を加える histG[int(G)]++; // 緑の画素値Gの個数に1を加える histB[int(B)]++; // 青の画素値Bの個数に1を加える m = max(max(histR[int(R)], histG[int(G)], histB[int(B)]), m); // 最大頻度を求めてmに代入する } } } void draw() { int i; // 整数型変数iを宣言する background(240); // 実行画面の背景を灰色にする(R=G=B=240) for (i = 0; i < 256; i++) { // iを0から255まで1ずつ増やす stroke(255, 0, 0); // 線の色を赤色に設定する if (histR[i] > 0) line(i+1, 100, i+1, 100-histR[i]*100/m); // 赤画素値iのヒストグラムのビンを直線で描く stroke(0, 255, 0); // 線の色を緑色に設定する if (histG[i] > 0) line(i+1, 201, i+1, 201-histG[i]*100/m); // 緑画素値iのヒストグラムのビンを直線で描く stroke(0, 0, 255); // 線の色を青色に設定する if (histB[i] > 0) line(i+1, 302, i+1, 302-histB[i]*100/m); // 青画素値iのヒストグラムのビンを直線で描く } image(f, 258, 0); // 実行画面の座標(258,0)の位置(ヒストグラムの右側)に画像fを貼る } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
def setup(): global f, histR, histG, histB, m f = loadImage("image.jpg") # 画像fへファイルimage.jpgのデータを読み込む y = max(f.height, 304) # 画像fの縦幅とヒストグラムの縦幅の大きい方をyに代入する this.surface.setSize(f.width+258, y) # 実行画面を画像fとヒストグラムが並ぶサイズに設定する histR = [0]*256 # 要素数256のリストhistRを作る(赤ヒストグラム用) histG = [0]*256 # 要素数256のリストhistGを作る(緑ヒストグラム用) histB = [0]*256 # 要素数256のリストhistBを作る(青ヒストグラム用) for y in range(0, f.height): # yを0から画像縦幅-1まで1ずつ増やす for x in range(0, f.width): # xを0から画像横幅-1まで1ずつ増やす c = f.get(x,y) # 画像fの座標(x,y)の色の値(カラー型)をcに代入する R = red(c) # cから赤の画素値を取り出してRに代入する G = green(c) # cから緑の画素値を取り出してGに代入する B = blue(c) # cから青の画素値を取り出してBに代入する histR[int(R)] += 1 # 赤の画素値Rの個数に1を加える histG[int(G)] += 1 # 緑の画素値Gの個数に1を加える histB[int(B)] += 1 # 青の画素値Bの個数に1を加える m = max(histR + histG + histB) # histR,histG,histBの要素の最大値を求めてmに代入する def draw(): background(240) # 実行画面の背景を灰色にする(R=G=B=240) for i in range(0, 256): # iを0から255まで1ずつ増やす stroke(255, 0, 0) # 線の色を赤色に設定する if histR[i] > 0: line(i+1, 100, i+1, 100-histR[i]*100/m) # 赤画素値iのヒストグラムのビンを直線で描く stroke(0, 255, 0) # 線の色を緑色に設定する if histG[i] > 0: line(i+1, 201, i+1, 201-histG[i]*100/m) # 緑画素値iのヒストグラムのビンを直線で描く stroke(0, 0, 255) # 線の色を青色に設定する if histB[i] > 0: line(i+1, 302, i+1, 302-histB[i]*100/m) # 青画素値iのヒストグラムのビンを直線で描く image(f, 258, 0) # 座標(258,0)の位置(ヒストグラムの右側)に画像fを貼る |
カラー画像のホワイトバランス調整
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
PImage f, g; // 画像オブジェクトf,gを宣言する int[] histR = new int[256]; // 整数型配列histRを宣言する(赤ヒストグラム) int[] histG = new int[256]; // 整数型配列histGを宣言する(緑ヒストグラム) int[] histB = new int[256]; // 整数型配列histBを宣言する(青ヒストグラム) void setup() { int x, y, i; // 整数型変数x,y,iを宣言する int minR, minG, minB, maxR, maxG, maxB; // 整数型変数minR,minG,minB,maxR,maxG,maxBを宣言する color c; // color型変数cを宣言する float a, s; // 実数型変数a,sを宣言する float R, G, B; // 実数型変数R,G,Bを宣言する float[] tableR = new float[256]; // 実数型配列tableRを宣言する(赤のルックアップテーブル用) float[] tableG = new float[256]; // 実数型配列tableGを宣言する(緑のルックアップテーブル用) float[] tableB = new float[256]; // 実数型配列tableBを宣言する(青のルックアップテーブル用) f = loadImage("image.jpg"); // 原画像を画像fに読み込む g = createImage(f.width, f.height, RGB); // 画像gを画像fと同じサイズで作る surface.setSize(f.width*2, f.height); // 実行画面のサイズを原画像の2倍の幅に設定する // ヒストグラムを計算する for (y = 0; y < f.height; y++) { // yを0から画像縦幅-1まで1ずつ増やす for (x = 0; x < f.width; x++) { // xを0から画像横幅-1まで1ずつ増やす c = f.get(x, y); // 画像fの座標(x,y)の色の値(color型)をcに代入する histR[int(red(c)) ]++; // cから赤画素値を取り出し、histRに個数をカウントする histG[int(green(c))]++; // cから緑画素値を取り出し、histGに個数をカウントする histB[int(blue(c)) ]++; // cから青画素値を取り出し、histBに個数をカウントする } } // 累積ヒストグラムを計算する for (i = 1; i < 256; i++) { // iを1から255まで1ずつ増やす histR[i] += histR[i-1]; // histR[i]にhistR[i-1]の値を加算する histG[i] += histG[i-1]; // histG[i]にhistG[i-1]の値を加算する histB[i] += histB[i-1]; // histB[i]にhistB[i-1]の値を加算する } // ヒストグラムから画素値の最小値と最大値を得る。ただし、ヒストグラムの右端と左端から割合aを除いた範囲とする a = .02; // aに計算から除くヒストグラムの範囲の割合を[0,.5)の範囲で指定する s = histR[255]; // sにhistR[255]の値(画像の全画素数)を代入する minR = minG = minB = 0; // 画素値の最小値minR,minG,minBを0で初期化する maxR = maxG = maxB = 255; // 画素値の最大値maxR,maxG,maxBを255で初期化する while (histR[minR]/s < a && minR < 255) minR++; // 赤の最小画素値を求めてminRに入れる while (histG[minG]/s < a && minG < 255) minG++; // 緑の最小画素値を求めてminGに入れる while (histB[minB]/s < a && minB < 255) minB++; // 青の最小画素値を求めてminBに入れる a = 1 - a; // aに1-aの値を代入する while (histR[maxR]/s > a && maxR > 0) maxR--; // 赤の最大画素値を求めてmaxRに入れる while (histG[maxG]/s > a && maxG > 0) maxG--; // 緑の最大画素値を求めてmaxGに入れる while (histB[maxB]/s > a && maxB > 0) maxB--; // 青の最大画素値を求めてmaxBに入れる // ヒストグラム伸長を行うルックアップテーブルをR,G,Bごとに作成する for (i = 0; i < 256; i++) { // iを0から255まで1ずつ増やす tableR[i] = 255./(maxR-minR)*(i-minR); // 赤画素値のヒストグラム伸長の変換値を求めてtableRに代入する tableG[i] = 255./(maxG-minG)*(i-minG); // 緑画素値のヒストグラム伸長の変換値を求めてtableGに代入する tableB[i] = 255./(maxB-minB)*(i-minB); // 青画素値のヒストグラム伸長の変換値を求めてtableBに代入する } // R,G,Bごとにヒストグラム伸長を行う for (y = 0; y < f.height; y++) { // yを0から画像縦幅-1まで1ずつ増やす for (x = 0; x < f.width; x++) { // xを0から画像横幅-1まで1ずつ増やす c = f.get(x, y); // 画像fの座標(x,y)の色の値(color型)をcに代入する R = tableR[int(red(c))]; // 赤の画素値に対応する変換値をtableRから取り出してRに代入する G = tableG[int(green(c))]; // 緑の画素値に対応する変換値をtableGから取り出してRに代入する B = tableB[int(blue(c))]; // 青の画素値に対応する変換値をtableBから取り出してRに代入する g.set(x, y, color(R, G, B)); // R,G,Bから作ったcolor型の値を画像gの座標(x,y)の画素に設定する } } g.save("output.jpg"); // 画像gをファイルoutput.jpgに保存する } void draw() { image(f, 0, 0); // 実行画面の左側に原画像fを貼る image(g, f.width, 0); // 実行画面の右側に変換後画像gを貼る } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
def setup(): global f, g # 変数f,gのグローバル宣言 f = loadImage("image.jpg") # 原画像を画像fに読み込む g = createImage(f.width, f.height, RGB) # 画像gを画像fと同じサイズで作る this.surface.setSize(f.width*2, f.height) # 実行画面のサイズを原画像の2倍の幅に設定する # ヒストグラムを計算する histR = [0]*256 # リストhistRを宣言する(赤ヒストグラム) histG = [0]*256 # リストhistGを宣言する(緑ヒストグラム) histB = [0]*256 # リストhistBを宣言する(青ヒストグラム) for y in range(0, f.height): # yを0から画像縦幅-1まで1ずつ増やす for x in range(0, f.width): # xを0から画像横幅-1まで1ずつ増やす c = f.get(x, y) # 画像fの座標(x,y)の色の値(color型)をcに代入する histR[int(red(c)) ] += 1 # cから赤画素値を取り出し、histRに個数をカウントする histG[int(green(c))] += 1 # cから緑画素値を取り出し、histGに個数をカウントする histB[int(blue(c)) ] += 1 # cから青画素値を取り出し、histBに個数をカウントする # 累積ヒストグラムを計算する for i in range(1, 256): # iを1から255まで1ずつ増やす histR[i] += histR[i-1] # histR[i]にhistR[i-1]の値を加算する histG[i] += histG[i-1] # histG[i]にhistG[i-1]の値を加算する histB[i] += histB[i-1] # histB[i]にhistB[i-1]の値を加算する # ヒストグラムから画素値の最小値と最大値を得る。ただし、ヒストグラムの右端と左端から割合aを除いた範囲とする a = .02 # aに計算から除くヒストグラムの範囲の割合を[0,.5)の範囲で指定する s = float(histR[255]) # sにhistR[255]の値(画像の全画素数)を代入する minR = minG = minB = 0 # 画素値の最小値minR,minG,minBを0で初期化する maxR = maxG = maxB = 255 # 画素値の最大値maxR,maxG,maxBを255で初期化する while histR[minR]/s < a and minR < 255: minR += 1 # 赤の最小画素値を求めてminRに入れる while histG[minG]/s < a and minG < 255: minG += 1 # 緑の最小画素値を求めてminGに入れる while histB[minB]/s < a and minB < 255: minB += 1 # 青の最小画素値を求めてminBに入れる a = 1 - a # aに1-aの値を代入する while histR[maxR]/s > a and maxR > 0: maxR -= 1 # 赤の最大画素値を求めてmaxRに入れる while histG[maxG]/s > a and maxG > 0: maxG -= 1 # 緑の最大画素値を求めてmaxGに入れる while histB[maxB]/s > a and maxB > 0: maxB -= 1 # 青の最大画素値を求めてmaxBに入れる # ヒストグラム伸長を行うルックアップテーブルをR,G,Bごとに作成する tableR = [255./(maxR-minR)*(i-minR) for i in range(0, 256)] # 赤画素値のヒストグラム伸長の変換値を求めてtableRに代入する tableG = [255./(maxG-minG)*(i-minG) for i in range(0, 256)] # 緑画素値のヒストグラム伸長の変換値を求めてtableGに代入する tableB = [255./(maxB-minB)*(i-minB) for i in range(0, 256)] # 青画素値のヒストグラム伸長の変換値を求めてtableBに代入する # R,G,Bごとにヒストグラム伸長を行う for y in range(0, f.height): # yを0から画像縦幅-1まで1ずつ増やす for x in range(0, f.width): # xを0から画像横幅-1まで1ずつ増やす c = f.get(x, y) # 画像fの座標(x,y)の色の値(color型)をcに代入する R = tableR[int(red(c))] # 赤の画素値に対応する変換値をtableRから取り出してRに代入する G = tableG[int(green(c))] # 緑の画素値に対応する変換値をtableGから取り出してRに代入する B = tableB[int(blue(c))] # 青の画素値に対応する変換値をtableBから取り出してRに代入する g.set(x, y, color(R, G, B)) # R,G,Bから作ったcolor型の値を画像gの座標(x,y)の画素に設定する g.save("output.jpg") # 画像gをファイルoutput.jpgに保存する def draw(): image(f, 0, 0) # 実行画面の左側に原画像fを貼る image(g, f.width, 0) # 実行画面の右側に変換後画像gを貼る |
Processingの組み込みフィルタ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
PImage f, g1, g2, g3, g4, g5, g6; // 画像オブジェクトf,g1,g2,g3,g4,g5,g6を宣言する void setup() { f = loadImage("image.jpg"); // 画像fへファイルimage.jpgのデータを読み込む surface.setSize(f.width*3, f.height*2); // 実行画面のサイズを画像fの横3倍、縦2倍に設定する g1 = f.copy(); // 画像fをコピーして画像g1を作る g2 = f.copy(); // 画像fをコピーして画像g2を作る g3 = f.copy(); // 画像fをコピーして画像g3を作る g4 = f.copy(); // 画像fをコピーして画像g4を作る g5 = f.copy(); // 画像fをコピーして画像g5を作る g6 = f.copy(); // 画像fをコピーして画像g6を作る g1.filter(GRAY); // 画像g1をグレイスケール画像に変換する g2.filter(POSTERIZE, 4); // 画像g2をポスタリゼーション(階調数変更)する g3.filter(THRESHOLD, 0.5); // 画像g3を2値画像に閾値処理する g4.filter(INVERT); // 画像g4を輝度反転(ネガポジ反転)する g5.filter(BLUR, 1.5); // 画像g5にガウシアンフィルタ(平滑化フィルタ)をかける g6.filter(ERODE); // 画像g6に収縮フィルタ(最小値フィルタ)をかける。 // 膨張フィルタ(最大値フィルタ)の場合はDILATEを指定する } void draw() { image(g1, 0, 0); // 実行画面の左上に画像g1を貼る image(g2, f.width, 0); // 実行画面の中上に画像g2を貼る image(g3, f.width*2, 0); // 実行画面の右上に画像g3を貼る image(g4, 0, f.height); // 実行画面の左下に画像g4を貼る image(g5, f.width, f.height); // 実行画面の中下に画像g5を貼る image(g6, f.width*2, f.height); // 実行画面の右下に画像g6を貼る } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
def setup(): global f, g1, g2, g3, g4, g5, g6 # 変数f,g1,g2,g3,g4,g5,g6のグローバル宣言 f = loadImage("image.jpg") # 画像fへファイルimage.jpgのデータを読み込む this.surface.setSize(f.width*3, f.height*2) # 実行画面のサイズを画像fの横3倍、縦2倍に設定する g1 = f.copy() # 画像fをコピーして画像g1を作る g2 = f.copy() # 画像fをコピーして画像g2を作る g3 = f.copy() # 画像fをコピーして画像g3を作る g4 = f.copy() # 画像fをコピーして画像g4を作る g5 = f.copy() # 画像fをコピーして画像g5を作る g6 = f.copy() # 画像fをコピーして画像g6を作る g1.filter(GRAY) # 画像g1をグレイスケール画像に変換する g2.filter(POSTERIZE, 4) # 画像g2をポスタリゼーション(階調数変更)する g3.filter(THRESHOLD, 0.5) # 画像g3を2値画像に閾値処理する g4.filter(INVERT) # 画像g4を輝度反転(ネガポジ反転)する g5.filter(BLUR, 1.5) # 画像g5にガウシアンフィルタ(平滑化フィルタ)をかける g6.filter(ERODE) # 画像g6に収縮フィルタ(最小値フィルタ)をかける。 # 膨張フィルタ(最大値フィルタ)の場合はDILATEを指定する def draw(): image(g1, 0, 0) # 実行画面の左上に画像g1を貼る image(g2, f.width, 0) # 実行画面の中上に画像g2を貼る image(g3, f.width*2, 0) # 実行画面の右上に画像g3を貼る image(g4, 0, f.height) # 実行画面の左下に画像g4を貼る image(g5, f.width, f.height) # 実行画面の中下に画像g5を貼る image(g6, f.width*2, f.height) # 実行画面の右下に画像g6を貼る |
平均値フィルタ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
PImage f, g; // 画像オブジェクトf,gを宣言する void setup() { int x, y; // 整数型変数x,yを宣言する float a, w; // 実数型変数x,yを宣言する f = loadImage("image.jpg"); // 画像fへファイルimage.jpgのデータを読み込む f.filter(GRAY); // 画像fをグレイスケール画像に変換する g = createImage(f.width, f.height, RGB); // 画像gを画像fと同じサイズで作る surface.setSize(f.width*2, f.height); // 実行画面のサイズを画像fの2倍の幅に設定する w = 1./9; // wに平均値フィルタの係数1/9を代入する for (y = 1; y < f.height-1; y++) { // yを1から画像縦幅-2まで1ずつ増やす for (x = 1; x < f.width-1; x++) { // xを1から画像縦幅-2まで1ずつ増やす // 画像fの座標(x,y)を中心した3×3の領域の各画素の画素値にwをかけて、その総和をaに代入する a = w*red(f.get(x-1,y-1)) + w*red(f.get(x,y-1)) + w*red(f.get(x+1,y-1)) + w*red(f.get(x-1,y )) + w*red(f.get(x,y )) + w*red(f.get(x+1,y )) + w*red(f.get(x-1,y+1)) + w*red(f.get(x,y+1)) + w*red(f.get(x+1,y+1)); g.set(x, y, color(a)); // aからcolor型の値を作り、画像gの座標(x,y)の画素値に設定する } } } void draw() { image(f, 0, 0); // 実行画面の左側に原画像fを貼る image(g, f.width, 0); // 実行画面の右側に変換後画像gを貼る } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
def setup(): global f, g f = loadImage("image.jpg") # 画像fへファイルimage.jpgのデータを読み込む f.filter(GRAY) # 画像fをグレイスケール画像に変換する g = createImage(f.width, f.height, RGB) # 画像gを画像fと同じサイズで作る this.surface.setSize(f.width*2, f.height) # 実行画面のサイズを画像fの2倍の幅に設定する w = 1./9 # wに平均値フィルタの係数1/9を代入する for y in range(1, f.height-1): # yを1から画像縦幅-2まで1ずつ増やす for x in range(1, f.width-1): # xを1から画像縦幅-2まで1ずつ増やす # 画像fの座標(x,y)を中心した3×3の領域の各画素の画素値にwをかけて、その総和をaに代入する a = w*red(f.get(x-1,y-1)) + w*red(f.get(x,y-1)) + w*red(f.get(x+1,y-1)) \ + w*red(f.get(x-1,y )) + w*red(f.get(x,y )) + w*red(f.get(x+1,y )) \ + w*red(f.get(x-1,y+1)) + w*red(f.get(x,y+1)) + w*red(f.get(x+1,y+1)) g.set(x, y, color(a)) # aからcolor型の値を作り、画像gの座標(x,y)の画素値に設定する def draw(): image(f, 0, 0) # 実行画面の左側に原画像fを貼る image(g, f.width, 0) # 実行画面の右側に変換後画像gを貼る |
1次微分フィルタ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
PImage f, g1, g2, g3; // 画像オブジェクトf,g1,g2,g3を宣言する void setup() { int x, y; // 整数型変数x,yを宣言する float dx, dy, norm; // 実数型変数dx,dy,normを宣言する f = loadImage("image.jpg"); // 画像fへファイルimage.jpgのデータを読み込む f.filter(GRAY); // 画像fをグレイスケールに変換する g1 = createImage(f.width, f.height, RGB); // 画像g1を画像fと同じサイズで作る g2 = createImage(f.width, f.height, RGB); // 画像g2を画像fと同じサイズで作る g3 = createImage(f.width, f.height, RGB); // 画像g3を画像fと同じサイズで作る surface.setSize(f.width*2, f.height*2); // 実行画面のサイズを画像fの2倍の幅に設定する 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)におけるx軸方向の微分を計算してdxに代入する dy = red(f.get(x ,y+1)) - red(f.get(x,y)); // 座標(x,y)におけるy軸方向の微分を計算してdyに代入する norm = sqrt(dx*dx + dy*dy); // エッジ強度を計算してnormに代入する dx = abs(dx); // dxを絶対値に変換する dy = abs(dy); // dyを絶対値に変換する g1.set(x, y, color(dx)); // dxからcolor型の値を作り、画像g1の座標(x,y)の画素値に設定する g2.set(x, y, color(dy)); // dyからcolor型の値を作り、画像g2の座標(x,y)の画素値に設定する g3.set(x, y, color(norm)); // normからcolor型の値を作り、画像g3の座標(x,y)の画素値に設定する } } } void draw() { image(f, 0, 0); // 実行画面の左上に原画像fを貼る image(g1, f.width, 0); // 実行画面の右上に画像g1を貼る image(g2, 0, f.height); // 実行画面の左下に画像g2を貼る image(g3, f.width, f.height); // 実行画面の右下に画像g3を貼る } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
def setup(): global f, g1, g2, g3 f = loadImage("image.jpg") # 画像fへファイルimage.jpgのデータを読み込む f.filter(GRAY) # 画像fをグレイスケールに変換する g1 = createImage(f.width, f.height, RGB) # 画像g1を画像fと同じサイズで作る g2 = createImage(f.width, f.height, RGB) # 画像g2を画像fと同じサイズで作る g3 = createImage(f.width, f.height, RGB) # 画像g3を画像fと同じサイズで作る this.surface.setSize(f.width*2, f.height*2) # 実行画面のサイズを画像fの2倍の幅に設定する for y in range(1, f.height-1): # yを1から画像縦幅-2まで1ずつ増やす for x in range(1, f.width-1): # xを1から画像縦幅-2まで1ずつ増やす dx = red(f.get(x+1,y )) - red(f.get(x,y)) # 座標(x,y)におけるx軸方向の微分を計算してdxに代入する dy = red(f.get(x ,y+1)) - red(f.get(x,y)) # 座標(x,y)におけるy軸方向の微分を計算してdyに代入する norm = sqrt(dx*dx + dy*dy) # エッジ強度を計算してnormに代入する dx = abs(dx) # dxを絶対値に変換する dy = abs(dy) # dyを絶対値に変換する g1.set(x, y, color(dx)) # dxからcolor型の値を作り、画像g1の座標(x,y)の画素値に設定する g2.set(x, y, color(dy)) # dyからcolor型の値を作り、画像g2の座標(x,y)の画素値に設定する g3.set(x, y, color(norm)) # normからcolor型の値を作り、画像g3の座標(x,y)の画素値に設定する def draw(): image(f, 0, 0) # 実行画面の左上に原画像fを貼る image(g1, f.width, 0) # 実行画面の右上に画像g1を貼る image(g2, 0, f.height) # 実行画面の左下に画像g2を貼る image(g3, f.width, f.height) # 実行画面の右下に画像g3を貼る |
エンボス加工
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
PImage f, g; // 画像オブジェクトf,gを宣言する void setup() { int x, y; // 整数型変数x,yを宣言する float d; // 実数型変数dを宣言する f = loadImage("image.jpg"); // 画像fへファイルimage.jpgのデータを読み込む f.filter(GRAY); // 画像fをグレイスケールに変換する g = createImage(f.width, f.height, RGB); // 画像gを画像fと同じサイズで作る surface.setSize(f.width*2, f.height); // 実行画面のサイズを画像fの2倍の幅に設定する for (y = 0; y < f.height-1; y++) { // yを0から画像縦幅-2まで1ずつ増やす for (x = 0; x < f.width-1; x++) { // xを0から画像縦幅-2まで1ずつ増やす d = red(f.get(x+1,y+1)) - red(f.get(x,y)); // 座標(x+1,y+1)から(x,y)の画素値の差分を計算してdに代入する d += 128; // dに128を加える g.set(x, y, color(d)); // dからcolor型の値を作り、画像gの座標(x,y)の画素値に設定する } } } void draw() { image(f, 0, 0); // 実行画面の左側に画像f(原画像)を貼る image(g, f.width, 0); // 実行画面の右側に画像g(変換後画像)を貼る } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
def setup(): global f, g f = loadImage("image.jpg") # 画像fへファイルimage.jpgのデータを読み込む f.filter(GRAY) # 画像fをグレイスケールに変換する g = createImage(f.width, f.height, RGB) # 画像gを画像fと同じサイズで作る this.surface.setSize(f.width*2, f.height) # 実行画面のサイズを画像fの2倍の幅に設定する for y in range(0, f.height-1): # yを0から画像縦幅-2まで1ずつ増やす for x in range(0, f.width-1): # xを0から画像縦幅-2まで1ずつ増やす d = red(f.get(x+1,y+1)) - red(f.get(x,y)) # 座標(x,y)におけるx軸方向の微分を計算してdxに代入する d += 128 # dに128を加える g.set(x, y, color(d)) # dからcolor型の値を作り、画像gの座標(x,y)の画素値に設定する def draw(): image(f, 0, 0) # 実行画面の左側に原画像fを貼る image(g, f.width, 0) # 実行画面の右側に変換後画像gを貼る |
2次微分フィルタ(ラプラシアンフィルタ)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
PImage f, g; // 画像オブジェクトf,gを宣言する void setup() { int x, y; // 整数型変数x,yを宣言する float a; // 実数型変数aを宣言する f = loadImage("image.jpg"); // 画像fへファイルimage.jpgのデータを読み込む f.filter(GRAY); // 画像fをグレイスケール画像に変換する g = createImage(f.width, f.height, RGB); // 画像gを画像fと同じサイズで作成する surface.setSize(f.width*2, f.height); // 実行画面の横幅を画像fの2倍に設定する for (y = 1; y < f.height-1; y++) { // yを1から画像縦幅-2まで1ずつ増やす for (x = 1; x < f.width-1; x++) { // xを1から画像縦幅-2まで1ずつ増やす // 画像fの座標(x,y)を中心した3×3の領域の各画素の画素値にラプラシアンフィルタの係数をかけて、その総和をaに代入する 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)); a = abs(a); // 画像化するために、aの絶対値を求めて0以上の数にする g.set(x, y, color(a)); // aからcolor型の値を作り、画像gの座標(x,y)の画素値に設定する } } } void draw() { image(f, 0, 0); // 実行画面の左側に原画像fを貼る image(g, f.width, 0); // 実行画面の右側に変換後画像gを貼る } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
def setup(): global f, g f = loadImage("image.jpg") # 画像fへファイルimage.jpgのデータを読み込む f.filter(GRAY) # 画像fをグレイスケールに変換する g = createImage(f.width, f.height, RGB) # 画像gを画像fと同じサイズで作る this.surface.setSize(f.width*2, f.height) # 実行画面のサイズを画像fの2倍の幅に設定する for y in range(1, f.height-1): # yを1から画像縦幅-2まで1ずつ増やす for x in range(1, f.width-1): # xを1から画像縦幅-2まで1ずつ増やす # 画像fの座標(x,y)を中心した3×3の領域の各画素の画素値にラプラシアンフィルタの係数をかけて、その総和をaに代入する 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)) a = abs(a) # 画像化するために、aの絶対値を求めて0以上の数にする g.set(x, y, color(a)) # aからcolor型の値を作り、画像gの座標(x,y)の画素値に設定する g.save("output.jpg") # 画像gをファイルoutput.jpgに保存する def draw(): image(f, 0, 0) # 実行画面の左側に原画像fを貼る image(g, f.width, 0) # 実行画面の右側に変換後画像gを貼る |
画像の平行移動
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
PImage f, g; void setup() { int X, Y, x, y; // 変換前座標を(X,Y)、変換後座標を(x,y)とする float a; f = loadImage("image.jpg"); // 原画像fをファイルから読み込む f.filter(GRAY); // 原画像fをグレイスケール画像に変換する g = createImage(f.width, f.height, RGB); // 変換後画像gを作成する surface.setSize(f.width, f.height); for (y = 0; y < g.height; y++) { // 変換後座標x,yを用いてラスタ走査を行う for (x = 0; x < g.width; x++) { // x軸方向に+80、y軸方向に+30の平行移動の逆変換式(変換前座標←変換後座標) X = x - 80; Y = y - 30; a = red(f.get(X, Y)); // 画像fの座標(X,Y)から画素値aを取得する g.set(x, y, color(a)); // 画像gの座標(x,y)に画素値aを設定する } } } void draw() { image(g, 0, 0); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
def setup(): global g f = loadImage("image.jpg") # 原画像fをファイルから読み込む f.filter(GRAY) # 原画像fをグレイスケール画像に変換する g = createImage(f.width, f.height, RGB) # 変換後画像gを作成する this.surface.setSize(f.width, f.height) for y in range(0, g.height): # 変換後座標x,yを用いてラスタ走査を行う for x in range(0, g.width): # x軸方向に+80、y軸方向に+30の平行移動の逆変換式(変換前座標←変換後座標) X = x - 80 Y = y - 30 a = red(f.get(X, Y)) # 画像fの座標(X,Y)から画素値aを取得する g.set(x, y, color(a)) # 画像gの座標(x,y)に画素値aを設定する def draw(): image(g, 0, 0) |
画像の拡大縮小(最近隣内挿)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
PImage f, g; void setup() { int X, Y, x, y; // 変換前座標を(X,Y)、変換後座標を(x,y)とする float Xf, Yf; // 変換前の実数座標を(Xf, Yf)とする float a; f = loadImage("image.jpg"); f.filter(GRAY); // 原画像fをグレイスケール画像に変換する g = createImage(f.width, f.height, RGB); // 変換後画像gを原画像fと同じサイズで作成する surface.setSize(f.width, f.height); for (y = 0; y < g.height; y++) { for (x = 0; x < g.width; x++) { // x軸方向に1.3倍、y軸方向に0.6倍の拡大の逆変換式(変換前座標←変換後座標) Xf = x / 1.3; Yf = y / 0.6; // 最近隣内挿により再標本化をする X = int(Xf + .5); // 小数点以下を四捨五入して整数座標を求める Y = int(Yf + .5); a = red(f.get(X, Y)); g.set(x, y, color(a)); } } } void draw() { image(g, 0, 0); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
def setup(): global g f = loadImage("image.jpg") # 原画像fをファイルから読み込む f.filter(GRAY) # 原画像fをグレイスケール画像に変換する g = createImage(f.width, f.height, RGB) # 変換後画像gを原画像fと同じサイズで作成する this.surface.setSize(f.width, f.height) for y in range(0, g.height): # 変換後座標x,yを用いてラスタ走査を行う for x in range(0, g.width): # x軸方向に1.3倍、y軸方向に0.6倍の拡大の逆変換式(変換前座標←変換後座標) Xf = x / 1.3 Yf = y / 0.6 # 最近隣内挿により再標本化をする X = int(Xf + .5) # 小数点以下を四捨五入して整数座標を求める Y = int(Yf + .5) a = red(f.get(X, Y)) g.set(x, y, color(a)) def draw(): image(g, 0, 0) |
画像の拡大縮小(バイリニア内挿)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
PImage f, g; void setup() { int X, Y, x, y; // 変換前座標を(X,Y)、変換後座標を(x,y)とする float Xf, Yf; // 変換前の実数座標を(Xf, Yf)とする float a, s, t; f = loadImage("image.jpg"); f.filter(GRAY); // 原画像fをグレイスケール画像に変換する g = createImage(f.width, f.height, RGB); // 変換後画像gを原画像fと同じサイズで作成する surface.setSize(f.width, f.height); for (y = 0; y < g.height; y++) { for (x = 0; x < g.width; x++) { // x軸方向に1.3倍、y軸方向に0.6倍の拡大の逆変換式(変換前座標←変換後座標) Xf = x / 1.3; Yf = y / 0.6; // バイリニア内挿により再標本化をする X = int(Xf); // Xfの整数部を取り出す Y = int(Yf); // Yfの整数部を取り出す s = Xf - X; // Xfの小数部を取り出す t = Yf - Y; // 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)); } } } void draw() { image(g, 0, 0); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
def setup(): global g f = loadImage("image.jpg") # 原画像fをファイルから読み込む f.filter(GRAY) # 原画像fをグレイスケール画像に変換する g = createImage(f.width, f.height, RGB) # 変換後画像gを原画像fと同じサイズで作成する this.surface.setSize(f.width, f.height) for y in range(0, g.height): # 変換後座標x,yを用いてラスタ走査を行う for x in range(0, g.width): # x軸方向に1.3倍、y軸方向に0.6倍の拡大の逆変換式(変換前座標←変換後座標) Xf = x / 1.3 Yf = y / 0.6 # バイリニア内挿により再標本化をする X = int(Xf) # Xfの整数部を取り出す Y = int(Yf) # Yfの整数部を取り出す s = Xf - X # Xfの小数部を取り出す t = Yf - Y # 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)) def draw(): image(g, 0, 0) |
画像の回転
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
PImage f, g; void setup() { int X, Y, x, y; // 変換前座標を(X,Y)、変換後座標を(x,y)とする float Xf, Yf; // 変換前の実数座標を(Xf, Yf)とする float a, s, t, rad; f = loadImage("image.jpg"); f.filter(GRAY); // 原画像fをグレイスケール画像に変換する g = createImage(f.width, f.height, RGB); // 変換後画像gを原画像fと同じサイズで作成する surface.setSize(f.width, f.height); rad = radians(15); // 角度15度をラジアン単位に変換してradに代入する for (y = 0; y < g.height; y++) { for (x = 0; x < g.width; x++) { // 角度radの回転の逆変換式(変換前座標←変換後座標) Xf = x*cos(rad) + y*sin(rad); Yf = -x*sin(rad) + y*cos(rad); // バイリニア内挿により再標本化をする X = int(Xf); // Xfの整数部を取り出す Y = int(Yf); // Yfの整数部を取り出す s = Xf - X; // Xfの小数部を取り出す t = Yf - Y; // 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)); } } } void draw() { image(g, 0, 0); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
def setup(): global g f = loadImage("image.jpg") # 原画像fをファイルから読み込む f.filter(GRAY) # 原画像fをグレイスケール画像に変換する g = createImage(f.width, f.height, RGB) # 変換後画像gを原画像fと同じサイズで作成する this.surface.setSize(f.width, f.height) rad = radians(15) # 角度15度をラジアン単位に変換してradに代入する for y in range(0, g.height): # 変換後座標x,yを用いてラスタ走査を行う for x in range(0, g.width): # 角度radの回転の逆変換式(変換前座標←変換後座標) Xf = x*cos(rad) + y*sin(rad) Yf = -x*sin(rad) + y*cos(rad) # バイリニア内挿により再標本化をする X = int(Xf) # Xfの整数部を取り出す Y = int(Yf) # Yfの整数部を取り出す s = Xf - X # Xfの小数部を取り出す t = Yf - Y # 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)) def draw(): image(g, 0, 0) |
アフィン変換
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
PImage f, g; void setup() { int X, Y, x, y; // 変換前座標を(X,Y)、変換後座標を(x,y)とする float Xf, Yf; // 変換前の実数座標を(Xf, Yf)とする float a, s, t; float a1, a2, a3, a4, a5, a6; // アフィン変換パラメータの変数a1~a6の宣言 f = loadImage("image.jpg"); f.filter(GRAY); // 原画像fをグレイスケール画像に変換する g = createImage(f.width, f.height, RGB); // 変換後画像gを原画像fと同じサイズで作成する surface.setSize(f.width, f.height); for (y = 0; y < g.height; y++) { for (x = 0; x < g.width; x++) { // アフィン変換パラメータを設定する a1 = 2.2; a2 = 0.4; a3 = -300; a4 = -0.2; a5 = 1.5; a6 = -50; // アフィン変換を計算する Xf = a1*x + a2*y + a3; Yf = a4*x + a5*y + a6; // バイリニア内挿により再標本化をする X = int(Xf); // Xfの整数部を取り出す Y = int(Yf); // Yfの整数部を取り出す s = Xf - X; // Xfの小数部を取り出す t = Yf - Y; // 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)); } } } void draw() { image(g, 0, 0); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
def setup(): global g f = loadImage("image.jpg") # 原画像fをファイルから読み込む f.filter(GRAY) # 原画像fをグレイスケール画像に変換する g = createImage(f.width, f.height, RGB) # 変換後画像gを原画像fと同じサイズで作成する this.surface.setSize(f.width, f.height) for y in range(0, g.height): # 変換後座標x,yを用いてラスタ走査を行う for x in range(0, g.width): # アフィン変換パラメータを設定する a1 = 2.2 a2 = 0.4 a3 = -300.0 a4 = -0.2 a5 = 1.5 a6 = -50.0 # アフィン変換を計算する Xf = a1*x + a2*y + a3 Yf = a4*x + a5*y + a6 # バイリニア内挿により再標本化をする X = int(Xf) # Xfの整数部を取り出す Y = int(Yf) # Yfの整数部を取り出す s = Xf - X # Xfの小数部を取り出す t = Yf - Y # 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)) def draw(): image(g, 0, 0) |
射影変換
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
PImage f, g; void setup() { int X, Y, x, y; // 変換前座標を(X,Y)、変換後座標を(x,y)とする float Xf, Yf; // 変換前の実数座標を(Xf, Yf)とする float a, s, t; float h1, h2, h3, h4, h5, h6, h7, h8; // 射影変換パラメータ f = loadImage("image.jpg"); f.filter(GRAY); // 原画像fをグレイスケール画像に変換する g = createImage(f.width, f.height, RGB); // 変換後画像gを原画像fと同じサイズで作成する surface.setSize(f.width, f.height); for (y = 0; y < g.height; y++) { for (x = 0; x < g.width; x++) { // 射影変換パラメータを設定する h1 = 0.936719; h2 = 0.054535; h3 = -92.94375; h4 = -0.730045; h5 = 1.358224; h6 = 43.02176; h7 = -0.003078805; h8 = 0.001698254; // 射影変換を計算する Xf = (h1*x + h2*y + h3) / (h7*x + h8*y + 1); Yf = (h4*x + h5*y + h6) / (h7*x + h8*y + 1); // バイリニア内挿により再標本化をする X = int(Xf); // Xfの整数部を取り出す Y = int(Yf); // Yfの整数部を取り出す s = Xf - X; // Xfの小数部を取り出す t = Yf - Y; // 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)); } } } void draw() { image(g, 0, 0); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
def setup(): global g f = loadImage("image.jpg") # 原画像fをファイルから読み込む f.filter(GRAY) # 原画像fをグレイスケール画像に変換する g = createImage(f.width, f.height, RGB) # 変換後画像gを原画像fと同じサイズで作成する this.surface.setSize(f.width, f.height) for y in range(0, g.height): # 変換後座標x,yを用いてラスタ走査を行う for x in range(0, g.width): # 射影変換パラメータを設定する h1 = 0.936719 h2 = 0.054535 h3 = -92.94375 h4 = -0.730045 h5 = 1.358224 h6 = 43.02176 h7 = -0.003078805 h8 = 0.001698254 # 射影変換を計算する Xf = (h1*x + h2*y + h3) / (h7*x + h8*y + 1) Yf = (h4*x + h5*y + h6) / (h7*x + h8*y + 1) # バイリニア内挿により再標本化をする X = int(Xf) # Xfの整数部を取り出す Y = int(Yf) # Yfの整数部を取り出す s = Xf - X # Xfの小数部を取り出す t = Yf - Y # 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)) def draw(): image(g, 0, 0) |