workshop/of/FaceController

faceController

このページでは,ofxFaceTracker を利用して,各顔パーツの情報を取得する方法を学びます. ある程度自由に各値を扱えるようになったら,簡単な操作コントローラを作ってみます.

ofxFaceTrackingから数値の取得

まず,そのための準備として,ofPolyline について学習します.ofxFaceTrackingでは認識された各顔パーツに関する情報を getImageFeature 関数を利用して取得できます.特に顔パーツ画像位置などに関するデータは ofPolyline の形式で関数の戻り値が 定義されています.このように定義されている関数がどのようなものなのかを知りたい場合,関数部分をハイライト表示(ダブルクリックで可能)して, の後,Control+クリック(右クリック)を行うと,下画像の様に「Jump to Definition」をクリックすることで,実際の定義部分に飛んで 確認することができます.適時活用してください.

基本的なベースを作成してみます

まずは ProjectGenerator を利用して,ofxFaceTracker を利用可能なひな形を作成しましょう.作成できたら,各testApp.h, testApp.cpp に関しては下記を コピーしましょう.

ofApp.cpp
#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup(){
  ofSetFrameRate(60);
  ofSetVerticalSync(true);
  
  cam.initGrabber(640, 480);
  tracker.setup();
}

//--------------------------------------------------------------
void ofApp::update(){
  cam.update();
  if(cam.isFrameNew()) {
    tracker.update(toCv(cam));
    
    if(tracker.getFound()) {
      face_outline = tracker.getImageFeature(ofxFaceTracker::FACE_OUTLINE);
    }
  }
  
}

//--------------------------------------------------------------
void ofApp::draw(){
  ofSetColor(255,255,255);
  cam.draw(0,0);
  ofSetColor(0,255,0);
  ofNoFill();
  
  if( tracker.getFound()){
    ofSetColor(255,255,255);
    ofRect(face_outline.getBoundingBox());
    ofDrawBitmapString("("+ofToString((int)face_outline.getBoundingBox().x)+","+ofToString((int)face_outline.getBoundingBox().y)+")",
                       face_outline.getBoundingBox().x,
                       face_outline.getBoundingBox().y);
  }
  
  
}
ofApp.h
#pragma once

#include "ofMain.h"
#include "ofxOpenCv.h"
#include "ofxFaceTracker.h"
#include "ofxCv.h"
using namespace ofxCv;

class ofApp : public ofBaseApp{
  
public:
  void setup();
  void update();
  void draw();
  
  ofVideoGrabber cam;
  ofxFaceTracker tracker;
  
  ofPolyline face_outline;
};

実行が確認できたら,各内容をしっかり理解しましょう.

練習1

では練習問題として,顔輪郭だけでなく,眉毛,目,鼻,口,顎に関してもその 多角線(ofPolyline)を同様の手順で取得できる ので,このプログラムをベースにして,各パーツの短形領域を表示するプログラムまで仕上げましょう.

練習2

プログラムがかけたら,各顔パーツに関して,Gesture という名前で,その状態をfloatで取得することも可能です. 例えば, tracker.getGesture(ofxFaceTracker::JAW_OPENESS); を利用すると,口の開閉具合が float 値で取得できます. Xcodeの補完機能で,どのようなGestureがあるかを確認し,その値を先のプログラムと同様に画面上に表示するプログラムを 作成してください.

練習3

では練習2までできたら,今度は様々なパラメータを利用して,3種類の認識処理をしてみましょう.どのようなパラメータを 使用するかはみなさんにお任せします.ofxFaceTracker からの変数だけで3種類のコマンドを利用できるようにします.ただし, 下記のことを設計指針に含めて作成してください.

  1. 自分だけでなく,誰でも(練習すれば)操作可能
  2. 極力キャリブレーション作業を伴わない.ただし,自動キャリブレーションであればOK

Box2dを追加して,顔でオブジェクトを操作する

Box2dを追加し,オブジェクトを一つ作成した上で,faceTracker によって,そのオブジェクトを 操作するインタフェースを作成してみましょう.基本操作として,下記アクションをできるようにしてみましょう.

  1. ジャンプ
  2. 右に移動
  3. 左に移動

下記サンプルをひな形として、はじめて見ましょう。

testApp.cpp
#include "testApp.h"

//--------------------------------------------------------------
void testApp::setup(){
  ofSetFrameRate(60);
  ofSetVerticalSync(true);
  
  cam.initGrabber(640, 480);
  tracker.setup();

  box2d.init();
	box2d.setGravity(0, 10);
	box2d.createBounds();
	box2d.setFPS(30.0);
	box2d.registerGrabbing();
  ofxBox2dCircle circle;
  circle.setPhysics(30.0, 0.53, 0.1);
  circle.setup(box2d.getWorld(), ofGetWindowWidth()/2,ofGetWindowHeight()/2, 10);
  circles.push_back(circle);
}

//--------------------------------------------------------------
void testApp::update(){
  cam.update();
  if(cam.isFrameNew()) {
    tracker.update(toCv(cam));
		
    if(tracker.getFound()) {
      face_outline = tracker.getImageFeature(ofxFaceTracker::FACE_OUTLINE);
    }
  }
  box2d.update();	
}

//--------------------------------------------------------------
void testApp::draw(){
  ofSetColor(255,255,255);
  cam.draw(0,0);
  ofSetColor(0,255,0);
  ofNoFill();
  
  if( tracker.getFound()){
    ofSetColor(255,255,255);
    ofRect(face_outline.getBoundingBox());
    ofDrawBitmapString("("+ofToString((int)face_outline.getBoundingBox().x)+","+ofToString((int)face_outline.getBoundingBox().y)+")",
                       face_outline.getBoundingBox().x,
                       face_outline.getBoundingBox().y);
  }
  
	box2d.drawGround();
  ofFill();
  ofSetHexColor(0xf6c738);
  circles[0].draw();
}

void testApp::keyPressed(int key){
  if( key == OF_KEY_UP){
    circles[0].addForce(ofVec2f(0,-1), 10000);
  }
  else if( key == OF_KEY_RIGHT ){
    circles[0].addForce(ofVec2f(1,0), 10000);
    
  }
  else if( key == OF_KEY_LEFT ){
    circles[0].addForce(ofVec2f(-1,0), 10000);
    
  }
  
}
testApp.h"
#pragma once

#include "ofMain.h"
#include "ofxOpenCv.h"
#include "ofxFaceTracker.h"
#include "ofxCv.h"
#include "ofxBox2d.h"
using namespace ofxCv;

class testApp : public ofBaseApp{
    
public:
  void setup();
  void update();
  void draw();
  void keyPressed(int key);
  
  ofVideoGrabber cam;
  ofxFaceTracker tracker;
  
  ofPolyline face_outline;
  
  ofxBox2d box2d;	
	vector circles;
};

Copyright (c) 2015 Tetsuaki BABA all rights reserved.