ofxCvで笑い男をやってみた
画像処理のハローワールド的存在(?)である笑い男をopenFrameworksのofxCvでやってみました。 pythonとかWebとかでも笑い男書いたし、何かもう笑い男ばっかりやっている気がします。
さて、ソースコード。
#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.xmlをbin/dada以下にコピーして、それからbin/data/laughing_man.pngなる画像を用意してからコンパイルしてください。
検出の精度を決めるsetPreset
の引数にはFast
の他にAccurate
やSensitive
なんてのがあるようです。ここを変えると精度やら速度やらが変わるはず。
Sensitiveにすると面白いほど誤検出します。Accurateはそこそこ。Fastが一番バランスが良い、ような気がします。
getObjectSmoothed
なるメソッドで発見した顔の座標を取得していますが、getObject
というメソッドを使うことも出来ます。
細かい意味は分かっていないのですが、getObjectを使うと座標が安定しないのに対して、getObjectSmoothedは平準化してくれているっぽい。
getObjectSmoothedの代わりにgetObjectを使うと、笑い男がの位置ががくがくと飛ぶようになります。
実に手軽に笑い男が出来てとても良い感じですね。 アルファチャンネルとか自分で考えなくて良いのが素晴しい。
笑い男の画像: 笑い男パーツ: マイペースなブログ