64
Media Art II 2011 第6回:openFrameworks 外部メディアを利用する 画像と動画 2011年10月11日 多摩美術大学 情報デザイン学科 情報芸術コース 田所 淳

openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

Embed Size (px)

Citation preview

Page 1: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

Media Art II 2011 第6回:openFrameworks外部メディアを利用する画像と動画

2011年10月11日多摩美術大学 情報デザイン学科 情報芸術コース田所 淳

Page 2: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

今日の内容‣ 外部メディアをopenFrameworks内で使用する‣ 今回はビットマップ画像データと動画データを扱います

‣ ビットマップ画像は実際どうなっているのか?‣ ビットマップ画像を読み込んで表示する‣ ビットマップ画像のピクセルデータにアクセスする‣ ビットマップ画像の再合成

‣ 動画データのしくみ‣ 動画を読み込んで表示する‣ 動画の解析、再合成

Page 3: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

サンプルファイル‣ 解説しているサンプルプログラムは全て下記からダウンロード可能です (Google Docsにリンク)

‣ http://goo.gl/T5sov

Page 4: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

ビットマップ画像のしくみ‣ そもそも、コンピュータモニタに、画像が映しだされる仕組み

‣ グリッド状に並んだ「ピクセル」という点の集合で構成される‣ 巨大なエクセルの表のようなイメージ

Page 5: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

ビットマップ画像のしくみ‣ 例えば、640 x 480 pixel の画像データの場合640 x 480 = 307,200307,200 個のピクセルから構成された平面

640 pixel

480 pixe

l

Page 6: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

ビットマップ画像のしくみ‣ 様々な種類のモニタを拡大した様子、ピクセルが見える

Page 7: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

ビットマップ画像のしくみ‣ それぞれのピクセルにはRGBとアルファチャンネルAのデータが格納されている(フルカラーの場合)

‣ それぞれのチャンネルに、8bit = 256 の階調を持つ

Page 8: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

ビットマップ画像のしくみ‣ 画像データのコンピュータ内での扱い‣ ラスターイメージ:ビットマップ画像を点が線上に並んだもの(ラスター)の集まりとして扱う

...

Page 9: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

ビットマップ画像のしくみ‣ 1ピクセルの中では、画像の色数に応じてそれぞれの画素が順番に並んでいる、1画素あたり8bit (0 ~ 255) の値

フルカラー(32bit) R G B A R G B A ...

フルカラーアルファ無し(24bit)

...R G B R G B R G B

グレースケール(8bit) K K K K K K K K K ...

R

1 pixel

1 pixel

Page 10: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

ビットマップ画像を表示する‣ コンピュータ内でのビットマップデータの内容を踏まえ、実際にopenFrameworksで画像を表示してみる

‣ 画像を扱うクラス:ofImage//ofImageをインスタンス化ofImage myImage;

//ビットマップ画像の読みこみmyImage.loadImage("画像ファイル名");!//ビットマップ画像の描画myImage.draw(float x, float y, float w, float h);

Page 11: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

ビットマップ画像を表示する‣ openFrameworksで読み込むデータは、以下の場所に格納‣ プロジェクトフォルダ > bin > data

‣ 画像、フォント、サウンド、設定ファイルなど

Page 12: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

ビットマップ画像を表示する‣ testApp.h#pragma once

#include "ofMain.h"

class testApp : public ofBaseApp{!public:! void setup();! void update();! void draw();

! //ofImageをインスタンス化! ofImage myImage;};

Page 13: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

ビットマップ画像を表示する‣ testApp.cpp#include "testApp.h"

void testApp::setup(){! ofBackground(0, 0, 0);!! //ビットマップ画像の読みこみ! myImage.loadImage("t_hero.png");!}

void testApp::update(){

}

void testApp::draw(){! //画像の位置を調整! int left = (ofGetWidth() - myImage.width) / 2;! int top = (ofGetHeight() - myImage.height) / 2;!! //ビットマップ画像の描画! myImage.draw(left, top);}

Page 14: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

ビットマップ画像を表示する‣ 実行結果

Page 15: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

ビットマップ画像を操作する‣ 読み込んだビットマップ画像データを、プログラムで操作‣ ofImageに読み込んだデータのピクセル単位での値を読み込むことが可能

‣ それぞれのピクセルの値を、配列として取り出す

‣ これにより、pixels[0], pixels[1], pixels[2]... と順番に画像のラスターが格納される

unsigned char * pixels = rioImage.getPixels();

Page 16: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

画像をピクセレイト - モザイク‣ 読み込んだ画像を、モザイク状にしてみる

‣ 方法:‣ 画像を読みこむ‣ ピクセル情報を取得‣ 一定の数ごとにスキップしながら、ピクセル値を読みこむ‣ 読み込んだ値をもとに、画像を再構成

Page 17: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

画像をピクセレイト - モザイク‣ testApp.cpp (1 / 2)#include "testApp.h"

void testApp::setup(){! ofBackground(0, 0, 0);!! //ビットマップ画像の読みこみ! myImage.loadImage("t_hero.png");}

void testApp::update(){

}

void testApp::draw(){

! //画像の位置を調整! int left = (ofGetWidth() - myImage.width) / 2;! int top = (ofGetHeight() - myImage.height) / 2;! ofTranslate(left, top);!! //ピクセル情報をとりだす! unsigned char * pixels = myImage.getPixels();

Page 18: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

画像をピクセレイト - モザイク‣ testApp.cpp (2 / 2)

! //20ピクセル毎に明度を取り出し、その色でRectを描画! int skip = 20;! for (int i = 0; i < myImage.width; i = i + skip){! ! for (int j = 0; j < myImage.height; j = j + skip){! ! ! int brightness = pixels[j*myImage.width + i];! ! ! ofSetColor(brightness, brightness, brightness);! ! ! ofRect(i, j, skip, skip);!! ! }! }}

Page 19: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

画像をピクセレイト - モザイク‣ 実行結果

Page 20: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

円の半径で濃度を表現‣ 読み出した明度情報を活用して、いろいろ試してみる

‣ 例えば…‣ 読み出した明度で円の半径を変化させてみる

Page 21: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

円の半径で濃度を表現‣ testApp.cpp - draw()void testApp::draw(){! //画像の位置を調整! int left = (ofGetWidth() - myImage.width) / 2;! int top = (ofGetHeight() - myImage.height) / 2;! ofTranslate(left, top);!! //ピクセル情報をとりだす! unsigned char * pixels = myImage.getPixels();

! //10ピクセル毎に明度を取り出し、その色でRectを描画! int skip = 12;! ofSetColor(0, 0, 0);! for (int i = 0; i < myImage.width; i = i + skip){! ! for (int j = 0; j < myImage.height; j = j + skip){! ! ! int brightness = pixels[j*myImage.width + i];! ! ! //大きさの割合(%)を算出! ! ! float pct = 1.0 - brightness / 255.0f;! ! ! //円を描く! ! ! ofCircle(i, j, pct * skip * 0.5);! ! }! }}

Page 22: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

円の半径で濃度を表現‣ 円の半径によって画像を表現

Page 23: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

角度を変化させて画像を再現‣ 明度で角度を変化させてみるとどうなるか?

Page 24: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

角度を変化させて画像を再現‣ testApp.cpp - draw()void testApp::draw(){! int left = (ofGetWidth() - myImage.width) / 2;! int top = (ofGetHeight() - myImage.height) / 2;! ofTranslate(left, top);! unsigned char * pixels = myImage.getPixels();

! int skip = 8;! ofSetColor(255, 255, 255);! ofSetLineWidth(3);! for (int i = 0; i < myImage.width; i = i + skip){! ! for (int j = 0; j < myImage.height; j = j + skip){! ! ! int brightness = pixels[j*myImage.width + i];! ! ! float pct = 1.0 - brightness / 255.0f;

! ! ! //角度を変化させて線を描く! ! ! ofPushMatrix();! ! ! ofTranslate(i, j);! ! ! ofRotateZ(pct * 90);! ! ! ofLine(-skip, 0, skip, 0);! ! ! ofPopMatrix();! ! }! }}

Page 25: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

角度を変化させて画像を再現‣ 角度によって画像を表現

Page 26: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

角度を変化させて画像を再現‣ さらに線の太さを変化させる

Page 27: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

文字によるピクセレイト‣ 文字をつかって、画像を表現してみる

‣ まず、文字の濃度順に並べた文字列を準備‣ 例えば「 . - + * a & @」の8文字‣ 濃度に応じて文字を選択して、所定の座標に文字を表示

Page 28: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

文字によるピクセレイト‣ testApp.cpp (1 / 2)#include "testApp.h"

void testApp::setup(){! ofBackground(255, 255, 255);! //ビットマップ画像の読みこみ! myImage.loadImage("t_hero.png");!! //8段階の文字の濃度を文字列に! pixelString = " .-+*a&@";!}

void testApp::update(){!}

void testApp::draw(){! int left = (ofGetWidth() - myImage.width) / 2;! int top = (ofGetHeight() - myImage.height) / 2;! ofTranslate(left, top);! unsigned char * pixels = myImage.getPixels();

! int skip = 6;! ofSetColor(0, 0, 0);

Page 29: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

文字によるピクセレイト‣ testApp.cpp (2 / 2)!! for (int i = 0; i < myImage.width; i = i + skip){! ! for (int j = 0; j < myImage.height; j = j + skip){! ! ! int brightness = pixels[j*myImage.width + i];! ! ! float pct = 1.0 - brightness / 255.0f;! ! ! //濃度の応じた文字をとりだし! ! ! string str = pixelString.substr(int(pct * 8),1);! ! ! //文字を描画! ! ! ofDrawBitmapString(str, i, j);! ! }! }}

Page 30: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

文字によるピクセレイト‣ 実行結果

Page 31: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

カラー画像を扱う‣ カラー画像を扱う際には、注意が必要‣ 24bitカラーのPNGデータの場合、ピクセルデータの列(ラスター)は、RGBの順に並んでいる

‣ つまり、1pixelあたり3つのデータが並ぶ‣ 1つのデータには、それぞれ256階調(8bit)の情報

‣ 幅640pixelの画像であれば、一列で 640 x 4 = 22560個‣ img.getPixel() した配列の読み出しの際に注意する

...R G B R G B R G B1 pixel

Page 32: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

カラー画像を扱う‣ testApp.cpp - draw()void testApp::draw(){! //画像の位置を調整! int left = (ofGetWidth() - myImage.width) / 2;! int top = (ofGetHeight() - myImage.height) / 2;! ofTranslate(left, top);!! //ピクセル情報をとりだす! unsigned char * pixels = myImage.getPixels();

! //10ピクセル毎に明度を取り出し、その色でRectを描画! int skip = 10;! for (int i = 0; i < myImage.width; i = i + skip){! ! for (int j = 0; j < myImage.height; j = j + skip){! ! ! //RGBの順でデータをとりだす! ! ! int r = pixels[j * myImage.width * 3 + i * 3];! ! ! int g = pixels[j * myImage.width * 3 + i * 3 + 1];! ! ! int b = pixels[j * myImage.width * 3 + i * 3 + 2];! ! ! //取得した色で、四角形を描画! ! ! ofSetColor(r, g, b);! ! ! ofRect(i, j, skip, skip);!! ! }! }}

Page 33: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

カラー画像を扱う‣ 実行結果

Page 34: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

カラー画像を扱う‣ 取り出した情報をもとに、グレースケールと同様に様々な方法で画像を再合成することが可能となる

‣ 例えば、‣ 明度を線の角度と長さで‣ 色はそのまま使用

Page 35: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

カラー画像を扱う‣ testApp.cpp - draw()void testApp::draw(){! int left = (ofGetWidth() - myImage.width) / 2;! int top = (ofGetHeight() - myImage.height) / 2;! ofTranslate(left, top);! unsigned char * pixels = myImage.getPixels();

! int skip = 8;! for (int i = 0; i < myImage.width; i = i + skip){! ! for (int j = 0; j < myImage.height; j = j + skip){! ! ! int r = pixels[j * myImage.width * 3 + i * 3];! ! ! int g = pixels[j * myImage.width * 3 + i * 3 + 1];! ! ! int b = pixels[j * myImage.width * 3 + i * 3 + 2];! ! ! int brightness = (r + g + b) / 3.0f * 255.0f;! ! ! float pct = 1.0 - (r + g + b) / 3.0f / 255.0f;! ! ! //線の角度と長さで画像を再現! ! ! ofSetColor(r, g, b);! ! ! ofPushMatrix();! ! ! ofTranslate(i, j);! ! ! ofRotateZ(pct * 360);! ! ! ofLine(-pct*skip*4, 0, pct*skip*4, 0);! ! ! ofPopMatrix();! ! }! }}

Page 36: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

カラー画像を扱う‣ 実行結果

Page 37: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

動画を扱う‣ 次に動画を扱ってみたい‣ 動画は、基本的には時間軸に沿ってビットマップ画像が並んでいると考えられる

時間

Page 38: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

動画を扱う‣ openFrameworksでは、ofImageと同じような感覚で使用できる動画を扱うクラスが存在する

‣ 動画ファイルの読込み(.mov, .mp4など):ofVideoPlayer‣ カメラから直接取り込む : ofVideoGrabber

‣ 読み込んだデータは、ofImageと同じようにピクセル単位で情報を取得することが可能

Page 39: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

動画を扱う‣ まずはシンプルに、カメラからキャプチャーした映像を、そのまま画面に描画してみる

Page 40: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

動画を扱う‣ testApp.h#pragma once

#include "ofMain.h"

class testApp : public ofBaseApp{public: void setup(); void update(); void draw(); ! //カメラからの映像取得のためのクラス ofVideoGrabber myVideo;};

Page 41: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

動画を扱う‣ testApp.cpp#include "testApp.h"

void testApp::setup(){! ofSetFrameRate(60);! ofBackground(0, 0, 0);

! //640x480 pixelでカメラの映像をキャプチャー myVideo.initGrabber(640, 480, true); }

void testApp::update(){! //カメラの取得を更新 myVideo.update();}

void testApp::draw(){! //位置を補整! int left = (ofGetWidth() - myVideo.width) / 2;! int top = (ofGetHeight() - myVideo.height) / 2;! ofTranslate(left, top);!! //カメラの映像を描画! myVideo.draw(0, 0);}

Page 42: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

動画をピクセレイト‣ 動画の情報をピクセレイトしてみる‣ 方法は、カラー画像の際とほとんど同じ

Page 43: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

動画をピクセレイト‣ testApp.cpp (1 / 2)#include "testApp.h"

void testApp::setup(){! ofSetFrameRate(60);! ofBackground(0, 0, 0);! ofSetRectMode(OF_RECTMODE_CENTER);!! //640x480 pixelでカメラの映像をキャプチャー myVideo.initGrabber(800, 600, true); }

void testApp::update(){! //カメラの取得を更新 myVideo.update();}

void testApp::draw(){! //位置を補整! int left = (ofGetWidth() - myVideo.width) / 2;! int top = (ofGetHeight() - myVideo.height) / 2;! ofTranslate(left, top);!! //全てのピクセルの値を取得! unsigned char * pixels = myVideo.getPixels();

Page 44: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

動画をピクセレイト‣ testApp.cpp (2 / 2)

! int skip = 12;! for (int i = 0; i < myVideo.width; i = i + skip){! ! for (int j = 0; j < myVideo.height; j = j + skip){ //RGBごとのピクセルの値を取得 int r = pixels[j * myVideo.width * 3 + i * 3];! ! ! int g = pixels[j * myVideo.width * 3 + i * 3 + 1];! ! ! int b = pixels[j * myVideo.width * 3 + i * 3 + 2];! ! ! //明度を算出! ! ! int brightness = (r + g + b) / 3.0f * 255.0f;! ! ! float pct = (r + g + b) / 3.0f / 255.0f;! ! ! //四角形の角度と大きさで画像を再現! ! ! ofSetColor(255,255,255);! ! ! ofPushMatrix();! ! ! ofTranslate(i, j);! ! ! ofRotateZ(pct * 180);! ! ! ofRect(0, 0, skip * pct, skip * pct);! ! ! ofPopMatrix();! ! }! }}

Page 45: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

動画をピクセレイト‣ 完成!

Page 46: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

動画を文字でピクセレイト‣ 文字で動画をピクセレイトしてみる‣ この手法も静止画の際と同じ

Page 47: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

動画を文字でピクセレイト‣ testApp.cpp (1 / 2)#include "testApp.h"

void testApp::setup(){! ofSetFrameRate(60);! ofBackground(255, 255, 255);! ofSetRectMode(OF_RECTMODE_CENTER);! //8段階の文字の濃度を文字列に! pixelString = " .-+*a&@";! //640x480 pixelでカメラの映像をキャプチャー myVideo.initGrabber(800, 600, true); }

void testApp::update(){! //カメラの取得を更新 myVideo.update();}

void testApp::draw(){! //位置を補整! int left = (ofGetWidth() - myVideo.width) / 2;! int top = (ofGetHeight() - myVideo.height) / 2;! //全てのピクセルの値を取得! unsigned char * pixels = myVideo.getPixels();

Page 48: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

動画を文字でピクセレイト‣ testApp.cpp (2 / 2)! int skip = 8;! ofTranslate(left, top+skip);! ofSetColor(0, 0, 0);! for (int i = 0; i < myVideo.width; i = i + skip){! ! for (int j = 0; j < myVideo.height; j = j + skip){! ! ! //RGBごとのピクセルの値を取得! ! ! int r = pixels[j * myVideo.width * 3 + i * 3];! ! ! int g = pixels[j * myVideo.width * 3 + i * 3 + 1];! ! ! int b = pixels[j * myVideo.width * 3 + i * 3 + 2];! ! ! //明度を算出! ! ! float pct = 1.0 - (r + g + b) / 3.0f / 255.0f;! ! ! //濃度の応じた文字をとりだし! ! ! string str = pixelString.substr(int(pct * 8),1);! ! ! //文字を描画! ! ! ofDrawBitmapString(str, i, j);! ! }! }}

Page 49: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

動画を文字でピクセレイト‣ 完成!!

Page 50: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

おまけ:glitch!!‣ グリッチ(glitch):回路の接触不良や、コンピュータの誤動作などで出てくるノイズを活用した表現

‣ 音楽:Ovalに代表される、音飛びのデジタルノイズ

Page 51: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

おまけ:glitch!!‣ グリッチの思想は、音だけでなく画像や動画にも応用可能‣ 例えば、画像ファイルのフォーマットをわざと破壊してみる

‣ 参考:”Visual Glitch, using Ruby” ucnv‣ http://www.ustream.tv/recorded/16077641

Page 52: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

おまけ:glitch!! - 画像をグリッジ‣ まずは、画像ファイルをグリッジしてみる‣ 粗いJpeg形式に圧縮してからグリッジするのがポイント

元画像を読みこみ

Jpeg圧縮して保存

Jpegファイルをバッファーに読込

データを破壊

Page 53: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

おまけ:glitch!! - 画像をグリッジ‣ testApp.h#pragma once

#include "ofMain.h"

class testApp : public ofBaseApp {!public:! void setup();! void update();! void draw();! void keyPressed(int key);! void mousePressed(int x, int y, int button);!! void reset();! ofImage img;! ofImageQualityType quality;};

Page 54: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

おまけ:glitch!! - 画像をグリッジ‣ testApp.cpp (1 / 3)#include "testApp.h"

void testApp::setup() {! ofSetFrameRate(60);! ofSetBackgroundAuto(false);! //Jpeg圧縮の強度! quality = OF_IMAGE_QUALITY_WORST;! //リセット! reset();}

void testApp::reset() {! //元のファイルを読込み! img.loadImage("input.jpg");}

void testApp::update() {! //Jpeg圧縮したデータの保存ファイル名! string compressedFilename = "compressed.jpg";! //Jpeg形式でファイルを保存! img.saveImage(compressedFilename, quality);! ofBuffer file = ofBufferFromFile(compressedFilename);! int fileSize = file.size();

Page 55: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

おまけ:glitch!! - 画像をグリッジ‣ testApp.cpp (2 / 3)! //Jepgファイルをバッファーに読込み! char * buffer = file.getBinaryBuffer();! //データを破壊する場所をランダムに決定! int whichByte = (int) ofRandom(fileSize);! //ONにするbitをランダムに決定! int whichBit = ofRandom(8);! //ビットシフト(データを破壊?)! char bitMask = 1 << whichBit;! buffer[whichByte] |= bitMask;! //glitchしたファイルを保存! ofBufferToFile(compressedFilename, file);! //再度読込み! img.loadImage(compressedFilename);}

void testApp::draw() {! //glitchしたイメージを描画! ofSetColor(255,255,255);! img.draw(0, 0, ofGetWidth(), ofGetHeight());}

Page 56: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

おまけ:glitch!! - 画像をグリッジ‣ testApp.cpp (3 / 3)void testApp::keyPressed (int key){! //リセット! reset();}

void testApp::mousePressed(int x, int y, int button){! //リセット! reset();}

Page 57: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

おまけ:glitch!! - 画像をグリッジ‣ glitch!!

Page 58: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

おまけ:glitch!! - カメラの映像をglitch!‣ さらに応用して、カメラの映像をリアルタイムにグリッジさせてみる!!

Webカメラの映像

Jpeg圧縮して保存

Jpegファイルをバッファーに読込

データを破壊

Page 59: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

おまけ:glitch!! - カメラの映像をglitch!‣ testApp.h#pragma once

#include "ofMain.h"

class testApp : public ofBaseApp {!public:! void setup();! void update();! void draw();! void keyPressed(int key);! void mousePressed(int x, int y, int button);!! void reset();!! ofImage img;! ofImageQualityType quality;! ofVideoGrabber myVideo;};

Page 60: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

おまけ:glitch!! - カメラの映像をglitch!‣ testApp.cpp (1 / 3)#include "testApp.h"

void testApp::setup() {! ofSetFrameRate(60);! quality = OF_IMAGE_QUALITY_WORST;! //カメラを初期化! myVideo.initGrabber(320, 240, true);! //スクリーンをキャプチャしてofImageに格納! img.grabScreen(0, 0, ofGetWidth(), ofGetHeight());}

void testApp::reset() {! //ビデオをアップデート! myVideo.update();! //ビデオのフレームを1コマ読込み! myVideo.draw(0, 0, ofGetWidth(), ofGetHeight());! //スクリーンをキャプチャしてofImageに格納! img.grabScreen(0, 0, ofGetWidth(), ofGetHeight());}

Page 61: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

おまけ:glitch!! - カメラの映像をglitch!‣ testApp.cpp (2 / 3)void testApp::update() {! //Jpeg圧縮したデータの保存ファイル名! string compressedFilename = "compressed.jpg";! //Jpeg形式でファイルを保存! img.saveImage(compressedFilename, quality);! ofBuffer file = ofBufferFromFile(compressedFilename);! int fileSize = file.size();! //Jepgファイルをバッファーに読込み! char * buffer = file.getBinaryBuffer();! //データを破壊する場所をランダムに決定! int whichByte = (int) ofRandom(fileSize);! //ONにするbitをランダムに決定! int whichBit = ofRandom(8);! //ビットシフト(データを破壊?)! char bitMask = 1 << whichBit;! buffer[whichByte] |= bitMask;! //glitchしたファイルを保存! ofBufferToFile(compressedFilename, file);! //再度読込み! img.loadImage(compressedFilename);

Page 62: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

おまけ:glitch!! - カメラの映像をglitch!‣ testApp.cpp (3 / 3)! //ランダムなタイミングで自動的にリセット! float coin = ofRandom(100);! if (coin > 95) {! ! reset();! }}

void testApp::draw() {! //glitchしたイメージを描画! ofSetColor(255);! img.draw(0, 0, ofGetWidth(), ofGetHeight());}

void testApp::keyPressed (int key){! reset();}

void testApp::mousePressed(int x, int y, int button){! reset();}

Page 63: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

おまけ:glitch!! - カメラの映像をglitch!‣ 完成:カメラからの映像をglitch!!

Page 64: openFrameworks 外部ファイルを利用する - 画像、動画 - 多摩美メディアアートII

次回の予告‣ 次回、より高度な画像処理を扱います‣ 映像の中の動いている物体だけを抽出するには?‣ 物体の輪郭、重心を算出‣ 顔をトラッキング ...etc

‣ 映像を媒介にした、インタラクティブアートの基礎