openFrameworksの顔をトラッキングして遊んでみよう

初めまして、10日目を担当する、けいです。
昨日のさんたさんに引き続きメディアアート作品を紹介しようと思います。
今回は「openFrameworks」を使ってprogrammingで顔をトラッキングして写真の顔と合成する方法を書いていこうと思います。
#[openFrameworks](http://openframeworks.cc/ja/)とは
![oft02icon.png](https://qiita-image-store.s3.amazonaws.com/0/93175/964ab575-6784-b708-11d1-deb67aea6155.png)

openFrameworksは創造的なコーディングのためのC++のオープンソースツールキットです。

#導入
###ofxCvとofxFaceTrackerを入手しよう
ofxFaceTracker

```
cd openFrameworks/addons/
git clone https://github.com/kylemcdonald/ofxFaceTracker.git
```
ofxCv

```
cd openFrameworks/addons/
git clone https://github.com/kylemcdonald/ofxCv.git
```

#新規作成しよう（Xcode8,oF 0.9.8 で確認）
###1. アドオン追加

projectGenerator で新規プロジェクトを作成する際、次の3つのアドオンを追加します。

- ofxOpenCv
- ofxCv
- ofxFaceTracker

###2.モデルデータを追加しよう ＃重要！！！
ofxFaceTracker/libs/FaceTracker 配下にある、 model フォルダをプロジェクトの bin/data フォルダにコピー しよう
###3.写真を用意しよう
なるべく真顔で正面なのがオススメです。
#実践

```ruby:ofApp
#include "ofMain.h"
#include "ofxCv.h"
using namespace ofxCv;
using namespace cv;

#include "ofxFaceTracker.h"

class ofApp : public ofBaseApp{

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

		void keyPressed(int key);
    ofVideoGrabber cam;
    ofxFaceTracker tracker;
    ofxFaceTracker imgTracker;
    ofImage faceImage;
    ofEasyCam easyCam;
};

```

```ruby:ofApp.cpp
#include "ofApp.h"
using namespace ofxCv;

//--------------------------------------------------------------
void ofApp::setup(){
    //画面基本設定
    ofSetVerticalSync(true);
    ofEnableAlphaBlending();
    
    //カメラを初期化
    cam.initGrabber(640, 480);
    
    //合成するイメージのメモリ領域を確保して、読込み
    faceImage.allocate(640, 480, OF_IMAGE_COLOR);
    faceImage.load("写真の名前");
    //カメラ映像のフェイストラッカーのセットアップ
    tracker.setup();
    //合成する顔画像のフェイストラッカーのセットアップ
    imgTracker.setup();

}

//--------------------------------------------------------------
void ofApp::update(){
    //カメラ更新
    cam.update();
    if(cam.isFrameNew()) {
        //フェイストラッカーの更新
        imgTracker.update(toCv(faceImage));
        tracker.update(toCv(cam));
    }
}

//--------------------------------------------------------------
void ofApp::draw(){
    //カメラ映像を描画
    ofSetColor(255);
    cam.draw(0, 0);
    //フレームレート表示
    ofDrawBitmapString(ofToString((int) ofGetFrameRate()), 10, 20);
    
    //もしカメラの映像に顔が検出されたら以下の処理をする
    if(tracker.getFound()) {
        
        //カメラ映像からメッシュを作成
        ofMesh objectMesh = tracker.getObjectMesh();
        //合成する顔の画像からメッシュを作成
        ofMesh imgMesh = imgTracker.getObjectMesh();
        
        //静止画のメッシュの頂点情報を、カメラから生成したメッシュのものに変換
        //つまり現在の顔の表情を、静止画のメッシュに適用
        for (int i = 0; i < objectMesh.getNumVertices(); i++) {
            imgMesh.setVertex(i, objectMesh.getVertex(i));
        }
        
        //画面の3Dのパースをなしに
//        ofSetupScreenOrtho();
//        ofSetupScreenOrtho(640, 480, OF_ORIENTATION_DEFAULT, true, -1000, 1000);
        //カメラで検出された顔の、位置、大きさ、傾きを取得
        ofVec2f positon = tracker.getPosition();
        float scale = tracker.getScale();
        ofVec3f orientation = tracker.getOrientation();
        
        //静止画のメッシュをカメラの位置、大きさ、傾きにあわせる
        ofPushMatrix();
        ofTranslate(positon.x, positon.y);
        ofScale(scale, scale, scale);
        ofRotateX(orientation.x * 45.0f);
        ofRotateY(orientation.y * 45.0f);
        ofRotateZ(orientation.z * 45.0f);
        
        //静止画から生成メッシュを配置して、合成する画像をマッピング
        ofSetColor(255, 255, 255, 127);
        faceImage.getTexture().bind();
        imgMesh.draw();
        faceImage.getTexture().unbind();
        ofPopMatrix();
    }
}

//--------------------------------------------------------------
void ofApp::keyPressed(int key){
    if(key == 'r') {
        tracker.reset();
    }
}


```
色々な写真を試してみるもの面白いかもしれないですね

#まとめ
openFrameworksはメディアアートやプロジェクションマッピングなどその他にもできることがたくさんあり初心者から上級者まで楽しめるのではないでしょうか。

明日、11日目は@ygknさんの「Sinatraで某コメントフロー型動画サイト風プレイヤーを作った」です！

では、また会う日まで。