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() を用いて描画すべきである。

  1. Mat mat = toCv(img); を用いて ofImage を Mat として扱い、その mat を修正し、そして img.update() で修正した画素を GPUにアップロードするか、
  2. 他の方法として、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でよいかと思われる。