Processingで画像の色情報を取得するアプリを作ってみた
Processing触ってみたら、思いのほか楽しかったので簡単なGUIアプリを作成してみた。
画像を読み込んで、Ctrl+マウスで選択した矩形範囲のRGB平均値を表示するだけのアプリ。
地味にハマったのがフォントの作成。
フォントはProcessingのMENUから予め作成しておく必要がある。
以下、コード。
calcal.pde
PImage img; int winWidth, winHeight; ArrayList selecters; // Select Rect Class boolean selecting = false; boolean showingHelp = false; void setup() { img = loadImage( selectInput() ); /* Resize Image */ if (640 < img.width) { img.resize(640, 0); } if (480 < img.height) { img.resize(0, 480); } winWidth = img.width; winHeight = img.height; size(winWidth, winHeight); noStroke(); /* Init ArrayList */ selecters = new ArrayList(); } void draw() { background(0); image(img, 0, 0); int size = selecters.size(); if (0 < size) { for (int i=0; i<size-1; i++) { ((CRect)selecters.get(i)).update(); } if (selecting) { ((CRect)selecters.get(size-1)).update(mouseX, mouseY); } else { ((CRect)selecters.get(size-1)).update(); } } if (showingHelp) { stroke(80, 180, 0); fill(0, 120, 20, 150); rect(0, 0, 240, winHeight); PFont font = loadFont("SansSerif.plain-12.vlw"); textFont(font, 12); fill(255); int str_x = 10; int str_y = 30; text("--- Help ---", str_x, str_y); text("Ctrl + MouseLeftPress :", str_x, str_y+=25); text("Select Color Analyzing Area", str_x+10, str_y+=16); text("key \'h\' :", str_x, str_y+=30); text("Show/Hide Help", str_x+10, str_y+=16); text("key \'r\' :", str_x, str_y+=20); text("Clear All Select Area", str_x+10, str_y+=16); text("key \'d\' :", str_x, str_y+=20); text("Remove Lateset Select Area", str_x+10, str_y+=16); } } void mousePressed() { switch (mouseButton) { case LEFT: if ((true == keyPressed) && (CONTROL == keyCode)) { selecters.add( new CRect(mouseX, mouseY) ); selecting = true; } break; default: break; } } void mouseReleased() { selecting = false; } void keyPressed() { switch (key) { case 'd': /* delete latest selecter */ if (0 < selecters.size()) { selecters.remove( selecters.size()-1 ); } break; case 'r': /* clear selecters */ selecters.clear(); break; case 'h': /* show/hide help */ showingHelp = (false == showingHelp) ? true : false; break; default: break; } } void keyReleased() { selecting = false; }
選択領域クラスのコード。
CRect.pde
/* Convert RGB to YUV */ int Y_yuv(color rgb) { int y = int(0.299*red(rgb) + 0.587*green(rgb) + 0.114*blue(rgb)); return y; } int Cb_yuv(color rgb) { int cb = int(0.169*red(rgb) - 0.331*green(rgb) + 0.500*blue(rgb)); return cb; } int Cr_yuv(color rgb) { int cr = int(0.500*red(rgb) - 0.419*green(rgb) - 0.081*blue(rgb)); return cr; } class CRect { int sx, sy, ex, ey; int small_x, small_y, large_x, large_y; color rgb; int yuv_y, yuv_cb, yuv_cr; int xyz_x, xyz_y, xyz_z; CRect(int x, int y) { this.sx = x; this.sy = y; this.ex = this.sx; this.ey = this.sy; } void update() { this.select(); this.textcolor(); } void update(int x, int y) { this.ex = x; this.ey = y; this.config(); this.select(); this.ave(); this.yuv(); this.textcolor(); } private void config() { /* rect(x1, y1, x2, y2)で x1>x2 もしくは y1>y2 になると落ちる対策 */ if (this.sx > this.ex) { this.small_x = this.ex; this.large_x = this.sx; } else { this.small_x = this.sx; this.large_x = this.ex; } if (this.sy > this.ey) { this.small_y = this.ey; this.large_y = this.sy; } else { this.small_y = this.sy; this.large_y = this.ey; } } private void select() { stroke(40, 0, 80); fill(255, 255, 255, 40); rect(this.small_x, this.small_y, (this.large_x - this.small_x), (this.large_y - this.small_y)); } private void ave() { long sum_r = 0, sum_g = 0, sum_b = 0; long count = 0; for (int i=this.small_x; i<=this.large_x; i++) { for (int j=this.small_y; j<=this.large_y; j++) { color c = get(i, j); sum_r += red(c); sum_g += green(c); sum_b += blue(c); count++; } } this.rgb = color( int(sum_r/count), int(sum_g/count), int(sum_b/count) ); } private void yuv() { this.yuv_y = Y_yuv(this.rgb); this.yuv_cb = Cb_yuv(this.rgb); this.yuv_cr = Cr_yuv(this.rgb); } private void textcolor() { PFont font = loadFont("SansSerif.plain-12.vlw"); textFont(font, 10); fill(0); String str_rgb = "RGB: " + int(red(this.rgb)) + ", " + int(green(this.rgb)) + ", " + int(blue(this.rgb)); String str_yuv = "YUV: " + this.yuv_y + ", " + this.yuv_cb + ", " + this.yuv_cr; text(str_rgb, this.small_x+5, this.small_y+10); text(str_yuv, this.small_x+5, this.small_y+25); } }
GitHubでも、はてなダイアリーでもProcessingってサポートされてないのね…。
参考ページ
Processing.org
yoppa org – Processingで画像データを扱う
Processing基礎最速入門 - catch.jp-wiki
建築発明工作ゼミ2008: Processing 文字と画像
[Processing]マウス座標の取得とArrayListを使った応用 | うえちょこ@ぼろぐ
a-07 画像を使う - Processing 学習ノート