<< Flash ActionScript2.0 実践講座6:ビデオ映像を扱う | top | ネットワークの利用 >>
JitterとProcessing+JMyronで映像を扱う
本日の予定
前回のFlashでの映像処理に引き続いて、今回はJitterとProcessingでのリアルタイム映像処理について学びます。扱う開発環境に違いによって、向き不向きなどがあるので、どのようなことをやりたいのかによって使いわけるようにすると、効率的に作品の制作ができるのではないかと思います。
本日のスライド
サンプルファイル
目次
- 本題の前に…
- Jitterを用いたリアルタイム映像処理
- Jitterでのビデオ取り込み
- Jitter:ビデオ映像の加工、変形
- RybczynskiエフェクトJitter版
- 音に反応するビデオ映像
- Jitterでの画像解析
- ビデオ映像を3Dのテクスチャに
- 応用:ビデオ映像で3D形態を変形
- Processing + JMyronを用いたリアルタイム映像処理
本題の前に…
書籍の紹介
- 2061:Maxオデッセイ
- ノイマンピアノ(赤松正行+佐近田展康)著
- リットーミュージック
- 6,800円 + 税
- Max/MSP Jitterを用いた作品、パフォーマンスを行いたいと考えているのであれば、絶対買って損のない本です。(価格は結構しますが…)
- 書籍のサポートサイト
- http://max.iamas.ac.jp/
- 書籍で紹介されているサンプルパッチとオブジェクトリファレンスがダウンロード可能
- (書籍がなくても?) “2061SampleBrowser”を順を追って勉強していくだけで、とても参考になりそうです。
- わからないオブジェクトに関しては、"2061ObjectBrowser”で確認できます
Jitterを用いたリアルタイム映像処理
- Jitterを用いたビデオ機器からの映像入力とその処理について学びます。
- 接続したカメラから映像をキャプチャーする方法
- キャプチャーした映像の画像処理
- 音に反応するリアルタイム映像
- 特定色域のトラッキング
- 変化量の抽出 など
Jitterでのビデオ取り込み


- jit.qt.grabオブジェクトを用いてビデオ映像入力する
- jit.qt.grabオブジェクト
- アトリビュート:[幅] [高さ] [ビデオ機器の種類(オプション)]
- openメッセージ:ビデオデバイスの取得、入力開始
- closeメッセージ:ビデオデバイスの開放、利用終了
- getdevlist:ビデオ入力デバイスのリストを取得
- getinputlist:ビデオ入力のリストを取得
- vmode:ビデオ入力モード
- 0:プレビューモード(負荷=軽、画質=劣)
- 1:vdig(Video Digitizer)モード、ビデオ機器のデバイスドライバから直で画像を取得する(負荷=軽、画質=優)
- 2:レコードモード(負荷=重、画質=優)
- settingメッセージ:ビデオデバイスの設定
- 圧縮方法、画質、色温度などの設定
Jitter:ビデオ映像の加工、変形


- jit.qt.grabオブジェクトで取得した画像はマトリクス形式に既に変換済みなので、QuickTimeムービーを扱う際と同じ要領で、加工、編集、解析することが可能
- Jitterに用意されている様々なエフェクトをリアルタイムに使用できる
- ビデオ画像にエフェクトを加えたサンプル
- jit.wake:映像をフィードバックさせている
RybczynskiエフェクトJitter版


- 前回Flashで解説した、Rybczynskiの「四次元」風エフェクトをJitterで再現してみる
- Flashよりも処理が早いような印象。。。
- Jitter版の方が音との同期など応用も簡単にできるので、こちらでやったほうがいいかもしれません
- rateの数字を変化させると、ユラユラのスピードを変化させることも可能
- jit.matrixsetにラインの高さの数だけマトリックスを記憶しておく
- その後、ラインを変化させて、jit.matrixに再構成している
音に反応するビデオ映像


- 前期の講義「第7回:Jitter(1): Jitter入門、マトリクスとは?、QuickTimeムービのコントロール」でQuickTimeのコントロールで用いた手法
- サウンドファイルのオーディオシグナルをsnapshotオブジェクトを用いて定期的に数字を抽出する
- その数字を用いて、映像のスケールや回転などをコントロールすることで音と同期する映像を作りだす
- 今回はそのリアルタイム版
- 音量でムービーの大きさと回転をコントロール
Jitterでの画像解析

- キャプチャーした画像のマトリクスを分析する
- jit.histogram:データを同じ数値ごとに分類し、値の分布を数える
- jit.unpack:プレーン毎に分解
- jit.spuill:データをリストに変換
- multislider:リスト化されたデータをグラフに可視化
- jit.3m:マトリクスのデータの最小値、平均値、最大値を求める
- キャプチャーした画像のマトリクスを分析する
ビデオ映像を3Dのテクスチャに


- キャプチャーした画像のマトリクスをOpenGLの3Dジオメトリのテクスチャとして使用することも可能
- 使用法はQuickTimeムービーをテクスチャにするやりかたと同じ
- 映像をマトリクスにして、テクチャとして定義する
応用:ビデオ映像で3D形態を変形


- キャプチャーした画像のマトリクスを利用して、3Dジオメトリの形態をリアルタイムに変形させるパッチ
Processing + JMyronを用いたリアルタイム映像処理
Myron(JMyron)とは

- http://webcamxtra.sourceforge.net/
- C++のコアライブラリーと、様々な言語で利用するためのラッパーから成る
- Java、Processing、Macromedia Directorから利用が可能
- オープンソースで開発が行われている、ビデオキャプチャーやコンピュータビジョンに関するプラグイン
ちなみに、Myron(JMyron)の由来とは?

- Myron Krueger (1942 - )アメリカのコンピュータアーティスト。初期のインタラクティブ・アートを開発した。またバーチャルリアリティーやオーギュメンテッドリアリティの初期世代として知られている。
JMyronをインストールする
- JMyronのWebページよりProcessing用のJMyronのライブラリーのパッケージを入手する
- ダウンロードページ(http://webcamxtra.sourceforge.net/download.shtml)に進み、”Processing Library”をダウンロードする
- ダウンロードしたzipファイルを解凍する
- “JMyron”フォルダを、Processingフォルダ内の”libraries”フォルダにコピースル
- “JMyron Examples”フォルダを、Processingフォルダ内の”examples”フォルダにコピーする
- Windowsのみ:”Extra DLLs”フォルダを”C:¥windows¥System32”にコピーする
まずはシンプルに映像を取り込んでみる

import JMyron.*;
//カメラのオブジェクト
JMyron m;
void setup(){
size(320,240);
frameRate(15);
//カメラのオブジェクトの
//新しいインスタンスを作成
m = new JMyron();
//キャプチャ開始
m.start(width,height);
//フレームレートを上げるため
//画像解析機能をoffにする
m.findGlobs(0);
}
void draw(){
//カメラ映像のアップデート
m.update();
//カメラの画像をピクセルで取得
int[] img = m.image();
//表示画面のピクセル配列をロード
loadPixels();
for(int i=0;i<width*height;i++){
//表示画面の各ピクセル配列に、
//ビデオ画像のピクセルの配列を読み込み
pixels[i] = img[i];
}
//表示画面のピクセル配列を更新
updatePixels();
}
public void stop(){
m.stop();
super.stop();
}
取り込んだ映像をRGBに分解

import JMyron.*;
JMyron m;
void setup(){
size(320*3,240);
frameRate(15);
m = new JMyron();
m.start(width,height);
m.findGlobs(0);
}
void draw(){
background(0);
m.update();
int[] img = m.image();
float[] r = new float[width*height];
float[] g = new float[width*height];
float[] b = new float[width*height];
loadPixels();
for(int i=0;i<width*height;i++){
r[i] = red(img[i]);
g[i] = green(img[i]);
b[i] = blue(img[i]);
}
for(int y=0;y<height;y++){
for(int x=0;x<width;x++){
pixels[y*width+int(x/3)]=color(r[y*width+x],0,0);
pixels[y*width+int(x/3)+320]=color(0,g[y*width+x],0);
pixels[y*width+int(x/3)+640]=color(0,0,b[y*width+x]);
}
}
updatePixels();
}
public void stop(){
m.stop();
super.stop();
}
ビデオ映像をピクセレート:その1

import JMyron.*;
JMyron m;
int camera_width, camera_height;
void setup(){
size(800,600);
background(0);
camera_width = 20;
camera_height = 15;
frameRate(15);
m = new JMyron();
m.start(camera_width, camera_height);
m.update();
m.adaptivity(10);
m.adapt();
rectMode(CENTER);
noStroke();
smooth();
}
void draw(){
background(0);
m.update();
int col= width/camera_width;
int row= height/camera_height;
int[] img = m.image();
for(int y=0;y<camera_height;y++){
for(int x=0;x<camera_width;x++){
float av = (red(img[y*camera_width+x])+green(img[y*camera_width+x])+blue(img[y*camera_width+x]))/3.0;
fill(red(img[y*camera_width+x]),green(img[y*camera_width+x]),blue(img[y*camera_width+x]),128);
pushMatrix();
translate(x*col+col*0.5,y*row+row*0.5);
rotate(av/32.0);
rect(0,0,av/4.0, av/4.0);
popMatrix();
}
}
}
ビデオ映像をピクセレート:その2

import JMyron.*;
JMyron m;
int camera_width, camera_height;
void setup(){
size(800,600);
background(0);
camera_width = width/36;
camera_height = height/36;
frameRate(15);
m = new JMyron();
m.start(camera_width, camera_height);
m.update();
m.adaptivity(10);
m.adapt();
ellipseMode(CENTER);
noStroke();
smooth();
}
void draw(){
m.update();
float col= width/camera_width;
float row= height/camera_height;
int[] img = m.image();
for(int y=0;y<camera_height;y++){
for(int x=0;x<camera_width;x++){
float av = (red(img[y*camera_width+x])+green(img[y*camera_width+x])+blue(img[y*camera_width+x]))/3.0;
fill(red(img[y*camera_width+x]),green(img[y*camera_width+x]),blue(img[y*camera_width+x]),32);
pushMatrix();
translate(x*col+col*0.5,y*row+row*0.5);
ellipse(0,0,(256-av)/4.0, (256-av)/4.0);
popMatrix();
}
}
}
ビデオ映像をピクセレート:その3

import JMyron.*;
JMyron m;
int camera_width, camera_height;
void setup(){
size(800,600);
background(255);
camera_width = int(width/15);
camera_height = int(height/15);
frameRate(30);
m = new JMyron();
m.start(camera_width, camera_height);
noStroke();
smooth();
}
void draw(){
int col= width/camera_width;
int row= height/camera_height;
m.update();
//変化した部分のみ抽出
int[] img = m.image();
//カメラのピクセルの明度と色を線の大きさ、色、回転で表現
for(int y=0;y<camera_height;y++){
for(int x=0;x<camera_width;x++){
float av = 255-(red(img[y*camera_width+x])+green(img[y*camera_width+x])+blue(img[y*camera_width+x]))/3.0;
stroke(red(img[y*camera_width+x]),green(img[y*camera_width+x]),blue(img[y*camera_width+x]),128);
pushMatrix();
translate(x*col+col*0.5,y*row+row*0.5);
translate(random(-col,col), random(-row,row));
rotate(av/8.0);
//rotate(random(PI*2));
line(av/20,0,av/-20,0);
popMatrix();
}
}
}
//マウスクリックで画面クリア
void mouseReleased() {
background(255);
}
変化した部分だけを、表示する

import JMyron.*;
JMyron m;
void setup(){
size(320,240);
frameRate(15);
m = new JMyron();
m.start(width,height);
m.update();
m.adaptivity(10);
m.adapt();
rectMode(CENTER);
noStroke();
}
void draw(){
m.update();
int[] img = m.differenceImage();
loadPixels();
for(int i=0;i<width*height;i++){
pixels[i] = img[i];
}
updatePixels();
}
変化した部分をピクセレイトする

import JMyron.*;
JMyron m;
int camera_width, camera_height;
void setup(){
size(800,600);
background(255);
camera_width = 40;
camera_height = 30;
frameRate(15);
m = new JMyron();
m.start(camera_width, camera_height);
m.update();
m.adaptivity(10);
m.adapt();
noStroke();
smooth();
}
void draw(){
int col= width/camera_width;
int row= height/camera_height;
m.update();
//変化した部分のみ抽出
int[] img = m.differenceImage();
//カメラのピクセルの明度と色を、四角形の大きさ、色、回転で表現
for(int y=0;y<camera_height;y++){
for(int x=0;x<camera_width;x++){
float av = (red(img[y*camera_width+x])+green(img[y*camera_width+x])+blue(img[y*camera_width+x]))/3.0;
stroke(red(img[y*camera_width+x]),green(img[y*camera_width+x]),blue(img[y*camera_width+x]),128);
pushMatrix();
translate(x*col+col*0.5,y*row+row*0.5);
translate(random(-col,col), random(-row,row));
rotate(av/8.0);
//rotate(random(PI*2));
line(av*0.25,0,av*-0.25,0);
popMatrix();
}
}
}
//マウスクリックで画面クリア
void mouseReleased() {
background(255);
}
<< Flash ActionScript2.0 実践講座6:ビデオ映像を扱う | top | ネットワークの利用 >>


Comments
コメントはありません
Add Comment
トップページに戻る