読者です 読者をやめる 読者になる 読者になる

aa develop

開発と成長

オプティカルフローでパーティクルを操作する

openFrameworksのofxCvアドオンを使って,オプティカルフローを計算する.オプティカルフローのベクトル値に基づき,パーティクルを動かす.

f:id:aa_debdeb:20160714105631p:plain

オプティカルフローを使うとインタラクティブな何か面白いものを作れそうな気がするが,アイデアが浮かばない.もう少し画像処理について勉強したら何か思いつくかも.

ofApp.h

#pragma once

#include "ofMain.h"
#include "ofxCv.h"
#include "ofxGui.h"
#include "particle.h"

class ofApp : public ofBaseApp{

public:
    void setup();
    void update();
    void draw();

    void keyPressed(int key);
    void keyReleased(int key);
    void mouseMoved(int x, int y );
    void mouseDragged(int x, int y, int button);
    void mousePressed(int x, int y, int button);
    void mouseReleased(int x, int y, int button);
    void mouseEntered(int x, int y);
    void mouseExited(int x, int y);
    void windowResized(int w, int h);
    void dragEvent(ofDragInfo dragInfo);
    void gotMessage(ofMessage msg);
    

    ofVideoGrabber camera;
    ofxCv::FlowFarneback fbFlow;
    
    ofxPanel gui;
    ofParameter fbPyrScale, fbPolySigma;
    ofParameter fbLevels, fbIterations, fbPolyN, fbWinSize;
    ofParameter fbUseGaussian;
    
    vector particles;
    
    void drawFlow1();
    void drawFlow2();
    
};
ofApp.cpp

#include "ofApp.h"

using namespace ofxCv;
using namespace cv;

//--------------------------------------------------------------
void ofApp::setup(){
    ofSetFrameRate(60);
    
    camera.setup(320, 240);
    
    gui.setup();
    gui.add(fbPyrScale.set("fbPyrScale", .5, 0, .99));
    gui.add(fbLevels.set("fbLevels", 4, 1, 8));
    gui.add(fbIterations.set("fbIterations", 2, 1, 8));
    gui.add(fbPolyN.set("fbPolyN", 7, 5, 10));
    gui.add(fbPolySigma.set("fbPolySigma", 1.5, 1.1, 2));
    gui.add(fbUseGaussian.set("fbUseGaussian", false));
    gui.add(fbWinSize.set("winSize", 32, 4, 64));
    
    particles = vector();
    for(int i = 0; i < 1000; i++){
        particles.push_back(Particle());
    }
}

//--------------------------------------------------------------
void ofApp::update(){
    camera.update();
    fbFlow.setPyramidScale(fbPyrScale);
    fbFlow.setNumLevels(fbLevels);
    fbFlow.setWindowSize(fbWinSize);
    fbFlow.setNumIterations(fbIterations);
    fbFlow.setPolyN(fbPolyN);
    fbFlow.setPolySigma(fbPolySigma);
    fbFlow.setUseGaussian(fbUseGaussian);
    fbFlow.calcOpticalFlow(camera);
    
    for(int i = 0; i < particles.size(); i++){
        float adjustedX = particles[i].position.x * float(camera.getWidth()) / ofGetWidth();
        float adjustedY = particles[i].position.y * float(camera.getHeight()) / ofGetHeight();
        ofVec2f force = fbFlow.getFlowOffset(adjustedX, adjustedY) * 3;
        particles[i].serForce(force);
        particles[i].update();
    }
}

//--------------------------------------------------------------
void ofApp::draw(){
    ofSetColor(255);
    camera.draw(0, 0, ofGetWidth(), ofGetHeight());
    fbFlow.draw(0, 0, ofGetWidth(), ofGetHeight());
    
    for(int i = 0; i < particles.size(); i++){
        particles[i].draw();
    }
    
    gui.draw();
}


//--------------------------------------------------------------
void ofApp::keyPressed(int key){

}

//--------------------------------------------------------------
void ofApp::keyReleased(int key){

}

//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y ){

}

//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mouseEntered(int x, int y){

}

//--------------------------------------------------------------
void ofApp::mouseExited(int x, int y){

}

//--------------------------------------------------------------
void ofApp::windowResized(int w, int h){

}

//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg){

}

//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo){ 

}
particle.h

//
//  particle.h
//  opticalFlowApp1
//
//  Created by aa_debdeb on 2015/11/15.
//
//

#ifndef __opticalFlowApp1__particle__
#define __opticalFlowApp1__particle__

#include 
#include "ofMain.h"

class Particle {

public:
    
    Particle();
    void update();
    void draw();
    void borders();
    void serForce(ofVec2f _force);
    ofVec2f position;
    ofVec2f velocity;
    ofVec2f force;
    float radious;
    float maxSpeed;
    
};

#endif /* defined(__opticalFlowApp1__particle__) */
particle.cpp

//
//  particle.cpp
//  opticalFlowApp1
//
//  Created by aa_debdeb on 2015/11/15.
//
//

#include "particle.h"

Particle::Particle(){
    position = ofVec2f(ofRandom(ofGetWidth()), ofRandom(ofGetHeight()));
    velocity = ofVec2f(ofRandom(-1, 1), ofRandom(-1, 1));
    force = ofVec2f(0, 0);
    radious = 10;
    maxSpeed = 10;
    
}

void Particle::update(){
    velocity *= 0.99;
    velocity += force;
    velocity.limit(maxSpeed);
    position += velocity;
    borders();
    force *= 0;
}

void Particle::borders(){
    if(position.x < radious){
        position.x = radious;
        velocity.x *= -1;
    }
    if(position.x > ofGetWidth() - radious){
        position.x = ofGetWidth() - radious;
        velocity *= -1;
    }
    if(position.y < radious){
        position.y = radious;
        velocity.y *= -1;
    }
    if(position.y > ofGetHeight() - radious){
        position.y = ofGetHeight() - radious;
        velocity.y *= -1;
    }
}

void Particle::draw(){
    ofSetColor(255, 255, 0, 100);
    ofDrawCircle(position.x, position.y, radious);
}

void Particle::serForce(ofVec2f _force){
    force = _force;
}

プロジェクトファイルは以下. openFrameworks/opticalFlowApp1 at master · aa-debdeb/openFrameworks

参考

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