openFrameworksでiOSの自撮りカメラを作る-2

      openFrameworksでiOSの自撮りカメラを作る-2 はコメントを受け付けていません

ofxCVはどうでしたか?頑張れば結構色々な自作エフェクトが作れると思います。ここからは顔のパーツをアプリに認識させる実習をおこないます。

ofxFaceTrackerのダウンロードとインストール

githubからダウンロード、解凍し、addonsフォルダに入れてください。
https://github.com/kylemcdonald/ofxFaceTracker

projectGeneratorで以下のように設定し、新しいプロジェクトを作ってください。

カメラを使うためのプライバシー設定をおこなう

このままだと、カメラを使うことができないので、ofxiOS-Info.plistPrivacy – Camera Usage Descriptionを追加します。

modelフォルダのコピー

ofxFaceTrackerを自身が作成したプロジェクトで使う場合は、アドオンを追加するだけではなく、プログラムに顔を認識させるためのmodelフォルダをコピーする必要があります。
of_v0.10.0_ios_release > addons > ofxFaceTracker > libs > FaceTracker > modelフォルダをコピーします。

そして、of_v0.10.0_ios_release > apps > myApps > myFaceTracker-iOS > bin > data 内にペーストしてください。

これで、顔のデータを認識することができます。

顔のパーツに合わせた線を描画する

ofApp.hで以下の変数を宣言します。ofxFaceTrackerを使うため、ofxCv.hofxFaceTracker.hの使用を宣言することを忘れないでください。

ofApp.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#pragma once
 
#include "ofxiOS.h"
#include "ofxCv.h"
#include "ofxFaceTracker.h"
 
 
class ofApp : public ofxiOSApp{
 
    public:
        /*省略*/
 
        ofVideoGrabber cam;     //カメラ用変数
        ofxFaceTracker tracker; //トラッキング用変数
        float winScale;         //ウィンドウの拡大率
        bool ready;             //カメラが使えるかを確認する変数
};

次に、setup()、update()、draw()でカメラの設定やエフェクトの設定をおこないます。

ofApp.mm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include "ofApp.h"
 
//--------------------------------------------------------------
void ofApp::setup(){
    ofBackground(0);
 
    //インカメラはDeviceID(1)
    cam.setDeviceID(1);
    cam.setup(640, 480);
 
    //カメラのサイズと画面のサイズの比を計算
    winScale = ofGetWidth() / cam.getWidth();
    ready = true;
 
    //トラッキング機能を準備
    tracker.setup();
}
 
//--------------------------------------------------------------
void ofApp::update(){
    if(!ready) return;
 
    //カメラ更新
    cam.update();
 
    //カメラが動いていたらトラッキング更新
    if(cam.isFrameNew()) {
        tracker.update(ofxCv::toCv(cam));
    }
}
 
//--------------------------------------------------------------
void ofApp::draw(){
    if(!ready) return;
 
    ofSetColor(255);
 
    //カメラ映像とトラッキングの結果を描画///////
    ofPushMatrix();
 
    //画面を鏡面にする
    ofTranslate(ofGetWidth(), 0);
    ofScale(-1, 1);
 
    ofScale(winScale);  //画面を拡大
    cam.draw(0, 0);
    tracker.draw();
 
    ofPopMatrix();
 
    //オブジェクトを描画///////////////////////
 
 
    //トラッキング情報を表示////////////////////
    ofPushMatrix();
    ofScale(2);
    ofTranslate(10, 15);
 
    ofSetColor(255);
 
    //画面にどのくらい近づいているかを検出
    ofDrawBitmapString("tracker scale= " + ofToString(tracker.getScale()), 0, 0);
    ofTranslate(0, 15);
 
    ofPopMatrix();
}

顔の輪郭や、眉毛、目、鼻、口に白い線が現れます。

顔のパーツの位置にオブジェクトを表示する

このofxFaceTrackerは、59箇所の点を認識することができます。

以下のurlを参照。
https://www.slideshare.net/takmin/201205016-deformablemodelfitting

59箇所の点にオブジェクトを描画することは簡単です。ここでは、眉間の点であるポイント27に赤い円を表示してみます。

draw()に以下のコードを追加します。tracker.getScale()を使用することによって、画面に顔が近づいたり離れたりしても、顔に対するオブジェクトの比率が一定になります。

draw() – ofApp.mm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//オブジェクトを描画///////////////////////
 
//画面の中での顔の輪郭の比率を検出。オブジェクトの大きさに反映させると、
//画面から顔までの距離によってオブジェクトが拡大縮小する。
float trackerScale = tracker.getScale();
 
ofPushMatrix();
 
//眉間の点を描画----------------------------
//https://www.slideshare.net/takmin/201205016-deformablemodelfitting
int x1 = ofGetWidth() - (int)tracker.getImagePoint(27).x * winScale;
int y1 = (int)tracker.getImagePoint(27).y * winScale;
ofSetColor(255, 0, 0);
ofDrawCircle(x1, y1, 10 * trackerScale);
 
ofPopMatrix();

次に頭頂を検出してみますが、これはちょっと特殊です。もともとofxFaceTrackerは頭頂の点は検出できないので、ポイント30から27の距離を上方向に4倍してみました。この方法が最善ではないでしょうから、自身で色々計算を考えてみてください。

draw() – ofApp.mm

1
2
3
4
int x2 = ofGetWidth() - ((int)tracker.getImagePoint(30).x - ((int)tracker.getImagePoint(30).x - (int)tracker.getImagePoint(27).x)*4) * winScale;
int y2 = ((int)tracker.getImagePoint(30).y - ((int)tracker.getImagePoint(30).y - (int)tracker.getImagePoint(27).y)*4) * winScale;
ofSetColor(0, 255, 0);
ofDrawCircle(x2, y2, 20);

また、口や目などの場合には、点で結ばれたグループ(オブジェクト)として、位置を検出することもできます。次の例では、口の位置の中心点を出し、さらにその広さや高さも検出しています。
ちなみに、顔の部分(グループ)は以下のパラメータを使うことによって取得できます。
LEFT_EYE_TOP, RIGHT_EYE_TOP, LEFT_EYEBROW, RIGHT_EYEBROW, LEFT_EYE, RIGHT_EYE, LEFT_JAW, RIGHT_JAW, JAW, OUTER_MOUTH, INNER_MOUTH, NOSE_BRIDGE, NOSE_BASE

tracker.getGesture()で顔のパーツの動きを数値化することもできます。以下のパラメータを使うことによって取得できます。
MOUTH_WIDTH, MOUTH_HEIGHT, LEFT_EYEBROW_HEIGHT, RIGHT_EYEBROW_HEIGHT, LEFT_EYE_OPENNESS, RIGHT_EYE_OPENNESS, JAW_OPENNESS, NOSTRIL_FLARE

draw() – ofApp.mm

1
2
3
4
5
6
7
8
9
10
//顔の部分(グループ)を検出
ofPolyline poly = tracker.getImageFeature(ofxFaceTracker::OUTER_MOUTH);
int x3 = ofGetWidth() - poly.getBoundingBox().getCenter().x * winScale;
int y3 = poly.getBoundingBox().getCenter().y * winScale;
 
//tracker.getGesture()で顔のパーツの動きを数値化
float mouthW = tracker.getGesture(ofxFaceTracker::MOUTH_WIDTH);
float mouthH = tracker.getGesture(ofxFaceTracker::MOUTH_HEIGHT);
ofSetColor(0, 0, 255);
ofDrawEllipse(x3, y3, mouthW * 10, mouthH * 10);

最終的なコードは以下になります。
myFaceTracker-iOS

参考:表情認識プログラム

表情認識プログラムです。ofxFaceTrackerのサンプルとしてもともとあった「example-expression」を元にしています。
左上のバーは通常は「neutral」で、笑う(と同時に顔を上向きにする)と「smile」、驚くと「surprised」になります。驚くかどうかは目から眉毛までの距離で計っているので、前髪が長いと正常には動かないことが多いです。
なお、ダブルタップするとトラッキング情報が全て非表示になるようになっています。
myFaceTracker-expressionSimple