ofxCvで笑い男をやってみた

画像処理のハローワールド的存在(?)である笑い男をopenFrameworksofxCvでやってみました。 pythonとかWebとかでも笑い男書いたし、何かもう笑い男ばっかりやっている気がします。

openFrameworksのofxCvで作った笑い男。

さて、ソースコード。

#include <ofMain.h>
#include <ofxCv.h>


class ofApp : public ofBaseApp {
private:
    ofVideoGrabber cam;
    ofxCv::ObjectFinder finder;
    ofImage laughingMan;

public:
    void setup() override {
        cam.setup(640, 480);

        finder.setup("haarcascade_frontalface_default.xml");
        finder.setPreset(ofxCv::ObjectFinder::Fast);

        laughingMan.loadImage("laughing_man.png");
    }

    void update() override {
        cam.update();

        if(cam.isFrameNew()){
            finder.update(cam);
        }
    }

    void draw() override {
        cam.draw(0, 0);

        for(int i=0; i<finder.size(); i++){
            ofRectangle rect = finder.getObjectSmoothed(i);
            laughingMan.draw(rect);
        }
    }
};


int main() {
    ofSetupOpenGL(640, 480, OF_WINDOW);

    ofRunApp(new ofApp());
}

ofxCv::ObjectFinderで顔を検出して、見付かった矩形領域に画像を重ねているだけです。実にシンプル。 OpenCVに同梱されているhaarcascade_frontalface_default.xmlbin/dada以下にコピーして、それからbin/data/laughing_man.pngなる画像を用意してからコンパイルしてください。

検出の精度を決めるsetPresetの引数にはFastの他にAccurateSensitiveなんてのがあるようです。ここを変えると精度やら速度やらが変わるはず。 Sensitiveにすると面白いほど誤検出します。Accurateはそこそこ。Fastが一番バランスが良い、ような気がします。

getObjectSmoothedなるメソッドで発見した顔の座標を取得していますが、getObjectというメソッドを使うことも出来ます。 細かい意味は分かっていないのですが、getObjectを使うと座標が安定しないのに対して、getObjectSmoothedは平準化してくれているっぽい。 getObjectSmoothedの代わりにgetObjectを使うと、笑い男がの位置ががくがくと飛ぶようになります。

実に手軽に笑い男が出来てとても良い感じですね。 アルファチャンネルとか自分で考えなくて良いのが素晴しい。

笑い男の画像: 笑い男パーツ: マイペースなブログ