2013年3月29日金曜日

[iOS]iOSでofxFaceTrackerを使用する方法

openFrameworksのアドオンの1つ、ofxFaceTrackerをiOSで使用するのに手こずったのでメモ。

まず普通にアドオンを追加してコンパイルしてもコンパイルが通らない。
こんな感じ。

iOSでは先にofxOpenCVを読み込んであげなきゃいけない。のでofxOpenCVをアドオンに追加し、ofxFaceTrackerの前(厳密にはofxCvの前)でインクルードしてもう一度コンパイルしてみる。
するとコンパイルは通った!

でカメラの初期化とかしてFacetrackerを使ってみようとコンパイルは通るけど起動時にエラーが出る。

なんでかなーと色々調べてると、ofxiPhoneアドオン内のofiPhoneVideoGrabber内の関数にこんな記述が…(笑)

 
ofPixelsRef ofiPhoneVideoGrabber::getPixelsRef(){
    static ofPixels dummy;
    //@TODO implement me
    return dummy;
}
 
ここをこんな風に修正したらちゃんと動くようになりました。

 
ofPixelsRef ofiPhoneVideoGrabber::getPixelsRef(){
    static ofPixels pixels;
    pixels.setFromExternalPixels(getPixels(), getWidth(), getHeight(), 3);
    return pixels;
}
 


参考URL:https://github.com/kylemcdonald/ofxCv/issues/14

2013年3月13日水曜日

[openCV]openFrameworksでwatershedアルゴリズムを実装する

openFrameworksを使ってopenCVを使おうと思ったら、意外と単純じゃなかったのでメモ。
学生の時にもっと画像処理系の研究しておくべきだった。

openFrameworksにはopenFrameworks用のopenCVライブラリofxopenCVが用意されているのだけど、openCVよりもできることが限られてる気がしました。
例えば、watershedアルゴリズムを使って領域分割しようとしてもofxopenCV用にはその関数が用意されていなかったり。直接openCVも使えるので多分そっち使ってってことだとは思うけど。

以下、openFrameworks内でwatershedアルゴリズムを実装した方法です。

1、ofxCvClolorImageのインスタンスに画像を読み込む

    ofImage buf; 
    ofxCvColorImage ofxSrc;
    buf.loadImage("munk.jpeg");
    ofxSrc.setFromPixels(buf.getPixels(), buf.width, buf.height);

2、openCVの画像データ構造体IplImageの入力画像、マーカー画像、出力画像用インスタンスを生成する。
この時、marker用画像のdepthは IPL_DEPTH_32S、nchannelは1にしなければエラーになる。(ここに詰まった。)

 
    IplImage *srcImg, *markers, *dstImg;
    srcImg = ofxSrc.getCvImage();
    
    markers = cvCreateImage(cvGetSize(srcImg), IPL_DEPTH_32S, 1); //depth, nchannelに注意
    cvZero(markers);

    dstImg = cvCloneImage(srcImg);

3、watershedアルゴリズム用のマーカーをランダムに分割数(この例では200個にした)作成する

 
    int seed_rad = 20;
    static int seed_num = 0;
    
    for(int i=0;iwidth), ofRandom(srcImg->height));
        cvCircle (markers, pt, seed_rad, cvScalarAll (seed_num), CV_FILLED, 8, 0);
    }

4、watershedアルゴリズムを実行し、出力画像に結果を代入する。

 
    cvWatershed(srcImg, markers);
    
    // 実行結果の画像中のwatershed境界(ピクセル値=-1)を結果表示用画像上に表示する
    int *idx;
    for (int i = 0; i < markers->height; i++) {
        for (int j = 0; j < markers->width; j++) {
            idx = (int *) cvPtr2D (markers, i, j, NULL);
            if (*idx == -1)
                cvSet2D (dstImg, i, j, cvScalarAll (255));
        }
    }

5、最後に画面描画ができるように用にofxCvClolorImageに結果画像を代入する。

 
    ofxCvColorImage ofxSrc,ofxDst;
    ofxDst.allocate(dstImg->width, dstImg->height);
    ofxDst = dstImg;

ムンクの画像を分割した結果がこれ。