ofxCv install and usage
以下はofxCvのREADMEより抜粋。原文は
https://github.com/kylemcdonald/ofxCv
日本語訳は以下のページにあるが、少し前のバージョンの記載になっている。
http://blog.n1n9.jp/how2/ofxcv-opencv.php
(追記:2017/4/22)
現時点でのoF 0.9.8に対するofxCvには、0.9.8用のofxCv-stableを選ぶ必要がある。
これをofxCv-master(0.10.0用)と間違えると、glm識別子がわからない、などのエラーが出る。
インストール
以下のようにgitを用いてソースコードをコピーする:
> cd openFrameworks/addons/
> git clone https://github.com/kylemcdonald/ofxCv.git
もしくは、その GitHub からソースをダウンロードしてフォルダに解凍し、ofxCv-master という名前を ofxCv に変更して openFrameworks/addons フォルダに格納する。 0.8.4のいくつかのサンプルでは ofxAutoControlPanel が必要になり、それは ofxControlPanel アドオンの中にある。
使い方
プロジェクト設定
ofxCv を用いるためには以下が必要となる:
ofxCv/libs/ofxCv/include/ ofxCv の全ヘッダが含まれている
ofxCv/libs/ofxCv/src/ ofxCv の全ソースが含まれている
ofxCv/src/ 全ての ofxCv をひとつの includeファイルにまとめている
opencv/include/ OpenCvのヘッダでaddons/ofxOpenCv/にある
opencv/lib/ コンパイルされた OpenCv のスタティックライブラリで addons/ofxOpenCv/にある
リンカは OpenCv のヘッダがどこにあるか知る必要がある。 XCode では Project.xconfigの一文を以下のように修正する:
HEADER_SEARCH_PATHS = $(OF_CORE_HEADERS) “../../../addons/ofxOpenCv/libs/opencv/include/” “../../../addons/ofxCv/libs/ofxCv/include/”
ofxCvのインクルード
ofApp.h の中で include文を追加する:
#include “ofxCv.h”
OpenCv は cv namespaceを用い、ofxCv は ofxCv namespaceを用いる。 .cpp ファイル内で以下のように記述することで自動的にインポートされる:
using namespace cv;
using namespace ofxCv;
ごくまれにコード内で cv:: と書く必要がある。例えば OS X ではRect と Point が OpenCvで定義されているが、 MacTypes.hでも定義されている。したがって OpenCv のRect もしくは Point を使う場合は曖昧さを避けるため明示的に cv::Rect もしくは cv::Point と書く必要がある。
ofxCv ではnamespaces の長所である関数名のオーバーロードを用いている。つまり ofxCv のラッパーにより cv::Canny() は ofxCv::Canny() としても呼び出すことができる。単純に Canny()と書けば、渡した引数に基づいて正しい関数が選択される。
(以下2015/10.28追記)
ofxCvで作業する
ofxOpenCvと異なり、 ofxCv は ofxCvImage のような第3の型を挿入するよりも、openFrameworks の元々の型か OpenCv の元々の型を使うように仕向けている。 OF とOpenCv の型をうまく使えるように、 ofxCv には toCv() と toOf() の関数が含まれている。それらは openFrameworks のデータを OpenCv のデータに、もしくは逆に変換する機能を提供する。 images のように大きなデータに対しては、複製ではなくラッピングすることで変換を行っている。 vectors のように小さなデータに対しては、複製を行う。
ofxCv の残りほとんどは、 helper 関数(例えば threshold())とラッパークラス(例えば Calibration)である。
toCv() と copy()
toCv() は openFrameworks のデータを OpenCv のデータへ変換するために用いられる。例えば:
ofImage img;
img.loadImage(“image.png”);
Mat imgMat = toCv(img);
として、 img に対するラッパーとして imgMat を生成する。deep copy(ラッパーでなく内容まで複製したデータ)を生成するためには、 clone() を用いて:
Mat imgMatClone = toCv(img).clone();
とする。もしくは copy() を用いる。これは toCv() がサポートするどの型でも機能する:
Mat imgCopy;
copy(img, imgCopy);
toCv() は IplImage* を返すofxOpenCv の ofxCvImage::getCvImage() メソッドと似ている。最大の違いは、OpenCv のコードを直接呼び出す際に toCv() を「その場で(in place)」常に使えるとは限らないことである。 別の言い方をすると、以下のように書くことは常にできる:
Mat imgMat = toCv(img);
cv::someFunction(imgMat, …);
しかし、 toCv() を以下のように(「その場で」)使うことは避けるべきである:
cv::someFunction(toCv(img), …);
なぜなら、「その場」での使い方がコンパイルエラーにつながる場合があるからである。もっと細かく言えば、 toCv() を「その場」で呼び出す場合、関数のその引数に対して非定数参照が要求されるときに失敗する。
drawMat() と toOf()
できるだけ早く簡単に、Mat をスクリーン上に直接描画したい時がある。それは drawMat() で行うことができる。 drawMat() は images をスクリーンに描画する最適の方法というわけではない。なぜなら、描画するたびに texture を生成するからである。効率的に描画したければ、 ofImage img; を用いて texture を一旦準備(アロケート)して、それから img.draw() を用いて描画すべきである。
- Mat mat = toCv(img); を用いて ofImage を Mat として扱い、その mat を修正し、そして img.update() で修正した画素を GPUにアップロードするか、
- 他の方法として、Mat が修正されるたびに toOf(mat, img) を呼び出す。 この場合 texture は必要とされる場合だけ再準備される(例えばサイズが変わった時)。
プロジェクト設定におけるヘッダサーチパスは、projectGeneratorを用いれば勝手に設定されるが、冗長なパス設定も追加される様子。
公開されている記事の中には、例えばofApp.hがtestApp.hになっている場合もあるので注意(旧バージョンでの記載)。
ofxOpenCvアドオンはopencvのライブラリやヘッダを用いるために必要となる。最新のofxOpenCvアドオンにおけるopencvのバージョンは2.4.9(2015/10時点)。
追記したのはoFとopenCVのやり取りの部分。特にofImageのupdateはMatだけ使っていると忘れがち。描画対象はofImageを使い、描画しない画像データはMatでよいかと思われる。