SlideShare ist ein Scribd-Unternehmen logo
1 von 55
Downloaden Sie, um offline zu lesen
Media Art II 2013
第6回:openFrameworks
Addonを使う 2 - ofxOpenCV と ofxCv
2013年10月21日
多摩美術大学 情報デザイン学科 メディア芸術コース
田所 淳
OpenCVとは
ofxOpenCVについて
OpenCVとは - ofxOpenCVについて
‣ アドオンの使用サンプルその2
‣ ofxOpenCv
OpenCVとは - ofxOpenCVについて
‣ ofxOpenCv
‣ OpenCVをアドオンとして使用できるようにしたもの
‣ OpenCVとは?
‣ OpenCV = Open Computer Vision Library
‣ 米 Intel 社で開発された画像処理・画像認識用のC言語ライ
ブラリ
‣ オープンソース、商用・非商用を問わず無料
‣ 静止画にも動画にも対応
OpenCVとは - ofxOpenCVについて
‣ openFrameworksとOpenCVを組みあわせた作品は、数多く存
在する
‣ カメラの映像によるインタラクションは、市販の機材で構築可
能で、かつメンテナンスも容易
‣ 個人制作する作品にも転用可能
OpenCVを活用した作品例
‣ YesYesNo Night Lights
‣ http://yesyesno.com/night-lights
OpenCVを活用した作品例
‣ Graffiti Research Lab. L.A.S.E.R. Tag
‣ http://graffitiresearchlab.com/projects/laser-tag/
OpenCVを活用した作品例
‣ The Eye Writer
‣ http://www.eyewriter.org/
OpenCVを活用した作品例
‣ Chris O'shea Hand from Above
‣ http://www.chrisoshea.org/hand-from-above
OpenCVを活用した作品例
‣ Chris O'shea Audience
‣ http://www.chrisoshea.org/audience
OpenCVを活用した作品例
‣ Golan Levin Double-Taker (Snout)
‣ http://www.flong.com/projects/snout/
OpenCVを活用した作品例
‣ boards magazine interactive cover: Rise and Fall
‣ http://www.boardsmag.com/community/blogs/behindthescenes/
index.php?p=834
OpenCV で物体を認識する
‣ これらの作品に共通する技術
‣ カメラで撮影された映像から、動いている物体を検出し、その
位置や輪郭を抽出する
‣ 「ロボットの眼」をプログラミングしている
‣ OpenCVを活用すると、この物体の認識が簡単に可能となる
OpenCV で物体を認識する
‣ 映像から物体の形態を認識するアルゴリズム
カメラから映像をキャプチャー
グレースケールに変換
背景画像を登録
背景画像と現在の画像の差分を計算
差分の画像を2値化
2値化した画像を解析 (輪郭抽出、重心を算出)
OpenCV で物体を認識する
‣ apps > addonsExamples > opencvExample に物体の輪郭を抽
出するまでの、わかりやすいサンプルが掲載
‣ まずは、この基本プログラムを読み解いていきたい
ofxOpenCv 基本
‣ testApp.h
#pragma once
#include "ofMain.h"
#include "ofxOpenCv.h"
//#define _USE_LIVE_VIDEO

カメラ入力を使用する場合は
ここをコメントアウト

class testApp : public ofBaseApp{
public:
! void setup();
! void update();
! void draw();
! void keyPressed(int key);
!
! #ifdef _USE_LIVE_VIDEO
! ofVideoGrabber vidGrabber;
カメラ入力
! #else
! ofVideoPlayer vidPlayer;
動画ファイルを再生
! #endif
!
入力された元映像
! ofxCvColorImage colorImg;
! ofxCvGrayscaleImage grayImage;
グレースケールに変換後
! ofxCvGrayscaleImage grayBg;
キャプチャーされた背景画像
! ofxCvGrayscaleImage grayDiff;
背景とグレースケール画像の差分
! ofxCvContourFinder contourFinder;
輪郭を抽出するためのオブジェクト
!
! int threshold;
画像を2値化する際の閾値(しきいち)
! bool bLearnBakground;
背景を記録した際に通知
};
ofxOpenCv 基本
‣ testApp.cpp setup()
void testApp::setup(){
! ofSetFrameRate(60);
!
! #ifdef _USE_LIVE_VIDEO
カメラ入力の場合は
! vidGrabber.setVerbose(true);
カメラを初期化
! vidGrabber.initGrabber(320,240);
! #else
動画再生の場合は
! vidPlayer.loadMovie("fingers.mov");
! vidPlayer.play();
動画ファイルを読込
! #endif
!
! colorImg.allocate(320,240);
必要となる画像のための
! grayImage.allocate(320,240);
! grayBg.allocate(320,240);
メモリ領域を確保
! grayDiff.allocate(320,240);
!
背景画像を記録した状態に
! bLearnBakground = true;
! threshold = 80;
2値化の閾値を設定
}
ofxOpenCv 基本
‣ testApp.cpp update(), 1 of 2
void testApp::update(){
! ofBackground(100,100,100);
!
新規フレームのとりこみをリセット
bool bNewFrame = false;
!
! #ifdef _USE_LIVE_VIDEO
! vidGrabber.grabFrame();
カメラ入力の場合は
! bNewFrame = vidGrabber.isFrameNew();
カメラ映像を1コマ取得
! #else
! vidPlayer.idleMovie();
動画再生の場合は
! bNewFrame = vidPlayer.isFrameNew();
動画ファイルから1コマ
! #endif
ofxOpenCv 基本
‣ testApp.cpp update(), 2 of 2
!
!
!
!
!
!
!
!

if (bNewFrame){
!
!
#ifdef _USE_LIVE_VIDEO 取得した映像をキャプチャーしcolorImgに
!
colorImg.setFromPixels(vidGrabber.getPixels(), 320,240);
!
#else
!
colorImg.setFromPixels(vidPlayer.getPixels(), 320,240);
!
#endif
!
グレースケールに変換
grayImage = colorImg;

!
!
!
!
!
!
!
!
!

!
!
!
!
!
!
!
!
!

!
}

}

if (bLearnBakground == true){
!
grayBg = grayImage;
!
bLearnBakground = false;
}
grayDiff.absDiff(grayBg, grayImage);
grayDiff.threshold(threshold);

もし背景取得モードだったら
現在のグレースケール画像を
背景画像として採用
背景画像とグレー画像の
差分を計算後、
設定した閾値で2値化

contourFinder.findContours(grayDiff, 20,
(340*240)/3, 10, true);
2値化した差分画像の
輪郭線を抽出
ofxOpenCv 基本
‣ testApp.cpp draw()
void testApp::draw(){
!
! ofSetHexColor(0xffffff);
! colorImg.draw(20,20);
! grayImage.draw(360,20);
! grayBg.draw(20,280);
! grayDiff.draw(360,280);
!
! ofFill();
! ofSetHexColor(0x333333);
! ofRect(360,540,320,240);
!
! ofSetHexColor(0xffffff);
! contourFinder.draw(360,540);
}

カラー画像を描画
グレースケール画像を描画
キャプチャーした背景を描画
2値化した差分画像を描画

抽出した輪郭を表示する
背景を描画
抽出した輪郭線を描画
ofxOpenCv 基本
‣ 実行結果:動いている物体の輪郭線が抽出される
OpenCVもう一つの実装
ofxCv
OpenCVもう一つの実装 - ofxCv
‣ openFrameworksには、ofxOpenCvの他に、OpenCVを使用す
るためのアドオンがもう一つ存在する
‣ → ofxCv
‣
‣
‣
‣

ofxCv
https://github.com/kylemcdonald/ofxCv
Kyle McDonald氏によるアドオン
openFrameworksでOpenCVをより簡単に、よりパワフルに利
用できる環境を目指している
‣ OpenCVとoFのより緊密な連携
OpenCVもう一つの実装 - ofxCv
‣ ofxCvのインストール
‣ GitHubからZip形式でダウンロード
‣ addonsフォルダに格納

ココ →
ofxCv 新規プロジェクトの作成
‣ ofxCvの新規プロジェクトを作成するには、ProjectGenerator
でofxOpenCVとofxCvを選択して、Generateする
輪郭抽出をofxCvで実装
‣ 先程、ofxOpenCVで実現した、映像の中の輪郭を抽出するプ
ログラムを、ofxCvでも作成してみる
‣ ofxCvでは、とても短いプログラムで実現可能(エレガント!)
輪郭抽出をofxCvで実装
‣ testApp.h
#pragma once
#include "ofMain.h"
#include "ofxCv.h"
class testApp : public ofBaseApp {
public:
! void setup();
! void update();
! void draw();
!
! ofVideoGrabber cam;
! ofxCv::ContourFinder contourFinder;
};
輪郭抽出をofxCvで実装
‣ testApp.cpp
#include "testApp.h"
using namespace ofxCv;
using namespace cv;
void testApp::setup() {
cam.initGrabber(ofGetWidth(), ofGetHeight());
contourFinder.setMinAreaRadius(10);
contourFinder.setMaxAreaRadius(200);
}
void testApp::update() {
cam.update();
if(cam.isFrameNew()) {
contourFinder.setThreshold(ofMap(mouseX, 0, ofGetWidth(), 0,
255));
contourFinder.findContours(cam);
}
}
void testApp::draw() {
ofSetColor(255);
cam.draw(0, 0);
contourFinder.draw();
}
輪郭抽出をofxCvで実装
‣ 完成! マウスのX座標で、閾値を調整
ofxCv + ofxGui
‣ プログラムをもっと実用的(作品に利用可能)なものに
‣ 先週とりあげた、ofxGuiと組合せてみる
‣ 単純にカメラの画像の輪郭抽出ではなく、背景画像を登録し
て、その差分イメージの輪郭を抽出
‣ 背景のリセットもGUIからできるように
ofxCv + ofxGui
‣ まずは、ofxOpenCV、ofxCv、ofxGuiを選択してプロジェクト
を生成
ofxCv + ofxGui
‣ testApp.h
#pragma once
#include "ofMain.h"
#include "ofxCv.h"
#include "ofxGui.h"
class testApp : public ofBaseApp {
public:
void setup();
void update();
void draw();
void resetBackgroundPressed();
ofVideoGrabber cam;
ofxCv::ContourFinder contourFinder;
ofxCv::RunningBackground background;
ofImage thresholded;
ofxPanel gui;
ofxFloatSlider bgThresh; // 背景差分の閾値
ofxFloatSlider contourThresh; // 輪郭抽出の閾値
ofxButton resetBackgroundButton; // 背景リセットボタン
};
ofxCv + ofxGui
‣ testApp.cpp
#include "testApp.h"
using namespace ofxCv;
using namespace cv;
void testApp::setup() {
// CV初期設定

!

cam.initGrabber(ofGetWidth(), ofGetHeight());
contourFinder.setMinAreaRadius(10);
contourFinder.setMaxAreaRadius(200);
background.setLearningTime(900);
background.setThresholdValue(20);

// GUI
resetBackgroundButton.addListener(this,
&testApp::resetBackgroundPressed);
gui.setup();
gui.add(bgThresh.setup("background thresh", 50, 0, 100));
gui.add(contourThresh.setup("contour finder thresh", 127, 0, 255));
gui.add(resetBackgroundButton.setup("reset background"));
}
ofxCv + ofxGui
‣ testApp.cpp
void testApp::update() {
cam.update();
if(cam.isFrameNew()) {
// 背景差分画像を生成

!

!

background.setThresholdValue(bgThresh);
background.update(cam, thresholded);
thresholded.update();
// 背景差分画像の輪郭抽出

}

}

contourFinder.setThreshold(contourThresh);
contourFinder.findContours(thresholded);

void testApp::draw() {
// 差分画像を描画
ofSetColor(255);
thresholded.draw(0, 0);
// 輪郭抽出結果を描画

}

ofSetColor(255, 0, 0);
contourFinder.draw();
// GUI
gui.draw();
ofxCv + ofxGui
‣ testApp.cpp
void testApp::resetBackgroundPressed(){
background.reset();
}
ofxCv + ofxGui
‣ 完成!!
オプティカル・フロー (Optical Flow)
オプティカル・フロー (Optical Flow)
‣ オプティカル・フロー
‣ 映像内での物体の動きを、ベクトル場で表したもの
‣ 参考: http://opencv.jp/sample/optical_flow.html
オプティカル・フロー (Optical Flow)
‣ ofxCvでは、オプティカル・フローのための2種類のクラスが
用意されている
‣ ofxCv::FlowFarneback
‣ Gunnar Farneback のアルゴリズムを用いた、密なオプティカ
ルフロー
‣ ofxCv::FlowPyrLK
‣ 疎な特徴集合に対するオプティカルフロー
‣ 参考: http://opencv.jp/opencv-2svn/cpp/
motion_analysis_and_object_tracking.html
オプティカル・フロー (Optical Flow)
‣ testApp.h
#pragma once
#include "ofMain.h"
#include "ofxCv.h"
#include "ofxGui.h"
class testApp : public ofBaseApp {
public:
void setup();
void update();
void draw();
ofVideoGrabber camera;
ofxCv::FlowFarneback farneback;
ofxCv::FlowPyrLK pyrLk;
ofxCv::Flow* curFlow;
ofxPanel gui;
ofxFloatSlider pyrScale;
ofxIntSlider levels;
ofxIntSlider winsize;
ofxIntSlider iterations;
ofxIntSlider polyN;
ofxFloatSlider polySigma;
ofxIntSlider winSize;
ofxIntSlider maxLevel;
オプティカル・フロー (Optical Flow)
‣ testApp.h
ofxFloatSlider maxFeatures;
ofxFloatSlider qualityLevel;
ofxFloatSlider minDistance;
ofxToggle OPTFLOW_FARNEBACK_GAUSSIAN;
ofxToggle useFarneback;
};
オプティカル・フロー (Optical Flow)
‣ testApp.cpp
#include "testApp.h"
using namespace ofxCv;
using namespace cv;
void testApp::setup() {
// CV初期設定
camera.initGrabber(320, 240);
// GUI
gui.setup();
gui.add(pyrScale.setup("pyrScale", .5, 0, 1));
gui.add(levels.setup("levels", 4, 1, 8));
gui.add(winsize.setup("levels", 8, 4, 64));
gui.add(iterations.setup("iterations", 2, 1, 8));
gui.add(polyN.setup("polyN", 7, 5, 10));
gui.add(polySigma.setup("polySigma", 1.5, 1.1, 2));
gui.add(OPTFLOW_FARNEBACK_GAUSSIAN.setup("OPTFLOW_FARNEBACK_GAUSSIAN",
false));
gui.add(useFarneback.setup("useFarneback", true));
gui.add(winSize.setup("winSize", 32, 4, 64));
gui.add(maxLevel.setup("maxLevel", 3, 0, 8));
gui.add(levels.setup("maxFeatures", 200, 1, 1000));
gui.add(qualityLevel.setup("levels", 0.01, 0.001, .02));
オプティカル・フロー (Optical Flow)
‣ testApp.cpp
gui.add(minDistance.setup("minDistance", 4, 1, 16));
}

curFlow = &farneback;

void testApp::update() {
camera.update();
if(camera.isFrameNew()) {
if(useFarneback) { // Farnebackの密なオプティカルフロー
curFlow = &farneback;
farneback.setPyramidScale(pyrScale);
farneback.setNumLevels(levels);
farneback.setWindowSize(winsize);
farneback.setNumIterations(iterations);
farneback.setPolyN(polyN);
farneback.setPolySigma(polySigma);
farneback.setUseGaussian(OPTFLOW_FARNEBACK_GAUSSIAN);
} else { // 画像ピラミッドを利用した、疎なオプティカルフロー

}

curFlow = &pyrLk;
pyrLk.setMaxFeatures(maxFeatures);
pyrLk.setQualityLevel(qualityLevel);
pyrLk.setMinDistance(minDistance);
pyrLk.setWindowSize(winSize);
pyrLk.setMaxLevel(maxLevel);
オプティカル・フロー (Optical Flow)
‣ testApp.cpp
// オプティカルフローを計算

}

}

curFlow->calcOpticalFlow(camera);

void testApp::draw() {
ofBackground(0);
ofSetColor(255);
camera.draw(0,0,ofGetWidth(),ofGetHeight());
curFlow->draw(0,0,ofGetWidth(),ofGetHeight());
}

gui.draw();
オプティカル・フロー (Optical Flow)
‣ 完成!!
オプティカル・フロー + パーティクル
オプティカル・フロー + パーティクル
‣ オプティカル・フローで生成したベクトル場に、パーティクル
を置いてみる
‣ 映像を解析して、舞い散るパーティクルが実現できるはず!!
‣ Particleクラスは、以前作成したものをそのまま再利用
オプティカル・フロー + パーティクル
‣ testApp.h
#pragma once
#include
#include
#include
#include

"ofMain.h"
"ofxCv.h"
"ofxGui.h"
"Particle.h"

class testApp : public ofBaseApp {
public:
void setup();
void update();
void draw();
// Optical Flow
ofVideoGrabber camera;
ofxCv::FlowFarneback flow;
// GUI
ofxPanel gui;
ofxFloatSlider pyrScale;
ofxIntSlider levels;
ofxIntSlider winsize;
ofxIntSlider iterations;
ofxIntSlider polyN;
ofxFloatSlider polySigma;
ofxFloatSlider flowScale;
オプティカル・フロー + パーティクル
‣ testApp.h
ofxToggle drawFlow;
ofxToggle fullscreen;
ofxButton resetParticleButton;
void resetParticlePressed();

};

// Particle
vector<Particle> particles;
static const int NUM = 20000;
オプティカル・フロー + パーティクル
‣ testApp.cpp
#include "testApp.h"
using namespace ofxCv;
using namespace cv;
void testApp::setup() {
// CV初期設定
camera.initGrabber(320, 240);
ofSetFrameRate(60);
ofEnableBlendMode(OF_BLENDMODE_ADD);
// GUI
resetParticleButton.addListener(this, &testApp::resetParticlePressed);
gui.setup();
gui.add(pyrScale.setup("pyrScale", .5, 0, 1));
gui.add(levels.setup("levels", 4, 1, 8));
gui.add(winsize.setup("winsize", 8, 4, 64));
gui.add(iterations.setup("iterations", 2, 1, 8));
gui.add(polyN.setup("polyN", 7, 5, 10));
gui.add(polySigma.setup("polySigma", 1.5, 1.1, 2));
gui.add(flowScale.setup("flowScale", 0.05, 0.0, 0.2));
gui.add(drawFlow.setup("draw opticalflow", true));
gui.add(fullscreen.setup("fullscreen", false));
gui.add(resetParticleButton.setup("reset particles"));
オプティカル・フロー + パーティクル
‣ testApp.cpp
//パーティクルを生成
!
!

for (int i = 0; i < NUM; i++){
!
Particle myParticle;
myParticle.friction = 0.01;
myParticle.radius = 2;
! !
myParticle.setup(ofVec2f(ofRandom(ofGetWidth()),
ofRandom(ofGetHeight())), ofVec2f(0, 0));
! !
particles.push_back(myParticle);
! }
}
void testApp::update() {
camera.update();
if(camera.isFrameNew()) {
flow.setPyramidScale(pyrScale);
flow.setNumLevels(levels);
flow.setWindowSize(winsize);
flow.setNumIterations(iterations);
flow.setPolyN(polyN);
flow.setPolySigma(polySigma);
// オプティカルフローを計算
}

flow.calcOpticalFlow(camera);
オプティカル・フロー + パーティクル
‣ testApp.cpp
// Particleのアップデート
!
!

for (int i = 0; i < particles.size(); i++){
!
!
//particleの力をリセット

!
!
!

!
!
!

!

!

!

!

!
!

!
!

!
!
}

!
}

particles[i].resetForce();
//オプティカルフローから、それぞれのparticleにかかる力を算出

ofVec2f force;
ofVec2f pos;
pos.x = particles[i].position.x * float(camera.getWidth()) /
float(ofGetWidth());
pos.y = particles[i].position.y * float(camera.getHeight()) /
float(ofGetHeight());
force = flow.getFlowOffset(pos.x, pos.y) * flowScale;
//Particleの状態を更新
particles[i].addForce(ofVec2f(force.x, force.y));
particles[i].updateForce();
particles[i].bounceOffWalls();
particles[i].update();
オプティカル・フロー + パーティクル
‣ testApp.cpp
void testApp::draw() {
ofSetFullscreen(fullscreen);
ofBackground(0);
ofSetColor(255);
camera.draw(0,0,ofGetWidth(),ofGetHeight());
if (drawFlow) {
ofSetColor(255, 0, 255);
flow.draw(0,0,ofGetWidth(),ofGetHeight());
}

!
!
}

ofSetColor(0, 127, 255);
for (int i = 0; i < particles.size(); i++){
!
particles[i].draw();
}
gui.draw();
オプティカル・フロー + パーティクル
‣ testApp.cpp
void testApp::resetParticlePressed(){
particles.clear();
for (int i = 0; i < NUM; i++){
! !
Particle myParticle;
myParticle.friction = 0.01;
myParticle.radius = 2;
! !
myParticle.setup(ofVec2f(ofRandom(ofGetWidth()),
ofRandom(ofGetHeight())), ofVec2f(0, 0));
! !
particles.push_back(myParticle);
! }
}
オプティカル・フロー + パーティクル
‣ 完成!!

Weitere ähnliche Inhalte

Was ist angesagt?

openFrameworks基礎 動きを生みだす、アニメーション入門 - 芸大グラフィックスプログラミング演習B
openFrameworks基礎 動きを生みだす、アニメーション入門 - 芸大グラフィックスプログラミング演習BopenFrameworks基礎 動きを生みだす、アニメーション入門 - 芸大グラフィックスプログラミング演習B
openFrameworks基礎 動きを生みだす、アニメーション入門 - 芸大グラフィックスプログラミング演習B
Atsushi Tadokoro
 
Media Art II 2013 第7回 : openFrameworks 3Dグラフィクス、OpenGL
Media Art II 2013 第7回 : openFrameworks 3Dグラフィクス、OpenGLMedia Art II 2013 第7回 : openFrameworks 3Dグラフィクス、OpenGL
Media Art II 2013 第7回 : openFrameworks 3Dグラフィクス、OpenGL
Atsushi Tadokoro
 
組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由
kikairoya
 
Unity道場京都スペシャル トゥーンシェーディングとノンフォトリアリスティック風絵づくり入門_
 Unity道場京都スペシャル トゥーンシェーディングとノンフォトリアリスティック風絵づくり入門_ Unity道場京都スペシャル トゥーンシェーディングとノンフォトリアリスティック風絵づくり入門_
Unity道場京都スペシャル トゥーンシェーディングとノンフォトリアリスティック風絵づくり入門_
Unity Technologies Japan K.K.
 
20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン
yohhoy
 
Observable Everywhere - Rxの原則とUniRxにみるデータソースの見つけ方
Observable Everywhere  - Rxの原則とUniRxにみるデータソースの見つけ方Observable Everywhere  - Rxの原則とUniRxにみるデータソースの見つけ方
Observable Everywhere - Rxの原則とUniRxにみるデータソースの見つけ方
Yoshifumi Kawai
 

Was ist angesagt? (20)

openFrameworks基礎 動きを生みだす、アニメーション入門 - 芸大グラフィックスプログラミング演習B
openFrameworks基礎 動きを生みだす、アニメーション入門 - 芸大グラフィックスプログラミング演習BopenFrameworks基礎 動きを生みだす、アニメーション入門 - 芸大グラフィックスプログラミング演習B
openFrameworks基礎 動きを生みだす、アニメーション入門 - 芸大グラフィックスプログラミング演習B
 
Media Art II 2013 第7回 : openFrameworks 3Dグラフィクス、OpenGL
Media Art II 2013 第7回 : openFrameworks 3Dグラフィクス、OpenGLMedia Art II 2013 第7回 : openFrameworks 3Dグラフィクス、OpenGL
Media Art II 2013 第7回 : openFrameworks 3Dグラフィクス、OpenGL
 
C++ マルチスレッドプログラミング
C++ マルチスレッドプログラミングC++ マルチスレッドプログラミング
C++ マルチスレッドプログラミング
 
【Unity道場】物理シミュレーション完全マスター
【Unity道場】物理シミュレーション完全マスター【Unity道場】物理シミュレーション完全マスター
【Unity道場】物理シミュレーション完全マスター
 
Unityとシェーダで描く360度フラクタル
Unityとシェーダで描く360度フラクタルUnityとシェーダで描く360度フラクタル
Unityとシェーダで描く360度フラクタル
 
【Unity道場スペシャル 2017大阪】クォータニオン完全マスター
【Unity道場スペシャル 2017大阪】クォータニオン完全マスター【Unity道場スペシャル 2017大阪】クォータニオン完全マスター
【Unity道場スペシャル 2017大阪】クォータニオン完全マスター
 
【Unity道場】ゲーム制作に使う数学を学習しよう
【Unity道場】ゲーム制作に使う数学を学習しよう【Unity道場】ゲーム制作に使う数学を学習しよう
【Unity道場】ゲーム制作に使う数学を学習しよう
 
組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由
 
HoloLens2とMeta QuestではじめるWebXR
HoloLens2とMeta QuestではじめるWebXRHoloLens2とMeta QuestではじめるWebXR
HoloLens2とMeta QuestではじめるWebXR
 
Unity道場京都スペシャル トゥーンシェーディングとノンフォトリアリスティック風絵づくり入門_
 Unity道場京都スペシャル トゥーンシェーディングとノンフォトリアリスティック風絵づくり入門_ Unity道場京都スペシャル トゥーンシェーディングとノンフォトリアリスティック風絵づくり入門_
Unity道場京都スペシャル トゥーンシェーディングとノンフォトリアリスティック風絵づくり入門_
 
A Brief History of UniRx/UniTask, IUniTaskSource in Depth
A Brief History of UniRx/UniTask, IUniTaskSource in DepthA Brief History of UniRx/UniTask, IUniTaskSource in Depth
A Brief History of UniRx/UniTask, IUniTaskSource in Depth
 
20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン
 
シェーダだけで世界を創る!three.jsによるレイマーチング
シェーダだけで世界を創る!three.jsによるレイマーチングシェーダだけで世界を創る!three.jsによるレイマーチング
シェーダだけで世界を創る!three.jsによるレイマーチング
 
【Unity】 Behavior TreeでAIを作る
 【Unity】 Behavior TreeでAIを作る 【Unity】 Behavior TreeでAIを作る
【Unity】 Behavior TreeでAIを作る
 
Unityでパフォーマンスの良いUIを作る為のTips
Unityでパフォーマンスの良いUIを作る為のTipsUnityでパフォーマンスの良いUIを作る為のTips
Unityでパフォーマンスの良いUIを作る為のTips
 
サムライスピリッツキャラクター制作事例 キャラクターモデル編
 サムライスピリッツキャラクター制作事例 キャラクターモデル編 サムライスピリッツキャラクター制作事例 キャラクターモデル編
サムライスピリッツキャラクター制作事例 キャラクターモデル編
 
Observable Everywhere - Rxの原則とUniRxにみるデータソースの見つけ方
Observable Everywhere  - Rxの原則とUniRxにみるデータソースの見つけ方Observable Everywhere  - Rxの原則とUniRxにみるデータソースの見つけ方
Observable Everywhere - Rxの原則とUniRxにみるデータソースの見つけ方
 
PCD2019 TOKYO ワークショップ「2時間で!Processingでプログラミング入門」
PCD2019 TOKYO ワークショップ「2時間で!Processingでプログラミング入門」PCD2019 TOKYO ワークショップ「2時間で!Processingでプログラミング入門」
PCD2019 TOKYO ワークショップ「2時間で!Processingでプログラミング入門」
 
A quick tour of the Cysharp OSS
A quick tour of the Cysharp OSSA quick tour of the Cysharp OSS
A quick tour of the Cysharp OSS
 
Deep Dive async/await in Unity with UniTask(UniRx.Async)
Deep Dive async/await in Unity with UniTask(UniRx.Async)Deep Dive async/await in Unity with UniTask(UniRx.Async)
Deep Dive async/await in Unity with UniTask(UniRx.Async)
 

Andere mochten auch

メディア・アートII 第3回 openFrameworks基礎 OOoF : オブジェクト指向 oF
メディア・アートII 第3回 openFrameworks基礎 OOoF : オブジェクト指向 oFメディア・アートII 第3回 openFrameworks基礎 OOoF : オブジェクト指向 oF
メディア・アートII 第3回 openFrameworks基礎 OOoF : オブジェクト指向 oF
Atsushi Tadokoro
 
メディア・アート II 第1回: ガイダンス openFrameworks入門
メディア・アート II 第1回: ガイダンス openFrameworks入門メディア・アート II 第1回: ガイダンス openFrameworks入門
メディア・アート II 第1回: ガイダンス openFrameworks入門
Atsushi Tadokoro
 
ノンデザイナーのための配色理論
ノンデザイナーのための配色理論ノンデザイナーのための配色理論
ノンデザイナーのための配色理論
tsukasa obara
 

Andere mochten auch (16)

201205016 deformablemodelfitting
201205016 deformablemodelfitting201205016 deformablemodelfitting
201205016 deformablemodelfitting
 
メディア・アートII 第3回 openFrameworks基礎 OOoF : オブジェクト指向 oF
メディア・アートII 第3回 openFrameworks基礎 OOoF : オブジェクト指向 oFメディア・アートII 第3回 openFrameworks基礎 OOoF : オブジェクト指向 oF
メディア・アートII 第3回 openFrameworks基礎 OOoF : オブジェクト指向 oF
 
メディア・アート II 第1回: ガイダンス openFrameworks入門
メディア・アート II 第1回: ガイダンス openFrameworks入門メディア・アート II 第1回: ガイダンス openFrameworks入門
メディア・アート II 第1回: ガイダンス openFrameworks入門
 
コンテンツをディレクションするということ
コンテンツをディレクションするということコンテンツをディレクションするということ
コンテンツをディレクションするということ
 
青年海外協力隊・フィールド調査団の最終報告書
青年海外協力隊・フィールド調査団の最終報告書青年海外協力隊・フィールド調査団の最終報告書
青年海外協力隊・フィールド調査団の最終報告書
 
インターネット広告代理店の「制作ディレクション」というお仕事
インターネット広告代理店の「制作ディレクション」というお仕事インターネット広告代理店の「制作ディレクション」というお仕事
インターネット広告代理店の「制作ディレクション」というお仕事
 
色で失敗しない為に 〜理論に基づく配色フロー〜
色で失敗しない為に 〜理論に基づく配色フロー〜色で失敗しない為に 〜理論に基づく配色フロー〜
色で失敗しない為に 〜理論に基づく配色フロー〜
 
Wo! vol.23 米Coca-Colaサイトにみるコンテンツ・マーケティング
Wo! vol.23 米Coca-Colaサイトにみるコンテンツ・マーケティングWo! vol.23 米Coca-Colaサイトにみるコンテンツ・マーケティング
Wo! vol.23 米Coca-Colaサイトにみるコンテンツ・マーケティング
 
カヤックコピー部のコピー講座
カヤックコピー部のコピー講座カヤックコピー部のコピー講座
カヤックコピー部のコピー講座
 
分かりやすく、使いやすいデザインを生み出す工夫 先生:池田 拓司
分かりやすく、使いやすいデザインを生み出す工夫 先生:池田 拓司分かりやすく、使いやすいデザインを生み出す工夫 先生:池田 拓司
分かりやすく、使いやすいデザインを生み出す工夫 先生:池田 拓司
 
コンテンツ作りの三原則
コンテンツ作りの三原則コンテンツ作りの三原則
コンテンツ作りの三原則
 
ノンデザイナーのための配色理論
ノンデザイナーのための配色理論ノンデザイナーのための配色理論
ノンデザイナーのための配色理論
 
【プレゼン】見やすいプレゼン資料の作り方【初心者用】
【プレゼン】見やすいプレゼン資料の作り方【初心者用】【プレゼン】見やすいプレゼン資料の作り方【初心者用】
【プレゼン】見やすいプレゼン資料の作り方【初心者用】
 
しょぼいプレゼンをパワポのせいにするな! by @jessedee
しょぼいプレゼンをパワポのせいにするな! by @jessedeeしょぼいプレゼンをパワポのせいにするな! by @jessedee
しょぼいプレゼンをパワポのせいにするな! by @jessedee
 
色彩センスのいらない配色講座
色彩センスのいらない配色講座色彩センスのいらない配色講座
色彩センスのいらない配色講座
 
見やすいプレゼン資料の作り方 - リニューアル増量版
見やすいプレゼン資料の作り方 - リニューアル増量版見やすいプレゼン資料の作り方 - リニューアル増量版
見やすいプレゼン資料の作り方 - リニューアル増量版
 

Ähnlich wie Media Art II 2013 第6回:openFrameworks Addonを使う 2 - ofxOpenCV と ofxCv

2012 kanemotolablecture1
2012 kanemotolablecture12012 kanemotolablecture1
2012 kanemotolablecture1
ytanno
 
2012 kanemotolablecture2
2012 kanemotolablecture22012 kanemotolablecture2
2012 kanemotolablecture2
ytanno
 
OpenCVをAndroidで動かしてみた
OpenCVをAndroidで動かしてみたOpenCVをAndroidで動かしてみた
OpenCVをAndroidで動かしてみた
徹 上野山
 
BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 1
BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 1BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 1
BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 1
Atsushi Tadokoro
 
TypeScript ファーストステップ ~ Any browser. Any host. Any OS. Open Source. ~
TypeScript ファーストステップ ~ Any browser. Any host. Any OS. Open Source. ~TypeScript ファーストステップ ~ Any browser. Any host. Any OS. Open Source. ~
TypeScript ファーストステップ ~ Any browser. Any host. Any OS. Open Source. ~
Akira Inoue
 
日本Androidの会のハンズオンセミナー資料(20130315)
日本Androidの会のハンズオンセミナー資料(20130315)日本Androidの会のハンズオンセミナー資料(20130315)
日本Androidの会のハンズオンセミナー資料(20130315)
eijikushida
 
Netラボ2012年6月勉強会 マイクロソフトのオープンソース戦略を考える
Netラボ2012年6月勉強会 マイクロソフトのオープンソース戦略を考えるNetラボ2012年6月勉強会 マイクロソフトのオープンソース戦略を考える
Netラボ2012年6月勉強会 マイクロソフトのオープンソース戦略を考える
david9142
 

Ähnlich wie Media Art II 2013 第6回:openFrameworks Addonを使う 2 - ofxOpenCV と ofxCv (20)

OpenCVを用いた画像処理入門
OpenCVを用いた画像処理入門OpenCVを用いた画像処理入門
OpenCVを用いた画像処理入門
 
2012 kanemotolablecture1
2012 kanemotolablecture12012 kanemotolablecture1
2012 kanemotolablecture1
 
2012 kanemotolablecture2
2012 kanemotolablecture22012 kanemotolablecture2
2012 kanemotolablecture2
 
OpenCVの入り口
OpenCVの入り口OpenCVの入り口
OpenCVの入り口
 
iOS の動画アプリ開発に Xamarin を使ってみた @JXUG #2 East
iOS の動画アプリ開発に Xamarin を使ってみた @JXUG #2 EastiOS の動画アプリ開発に Xamarin を使ってみた @JXUG #2 East
iOS の動画アプリ開発に Xamarin を使ってみた @JXUG #2 East
 
OpenCVをAndroidで動かしてみた
OpenCVをAndroidで動かしてみたOpenCVをAndroidで動かしてみた
OpenCVをAndroidで動かしてみた
 
Xamarin で ReactiveUI を使ってみた
Xamarin で ReactiveUI を使ってみたXamarin で ReactiveUI を使ってみた
Xamarin で ReactiveUI を使ってみた
 
BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 1
BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 1BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 1
BNN CAMP vol.3  インタラクションデザインの現在―プログラミング初心者のためのopenFrameworks入門 1
 
RoboVM
RoboVMRoboVM
RoboVM
 
cocos2d-xとネイティブ間の連携
cocos2d-xとネイティブ間の連携cocos2d-xとネイティブ間の連携
cocos2d-xとネイティブ間の連携
 
How to Make Own Framework built on OWIN
How to Make Own Framework built on OWINHow to Make Own Framework built on OWIN
How to Make Own Framework built on OWIN
 
Canvas勉強会
Canvas勉強会Canvas勉強会
Canvas勉強会
 
TypeScript ファーストステップ ~ Any browser. Any host. Any OS. Open Source. ~
TypeScript ファーストステップ ~ Any browser. Any host. Any OS. Open Source. ~TypeScript ファーストステップ ~ Any browser. Any host. Any OS. Open Source. ~
TypeScript ファーストステップ ~ Any browser. Any host. Any OS. Open Source. ~
 
WASM(WebAssembly)入門 ペアリング演算やってみた
WASM(WebAssembly)入門 ペアリング演算やってみたWASM(WebAssembly)入門 ペアリング演算やってみた
WASM(WebAssembly)入門 ペアリング演算やってみた
 
C#のコード解析ってなんだ@20160825 CenterCLR.学生 #1
C#のコード解析ってなんだ@20160825 CenterCLR.学生 #1C#のコード解析ってなんだ@20160825 CenterCLR.学生 #1
C#のコード解析ってなんだ@20160825 CenterCLR.学生 #1
 
日本Androidの会のハンズオンセミナー資料(20130315)
日本Androidの会のハンズオンセミナー資料(20130315)日本Androidの会のハンズオンセミナー資料(20130315)
日本Androidの会のハンズオンセミナー資料(20130315)
 
20130315 abc firefox_os
20130315 abc firefox_os20130315 abc firefox_os
20130315 abc firefox_os
 
Jenkins 2.0 (日本語)
Jenkins 2.0 (日本語)Jenkins 2.0 (日本語)
Jenkins 2.0 (日本語)
 
Cocos2d xをさらにさわってみよう!
Cocos2d xをさらにさわってみよう!Cocos2d xをさらにさわってみよう!
Cocos2d xをさらにさわってみよう!
 
Netラボ2012年6月勉強会 マイクロソフトのオープンソース戦略を考える
Netラボ2012年6月勉強会 マイクロソフトのオープンソース戦略を考えるNetラボ2012年6月勉強会 マイクロソフトのオープンソース戦略を考える
Netラボ2012年6月勉強会 マイクロソフトのオープンソース戦略を考える
 

Mehr von Atsushi Tadokoro

「クリエイティブ・ミュージック・コーディング」- オーディオ・ビジュアル作品のための、オープンソースなソフトウエア・フレームワークの現状と展望
「クリエイティブ・ミュージック・コーディング」- オーディオ・ビジュアル作品のための、オープンソースなソフトウエア・フレームワークの現状と展望「クリエイティブ・ミュージック・コーディング」- オーディオ・ビジュアル作品のための、オープンソースなソフトウエア・フレームワークの現状と展望
「クリエイティブ・ミュージック・コーディング」- オーディオ・ビジュアル作品のための、オープンソースなソフトウエア・フレームワークの現状と展望
Atsushi Tadokoro
 
プログラム初級講座 - メディア芸術をはじめよう
プログラム初級講座 - メディア芸術をはじめようプログラム初級講座 - メディア芸術をはじめよう
プログラム初級講座 - メディア芸術をはじめよう
Atsushi Tadokoro
 
Interactive Music II ProcessingとSuperColliderの連携 -2
Interactive Music II ProcessingとSuperColliderの連携 -2Interactive Music II ProcessingとSuperColliderの連携 -2
Interactive Music II ProcessingとSuperColliderの連携 -2
Atsushi Tadokoro
 
coma Creators session vol.2
coma Creators session vol.2coma Creators session vol.2
coma Creators session vol.2
Atsushi Tadokoro
 
Interactive Music II ProcessingとSuperColliderの連携1
Interactive Music II ProcessingとSuperColliderの連携1Interactive Music II ProcessingとSuperColliderの連携1
Interactive Music II ProcessingとSuperColliderの連携1
Atsushi Tadokoro
 
Interactive Music II Processingによるアニメーション
Interactive Music II ProcessingによるアニメーションInteractive Music II Processingによるアニメーション
Interactive Music II Processingによるアニメーション
Atsushi Tadokoro
 
Interactive Music II Processing基本
Interactive Music II Processing基本Interactive Music II Processing基本
Interactive Music II Processing基本
Atsushi Tadokoro
 
Interactive Music II SuperCollider応用 2 - SuperColliderとPure Dataの連携
Interactive Music II SuperCollider応用 2 - SuperColliderとPure Dataの連携Interactive Music II SuperCollider応用 2 - SuperColliderとPure Dataの連携
Interactive Music II SuperCollider応用 2 - SuperColliderとPure Dataの連携
Atsushi Tadokoro
 
Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス
Media Art II openFrameworks  アプリ間の通信とタンジブルなインターフェイス Media Art II openFrameworks  アプリ間の通信とタンジブルなインターフェイス
Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス
Atsushi Tadokoro
 
Interactive Music II SuperCollider応用 - SuperColliderと OSC (Open Sound Control)
Interactive Music II SuperCollider応用 - SuperColliderと OSC (Open Sound Control)Interactive Music II SuperCollider応用 - SuperColliderと OSC (Open Sound Control)
Interactive Music II SuperCollider応用 - SuperColliderと OSC (Open Sound Control)
Atsushi Tadokoro
 
iTamabi 13 ARTSAT API 実践 5 - 衛星の軌道を描く
iTamabi 13 ARTSAT API 実践 5 - 衛星の軌道を描くiTamabi 13 ARTSAT API 実践 5 - 衛星の軌道を描く
iTamabi 13 ARTSAT API 実践 5 - 衛星の軌道を描く
Atsushi Tadokoro
 
メディア芸術基礎 II 第11回:HTML5実践 表現のための様々なJavaScriptライブラリ
メディア芸術基礎 II 第11回:HTML5実践 表現のための様々なJavaScriptライブラリメディア芸術基礎 II 第11回:HTML5実践 表現のための様々なJavaScriptライブラリ
メディア芸術基礎 II 第11回:HTML5実践 表現のための様々なJavaScriptライブラリ
Atsushi Tadokoro
 
芸術情報演習デザイン(Web) 第8回: CSSフレームワークを使う
芸術情報演習デザイン(Web)  第8回: CSSフレームワークを使う芸術情報演習デザイン(Web)  第8回: CSSフレームワークを使う
芸術情報演習デザイン(Web) 第8回: CSSフレームワークを使う
Atsushi Tadokoro
 
Interactive Music II SuperCollider応用 JITLib - ライブコーディング 2
Interactive Music II SuperCollider応用 JITLib - ライブコーディング 2Interactive Music II SuperCollider応用 JITLib - ライブコーディング 2
Interactive Music II SuperCollider応用 JITLib - ライブコーディング 2
Atsushi Tadokoro
 
iTamabi 13 第9回:ARTSAT API 実践 3 ジオコーディングで衛星の位置を取得
iTamabi 13 第9回:ARTSAT API 実践 3 ジオコーディングで衛星の位置を取得iTamabi 13 第9回:ARTSAT API 実践 3 ジオコーディングで衛星の位置を取得
iTamabi 13 第9回:ARTSAT API 実践 3 ジオコーディングで衛星の位置を取得
Atsushi Tadokoro
 
Webデザイン 第10回:HTML5実践 Three.jsで3Dプログラミング
Webデザイン 第10回:HTML5実践 Three.jsで3DプログラミングWebデザイン 第10回:HTML5実践 Three.jsで3Dプログラミング
Webデザイン 第10回:HTML5実践 Three.jsで3Dプログラミング
Atsushi Tadokoro
 
Interactive Music II SuperCollider応用 JITLib - ライブコーディング 1
Interactive Music II SuperCollider応用 JITLib - ライブコーディング 1Interactive Music II SuperCollider応用 JITLib - ライブコーディング 1
Interactive Music II SuperCollider応用 JITLib - ライブコーディング 1
Atsushi Tadokoro
 
iTamabi 13 第8回:ARTSAT API 実践 2 衛星アプリを企画する
iTamabi 13 第8回:ARTSAT API 実践 2 衛星アプリを企画するiTamabi 13 第8回:ARTSAT API 実践 2 衛星アプリを企画する
iTamabi 13 第8回:ARTSAT API 実践 2 衛星アプリを企画する
Atsushi Tadokoro
 
Interactive Music II SuperCollider実習 オリジナルの楽器を作ろう!
Interactive Music II SuperCollider実習  オリジナルの楽器を作ろう!Interactive Music II SuperCollider実習  オリジナルの楽器を作ろう!
Interactive Music II SuperCollider実習 オリジナルの楽器を作ろう!
Atsushi Tadokoro
 

Mehr von Atsushi Tadokoro (20)

「クリエイティブ・ミュージック・コーディング」- オーディオ・ビジュアル作品のための、オープンソースなソフトウエア・フレームワークの現状と展望
「クリエイティブ・ミュージック・コーディング」- オーディオ・ビジュアル作品のための、オープンソースなソフトウエア・フレームワークの現状と展望「クリエイティブ・ミュージック・コーディング」- オーディオ・ビジュアル作品のための、オープンソースなソフトウエア・フレームワークの現状と展望
「クリエイティブ・ミュージック・コーディング」- オーディオ・ビジュアル作品のための、オープンソースなソフトウエア・フレームワークの現状と展望
 
プログラム初級講座 - メディア芸術をはじめよう
プログラム初級講座 - メディア芸術をはじめようプログラム初級講座 - メディア芸術をはじめよう
プログラム初級講座 - メディア芸術をはじめよう
 
Interactive Music II ProcessingとSuperColliderの連携 -2
Interactive Music II ProcessingとSuperColliderの連携 -2Interactive Music II ProcessingとSuperColliderの連携 -2
Interactive Music II ProcessingとSuperColliderの連携 -2
 
coma Creators session vol.2
coma Creators session vol.2coma Creators session vol.2
coma Creators session vol.2
 
Interactive Music II ProcessingとSuperColliderの連携1
Interactive Music II ProcessingとSuperColliderの連携1Interactive Music II ProcessingとSuperColliderの連携1
Interactive Music II ProcessingとSuperColliderの連携1
 
Interactive Music II Processingによるアニメーション
Interactive Music II ProcessingによるアニメーションInteractive Music II Processingによるアニメーション
Interactive Music II Processingによるアニメーション
 
Interactive Music II Processing基本
Interactive Music II Processing基本Interactive Music II Processing基本
Interactive Music II Processing基本
 
Interactive Music II SuperCollider応用 2 - SuperColliderとPure Dataの連携
Interactive Music II SuperCollider応用 2 - SuperColliderとPure Dataの連携Interactive Music II SuperCollider応用 2 - SuperColliderとPure Dataの連携
Interactive Music II SuperCollider応用 2 - SuperColliderとPure Dataの連携
 
Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス
Media Art II openFrameworks  アプリ間の通信とタンジブルなインターフェイス Media Art II openFrameworks  アプリ間の通信とタンジブルなインターフェイス
Media Art II openFrameworks アプリ間の通信とタンジブルなインターフェイス
 
Interactive Music II SuperCollider応用 - SuperColliderと OSC (Open Sound Control)
Interactive Music II SuperCollider応用 - SuperColliderと OSC (Open Sound Control)Interactive Music II SuperCollider応用 - SuperColliderと OSC (Open Sound Control)
Interactive Music II SuperCollider応用 - SuperColliderと OSC (Open Sound Control)
 
iTamabi 13 ARTSAT API 実践 5 - 衛星の軌道を描く
iTamabi 13 ARTSAT API 実践 5 - 衛星の軌道を描くiTamabi 13 ARTSAT API 実践 5 - 衛星の軌道を描く
iTamabi 13 ARTSAT API 実践 5 - 衛星の軌道を描く
 
メディア芸術基礎 II 第11回:HTML5実践 表現のための様々なJavaScriptライブラリ
メディア芸術基礎 II 第11回:HTML5実践 表現のための様々なJavaScriptライブラリメディア芸術基礎 II 第11回:HTML5実践 表現のための様々なJavaScriptライブラリ
メディア芸術基礎 II 第11回:HTML5実践 表現のための様々なJavaScriptライブラリ
 
芸術情報演習デザイン(Web) 第8回: CSSフレームワークを使う
芸術情報演習デザイン(Web)  第8回: CSSフレームワークを使う芸術情報演習デザイン(Web)  第8回: CSSフレームワークを使う
芸術情報演習デザイン(Web) 第8回: CSSフレームワークを使う
 
Interactive Music II SuperCollider応用 JITLib - ライブコーディング 2
Interactive Music II SuperCollider応用 JITLib - ライブコーディング 2Interactive Music II SuperCollider応用 JITLib - ライブコーディング 2
Interactive Music II SuperCollider応用 JITLib - ライブコーディング 2
 
iTamabi 13 第9回:ARTSAT API 実践 3 ジオコーディングで衛星の位置を取得
iTamabi 13 第9回:ARTSAT API 実践 3 ジオコーディングで衛星の位置を取得iTamabi 13 第9回:ARTSAT API 実践 3 ジオコーディングで衛星の位置を取得
iTamabi 13 第9回:ARTSAT API 実践 3 ジオコーディングで衛星の位置を取得
 
Tamabi media131118
Tamabi media131118Tamabi media131118
Tamabi media131118
 
Webデザイン 第10回:HTML5実践 Three.jsで3Dプログラミング
Webデザイン 第10回:HTML5実践 Three.jsで3DプログラミングWebデザイン 第10回:HTML5実践 Three.jsで3Dプログラミング
Webデザイン 第10回:HTML5実践 Three.jsで3Dプログラミング
 
Interactive Music II SuperCollider応用 JITLib - ライブコーディング 1
Interactive Music II SuperCollider応用 JITLib - ライブコーディング 1Interactive Music II SuperCollider応用 JITLib - ライブコーディング 1
Interactive Music II SuperCollider応用 JITLib - ライブコーディング 1
 
iTamabi 13 第8回:ARTSAT API 実践 2 衛星アプリを企画する
iTamabi 13 第8回:ARTSAT API 実践 2 衛星アプリを企画するiTamabi 13 第8回:ARTSAT API 実践 2 衛星アプリを企画する
iTamabi 13 第8回:ARTSAT API 実践 2 衛星アプリを企画する
 
Interactive Music II SuperCollider実習 オリジナルの楽器を作ろう!
Interactive Music II SuperCollider実習  オリジナルの楽器を作ろう!Interactive Music II SuperCollider実習  オリジナルの楽器を作ろう!
Interactive Music II SuperCollider実習 オリジナルの楽器を作ろう!
 

Media Art II 2013 第6回:openFrameworks Addonを使う 2 - ofxOpenCV と ofxCv

  • 1. Media Art II 2013 第6回:openFrameworks Addonを使う 2 - ofxOpenCV と ofxCv 2013年10月21日 多摩美術大学 情報デザイン学科 メディア芸術コース 田所 淳
  • 3. OpenCVとは - ofxOpenCVについて ‣ アドオンの使用サンプルその2 ‣ ofxOpenCv
  • 4. OpenCVとは - ofxOpenCVについて ‣ ofxOpenCv ‣ OpenCVをアドオンとして使用できるようにしたもの ‣ OpenCVとは? ‣ OpenCV = Open Computer Vision Library ‣ 米 Intel 社で開発された画像処理・画像認識用のC言語ライ ブラリ ‣ オープンソース、商用・非商用を問わず無料 ‣ 静止画にも動画にも対応
  • 5. OpenCVとは - ofxOpenCVについて ‣ openFrameworksとOpenCVを組みあわせた作品は、数多く存 在する ‣ カメラの映像によるインタラクションは、市販の機材で構築可 能で、かつメンテナンスも容易 ‣ 個人制作する作品にも転用可能
  • 6. OpenCVを活用した作品例 ‣ YesYesNo Night Lights ‣ http://yesyesno.com/night-lights
  • 7. OpenCVを活用した作品例 ‣ Graffiti Research Lab. L.A.S.E.R. Tag ‣ http://graffitiresearchlab.com/projects/laser-tag/
  • 8. OpenCVを活用した作品例 ‣ The Eye Writer ‣ http://www.eyewriter.org/
  • 9. OpenCVを活用した作品例 ‣ Chris O'shea Hand from Above ‣ http://www.chrisoshea.org/hand-from-above
  • 10. OpenCVを活用した作品例 ‣ Chris O'shea Audience ‣ http://www.chrisoshea.org/audience
  • 11. OpenCVを活用した作品例 ‣ Golan Levin Double-Taker (Snout) ‣ http://www.flong.com/projects/snout/
  • 12. OpenCVを活用した作品例 ‣ boards magazine interactive cover: Rise and Fall ‣ http://www.boardsmag.com/community/blogs/behindthescenes/ index.php?p=834
  • 13. OpenCV で物体を認識する ‣ これらの作品に共通する技術 ‣ カメラで撮影された映像から、動いている物体を検出し、その 位置や輪郭を抽出する ‣ 「ロボットの眼」をプログラミングしている ‣ OpenCVを活用すると、この物体の認識が簡単に可能となる
  • 15. OpenCV で物体を認識する ‣ apps > addonsExamples > opencvExample に物体の輪郭を抽 出するまでの、わかりやすいサンプルが掲載 ‣ まずは、この基本プログラムを読み解いていきたい
  • 16. ofxOpenCv 基本 ‣ testApp.h #pragma once #include "ofMain.h" #include "ofxOpenCv.h" //#define _USE_LIVE_VIDEO カメラ入力を使用する場合は ここをコメントアウト class testApp : public ofBaseApp{ public: ! void setup(); ! void update(); ! void draw(); ! void keyPressed(int key); ! ! #ifdef _USE_LIVE_VIDEO ! ofVideoGrabber vidGrabber; カメラ入力 ! #else ! ofVideoPlayer vidPlayer; 動画ファイルを再生 ! #endif ! 入力された元映像 ! ofxCvColorImage colorImg; ! ofxCvGrayscaleImage grayImage; グレースケールに変換後 ! ofxCvGrayscaleImage grayBg; キャプチャーされた背景画像 ! ofxCvGrayscaleImage grayDiff; 背景とグレースケール画像の差分 ! ofxCvContourFinder contourFinder; 輪郭を抽出するためのオブジェクト ! ! int threshold; 画像を2値化する際の閾値(しきいち) ! bool bLearnBakground; 背景を記録した際に通知 };
  • 17. ofxOpenCv 基本 ‣ testApp.cpp setup() void testApp::setup(){ ! ofSetFrameRate(60); ! ! #ifdef _USE_LIVE_VIDEO カメラ入力の場合は ! vidGrabber.setVerbose(true); カメラを初期化 ! vidGrabber.initGrabber(320,240); ! #else 動画再生の場合は ! vidPlayer.loadMovie("fingers.mov"); ! vidPlayer.play(); 動画ファイルを読込 ! #endif ! ! colorImg.allocate(320,240); 必要となる画像のための ! grayImage.allocate(320,240); ! grayBg.allocate(320,240); メモリ領域を確保 ! grayDiff.allocate(320,240); ! 背景画像を記録した状態に ! bLearnBakground = true; ! threshold = 80; 2値化の閾値を設定 }
  • 18. ofxOpenCv 基本 ‣ testApp.cpp update(), 1 of 2 void testApp::update(){ ! ofBackground(100,100,100); ! 新規フレームのとりこみをリセット bool bNewFrame = false; ! ! #ifdef _USE_LIVE_VIDEO ! vidGrabber.grabFrame(); カメラ入力の場合は ! bNewFrame = vidGrabber.isFrameNew(); カメラ映像を1コマ取得 ! #else ! vidPlayer.idleMovie(); 動画再生の場合は ! bNewFrame = vidPlayer.isFrameNew(); 動画ファイルから1コマ ! #endif
  • 19. ofxOpenCv 基本 ‣ testApp.cpp update(), 2 of 2 ! ! ! ! ! ! ! ! if (bNewFrame){ ! ! #ifdef _USE_LIVE_VIDEO 取得した映像をキャプチャーしcolorImgに ! colorImg.setFromPixels(vidGrabber.getPixels(), 320,240); ! #else ! colorImg.setFromPixels(vidPlayer.getPixels(), 320,240); ! #endif ! グレースケールに変換 grayImage = colorImg; ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! } } if (bLearnBakground == true){ ! grayBg = grayImage; ! bLearnBakground = false; } grayDiff.absDiff(grayBg, grayImage); grayDiff.threshold(threshold); もし背景取得モードだったら 現在のグレースケール画像を 背景画像として採用 背景画像とグレー画像の 差分を計算後、 設定した閾値で2値化 contourFinder.findContours(grayDiff, 20, (340*240)/3, 10, true); 2値化した差分画像の 輪郭線を抽出
  • 20. ofxOpenCv 基本 ‣ testApp.cpp draw() void testApp::draw(){ ! ! ofSetHexColor(0xffffff); ! colorImg.draw(20,20); ! grayImage.draw(360,20); ! grayBg.draw(20,280); ! grayDiff.draw(360,280); ! ! ofFill(); ! ofSetHexColor(0x333333); ! ofRect(360,540,320,240); ! ! ofSetHexColor(0xffffff); ! contourFinder.draw(360,540); } カラー画像を描画 グレースケール画像を描画 キャプチャーした背景を描画 2値化した差分画像を描画 抽出した輪郭を表示する 背景を描画 抽出した輪郭線を描画
  • 23. OpenCVもう一つの実装 - ofxCv ‣ openFrameworksには、ofxOpenCvの他に、OpenCVを使用す るためのアドオンがもう一つ存在する ‣ → ofxCv ‣ ‣ ‣ ‣ ofxCv https://github.com/kylemcdonald/ofxCv Kyle McDonald氏によるアドオン openFrameworksでOpenCVをより簡単に、よりパワフルに利 用できる環境を目指している ‣ OpenCVとoFのより緊密な連携
  • 24. OpenCVもう一つの実装 - ofxCv ‣ ofxCvのインストール ‣ GitHubからZip形式でダウンロード ‣ addonsフォルダに格納 ココ →
  • 27. 輪郭抽出をofxCvで実装 ‣ testApp.h #pragma once #include "ofMain.h" #include "ofxCv.h" class testApp : public ofBaseApp { public: ! void setup(); ! void update(); ! void draw(); ! ! ofVideoGrabber cam; ! ofxCv::ContourFinder contourFinder; };
  • 28. 輪郭抽出をofxCvで実装 ‣ testApp.cpp #include "testApp.h" using namespace ofxCv; using namespace cv; void testApp::setup() { cam.initGrabber(ofGetWidth(), ofGetHeight()); contourFinder.setMinAreaRadius(10); contourFinder.setMaxAreaRadius(200); } void testApp::update() { cam.update(); if(cam.isFrameNew()) { contourFinder.setThreshold(ofMap(mouseX, 0, ofGetWidth(), 0, 255)); contourFinder.findContours(cam); } } void testApp::draw() { ofSetColor(255); cam.draw(0, 0); contourFinder.draw(); }
  • 30. ofxCv + ofxGui ‣ プログラムをもっと実用的(作品に利用可能)なものに ‣ 先週とりあげた、ofxGuiと組合せてみる ‣ 単純にカメラの画像の輪郭抽出ではなく、背景画像を登録し て、その差分イメージの輪郭を抽出 ‣ 背景のリセットもGUIからできるように
  • 31. ofxCv + ofxGui ‣ まずは、ofxOpenCV、ofxCv、ofxGuiを選択してプロジェクト を生成
  • 32. ofxCv + ofxGui ‣ testApp.h #pragma once #include "ofMain.h" #include "ofxCv.h" #include "ofxGui.h" class testApp : public ofBaseApp { public: void setup(); void update(); void draw(); void resetBackgroundPressed(); ofVideoGrabber cam; ofxCv::ContourFinder contourFinder; ofxCv::RunningBackground background; ofImage thresholded; ofxPanel gui; ofxFloatSlider bgThresh; // 背景差分の閾値 ofxFloatSlider contourThresh; // 輪郭抽出の閾値 ofxButton resetBackgroundButton; // 背景リセットボタン };
  • 33. ofxCv + ofxGui ‣ testApp.cpp #include "testApp.h" using namespace ofxCv; using namespace cv; void testApp::setup() { // CV初期設定 ! cam.initGrabber(ofGetWidth(), ofGetHeight()); contourFinder.setMinAreaRadius(10); contourFinder.setMaxAreaRadius(200); background.setLearningTime(900); background.setThresholdValue(20); // GUI resetBackgroundButton.addListener(this, &testApp::resetBackgroundPressed); gui.setup(); gui.add(bgThresh.setup("background thresh", 50, 0, 100)); gui.add(contourThresh.setup("contour finder thresh", 127, 0, 255)); gui.add(resetBackgroundButton.setup("reset background")); }
  • 34. ofxCv + ofxGui ‣ testApp.cpp void testApp::update() { cam.update(); if(cam.isFrameNew()) { // 背景差分画像を生成 ! ! background.setThresholdValue(bgThresh); background.update(cam, thresholded); thresholded.update(); // 背景差分画像の輪郭抽出 } } contourFinder.setThreshold(contourThresh); contourFinder.findContours(thresholded); void testApp::draw() { // 差分画像を描画 ofSetColor(255); thresholded.draw(0, 0); // 輪郭抽出結果を描画 } ofSetColor(255, 0, 0); contourFinder.draw(); // GUI gui.draw();
  • 35. ofxCv + ofxGui ‣ testApp.cpp void testApp::resetBackgroundPressed(){ background.reset(); }
  • 36. ofxCv + ofxGui ‣ 完成!!
  • 38. オプティカル・フロー (Optical Flow) ‣ オプティカル・フロー ‣ 映像内での物体の動きを、ベクトル場で表したもの ‣ 参考: http://opencv.jp/sample/optical_flow.html
  • 39. オプティカル・フロー (Optical Flow) ‣ ofxCvでは、オプティカル・フローのための2種類のクラスが 用意されている ‣ ofxCv::FlowFarneback ‣ Gunnar Farneback のアルゴリズムを用いた、密なオプティカ ルフロー ‣ ofxCv::FlowPyrLK ‣ 疎な特徴集合に対するオプティカルフロー ‣ 参考: http://opencv.jp/opencv-2svn/cpp/ motion_analysis_and_object_tracking.html
  • 40. オプティカル・フロー (Optical Flow) ‣ testApp.h #pragma once #include "ofMain.h" #include "ofxCv.h" #include "ofxGui.h" class testApp : public ofBaseApp { public: void setup(); void update(); void draw(); ofVideoGrabber camera; ofxCv::FlowFarneback farneback; ofxCv::FlowPyrLK pyrLk; ofxCv::Flow* curFlow; ofxPanel gui; ofxFloatSlider pyrScale; ofxIntSlider levels; ofxIntSlider winsize; ofxIntSlider iterations; ofxIntSlider polyN; ofxFloatSlider polySigma; ofxIntSlider winSize; ofxIntSlider maxLevel;
  • 41. オプティカル・フロー (Optical Flow) ‣ testApp.h ofxFloatSlider maxFeatures; ofxFloatSlider qualityLevel; ofxFloatSlider minDistance; ofxToggle OPTFLOW_FARNEBACK_GAUSSIAN; ofxToggle useFarneback; };
  • 42. オプティカル・フロー (Optical Flow) ‣ testApp.cpp #include "testApp.h" using namespace ofxCv; using namespace cv; void testApp::setup() { // CV初期設定 camera.initGrabber(320, 240); // GUI gui.setup(); gui.add(pyrScale.setup("pyrScale", .5, 0, 1)); gui.add(levels.setup("levels", 4, 1, 8)); gui.add(winsize.setup("levels", 8, 4, 64)); gui.add(iterations.setup("iterations", 2, 1, 8)); gui.add(polyN.setup("polyN", 7, 5, 10)); gui.add(polySigma.setup("polySigma", 1.5, 1.1, 2)); gui.add(OPTFLOW_FARNEBACK_GAUSSIAN.setup("OPTFLOW_FARNEBACK_GAUSSIAN", false)); gui.add(useFarneback.setup("useFarneback", true)); gui.add(winSize.setup("winSize", 32, 4, 64)); gui.add(maxLevel.setup("maxLevel", 3, 0, 8)); gui.add(levels.setup("maxFeatures", 200, 1, 1000)); gui.add(qualityLevel.setup("levels", 0.01, 0.001, .02));
  • 43. オプティカル・フロー (Optical Flow) ‣ testApp.cpp gui.add(minDistance.setup("minDistance", 4, 1, 16)); } curFlow = &farneback; void testApp::update() { camera.update(); if(camera.isFrameNew()) { if(useFarneback) { // Farnebackの密なオプティカルフロー curFlow = &farneback; farneback.setPyramidScale(pyrScale); farneback.setNumLevels(levels); farneback.setWindowSize(winsize); farneback.setNumIterations(iterations); farneback.setPolyN(polyN); farneback.setPolySigma(polySigma); farneback.setUseGaussian(OPTFLOW_FARNEBACK_GAUSSIAN); } else { // 画像ピラミッドを利用した、疎なオプティカルフロー } curFlow = &pyrLk; pyrLk.setMaxFeatures(maxFeatures); pyrLk.setQualityLevel(qualityLevel); pyrLk.setMinDistance(minDistance); pyrLk.setWindowSize(winSize); pyrLk.setMaxLevel(maxLevel);
  • 44. オプティカル・フロー (Optical Flow) ‣ testApp.cpp // オプティカルフローを計算 } } curFlow->calcOpticalFlow(camera); void testApp::draw() { ofBackground(0); ofSetColor(255); camera.draw(0,0,ofGetWidth(),ofGetHeight()); curFlow->draw(0,0,ofGetWidth(),ofGetHeight()); } gui.draw();
  • 47. オプティカル・フロー + パーティクル ‣ オプティカル・フローで生成したベクトル場に、パーティクル を置いてみる ‣ 映像を解析して、舞い散るパーティクルが実現できるはず!! ‣ Particleクラスは、以前作成したものをそのまま再利用
  • 48. オプティカル・フロー + パーティクル ‣ testApp.h #pragma once #include #include #include #include "ofMain.h" "ofxCv.h" "ofxGui.h" "Particle.h" class testApp : public ofBaseApp { public: void setup(); void update(); void draw(); // Optical Flow ofVideoGrabber camera; ofxCv::FlowFarneback flow; // GUI ofxPanel gui; ofxFloatSlider pyrScale; ofxIntSlider levels; ofxIntSlider winsize; ofxIntSlider iterations; ofxIntSlider polyN; ofxFloatSlider polySigma; ofxFloatSlider flowScale;
  • 49. オプティカル・フロー + パーティクル ‣ testApp.h ofxToggle drawFlow; ofxToggle fullscreen; ofxButton resetParticleButton; void resetParticlePressed(); }; // Particle vector<Particle> particles; static const int NUM = 20000;
  • 50. オプティカル・フロー + パーティクル ‣ testApp.cpp #include "testApp.h" using namespace ofxCv; using namespace cv; void testApp::setup() { // CV初期設定 camera.initGrabber(320, 240); ofSetFrameRate(60); ofEnableBlendMode(OF_BLENDMODE_ADD); // GUI resetParticleButton.addListener(this, &testApp::resetParticlePressed); gui.setup(); gui.add(pyrScale.setup("pyrScale", .5, 0, 1)); gui.add(levels.setup("levels", 4, 1, 8)); gui.add(winsize.setup("winsize", 8, 4, 64)); gui.add(iterations.setup("iterations", 2, 1, 8)); gui.add(polyN.setup("polyN", 7, 5, 10)); gui.add(polySigma.setup("polySigma", 1.5, 1.1, 2)); gui.add(flowScale.setup("flowScale", 0.05, 0.0, 0.2)); gui.add(drawFlow.setup("draw opticalflow", true)); gui.add(fullscreen.setup("fullscreen", false)); gui.add(resetParticleButton.setup("reset particles"));
  • 51. オプティカル・フロー + パーティクル ‣ testApp.cpp //パーティクルを生成 ! ! for (int i = 0; i < NUM; i++){ ! Particle myParticle; myParticle.friction = 0.01; myParticle.radius = 2; ! ! myParticle.setup(ofVec2f(ofRandom(ofGetWidth()), ofRandom(ofGetHeight())), ofVec2f(0, 0)); ! ! particles.push_back(myParticle); ! } } void testApp::update() { camera.update(); if(camera.isFrameNew()) { flow.setPyramidScale(pyrScale); flow.setNumLevels(levels); flow.setWindowSize(winsize); flow.setNumIterations(iterations); flow.setPolyN(polyN); flow.setPolySigma(polySigma); // オプティカルフローを計算 } flow.calcOpticalFlow(camera);
  • 52. オプティカル・フロー + パーティクル ‣ testApp.cpp // Particleのアップデート ! ! for (int i = 0; i < particles.size(); i++){ ! ! //particleの力をリセット ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! } ! } particles[i].resetForce(); //オプティカルフローから、それぞれのparticleにかかる力を算出 ofVec2f force; ofVec2f pos; pos.x = particles[i].position.x * float(camera.getWidth()) / float(ofGetWidth()); pos.y = particles[i].position.y * float(camera.getHeight()) / float(ofGetHeight()); force = flow.getFlowOffset(pos.x, pos.y) * flowScale; //Particleの状態を更新 particles[i].addForce(ofVec2f(force.x, force.y)); particles[i].updateForce(); particles[i].bounceOffWalls(); particles[i].update();
  • 53. オプティカル・フロー + パーティクル ‣ testApp.cpp void testApp::draw() { ofSetFullscreen(fullscreen); ofBackground(0); ofSetColor(255); camera.draw(0,0,ofGetWidth(),ofGetHeight()); if (drawFlow) { ofSetColor(255, 0, 255); flow.draw(0,0,ofGetWidth(),ofGetHeight()); } ! ! } ofSetColor(0, 127, 255); for (int i = 0; i < particles.size(); i++){ ! particles[i].draw(); } gui.draw();
  • 54. オプティカル・フロー + パーティクル ‣ testApp.cpp void testApp::resetParticlePressed(){ particles.clear(); for (int i = 0; i < NUM; i++){ ! ! Particle myParticle; myParticle.friction = 0.01; myParticle.radius = 2; ! ! myParticle.setup(ofVec2f(ofRandom(ofGetWidth()), ofRandom(ofGetHeight())), ofVec2f(0, 0)); ! ! particles.push_back(myParticle); ! } }