openCV3/4のメモ

openCV3/4のメモ

要約

openCv4をopenframeworksで使うまでの手順。
プロジェクトの生成については、ほかサイトで見なかった簡単な方法をメモ。
めちゃ雑記です。

概要

oFでopenCV3とか4とか使ってみます。
この記事この記事にそって進めてみる。
opencv4でないといけないことは特にないです。ただただBackgroundSubtractorを試してみたかった。
後日また雑な記事かきます。テストの動画だけ貼っときます。なにかのための証拠。

環境とりあえずMac

openCVのinstall

まずはopenCV3 or 4のインストール。
※ 基本最新で上書きされるっぽい。3,4を共存させる方法もあるらしいが、自分は openCv4.1.0でこれといって不具合はないので、opencv4のみになっています。

brew tap homebrew/scienceは使えなくなったらしい。参考
そのため brew tap brewsci/science こちらのコマンドで環境アップデート。

  • opencv3の場合
    brew install openCV3で入れる。
  • opencv4の場合
    opencv4についてはこちらが詳しい。
    brew upgrade opencv でopenCV4(最新版 ex: 4.1.0)を入れる。
途中xcodeのコマンドラインをインストールしてね的なエラーが出たので、xcode-select --installをして、再度upgradeかけると、エラーなく無事完了した。  
過去に入れた気がするのにと思っていたけど、どうもOSをアップグレードすると再度入れる必要があるらしい。  

普通にすすめると、たいていは/usr/local/Cellar/opencv/が更新されるはず。

Xcodeで新規プロジェクト作成

色んなサイトでは以下の方法があげられていたが、パス間違える可能性があったり、記入が面倒だったりなので、個人的にはおすすめじゃない。

紹介されていたプロジェクト生成方法

open
  1. Project.xcconfigでOPENCV_PATHを設定 パスは適宜変えてください。
//OpenCV3
OPENCV_PATH = /usr/local/Cellar/opencv/3.4.1_2
//OpenCV4
OPENCV_PATH = /usr/local/Cellar/opencv/4.1.0_2  
  1. BuildSettingsのHeader Search PathsにOpenCVのインクルードパスを追加
    $(OPENCV_PATH)/include/opencv4

  2. Build SettingsのOther Linker Flagsに必要なdlybを追加
    ここが面倒、、

openCV4をインストールすると、libフォルダにdylib以外に.aファイルもありました。
これらおそらく中身は同じですが、動的ライブラリか、静的ライブラリかの違いがあります。  
こちらでは動的のほうがファイルサイズ小さく、使用メモリも少なくできるっぽい。
dylibを追加するのが面倒な場合は、
.aファイルをGeneralのLinked Frameworks and Librariesにドラッグドロップしても起動可能です。

(たぶんProject.xcconfigのOTHER_LDFLAGSこのあたりの設定でどうにかなるのだけど、、)

#include <opencv2/core.hpp>ここでリンク貼れてないよってエラー出たけど、単純にheader search pathに$(OPENCV_PATH)/includeを入れてないのが原因でした。

おすすめの生成方法

ProjectGeneratorでプロジェクトを作り、

  1. プロジェクトのSearchPaths > HeaderSearchPathsに/usr/local/Cellar/opencv/4.1.0_2/include/opencv4 を追加。
  2. /usr/local/Cellar/opencv/4.1.0_2/libから必要なdylibを General>LinkedFrameworks and Libraries にドラッグドロップで追加

どのヘッダ呼び出すときにどのlibが必要になるのか、どこを見ればいいんだろう。。。今の所勘で追加しています。。。
このやり方が簡単安定な気がする。Debug/Releaseで変更の必要ない?1だと必要かもだけど。

画像は適当に追加したのでごちゃっとしています。どうやらdylibなど動的ライブラリのほうが実行ファイルが軽く、メモリの消費を抑えられるとかどうとか。。。

ofxCvとの連携と利用

oFでopenCVを扱う際に、関数群を使いやすくまとめてくれているofxCvを使うとめっちゃ便利。

ProjectGeneratorでofxCvのみ追加してプロジェクト生成。
あとは、上の1.2.を同様に。
なんかもしかしたら、もうちょうっと設定必要だったかも。わすれてもうた。


おまけめも

ofxOpenCvDnnSegmentation など

やはりどこにでも先人がいるもので、馬場先生のofxOpenCvDnnSegmentationがあった。openCVのdnnライブラリをいろいろまとめてらっしゃる。

配布されていたopencv2.aでうまくいかなかったので、自分でメイクしてみる。参考

が、原因はどうもそこではなかった。ので、makeの手順は隠す。

makeの手順
  1. python build_framework.py osxを実行するが、python3ではうまくいかないみたい。
    自分の場合は python2 build_framework.py osc とするとうまくいった。
    python -Vでバージョンを確認したり、which python, which python2でpythonの2.7以上が使われているか確認するとよさそう。
    参考1 参考2

エラー(returned non-zero exit status 65)について
** BUILD FAILED **

The following build commands failed:
    CompileC /Users/hiraoshugo/openCV/opencv-4.1.0/platforms/osx/osx/build/build-x86_64-macosx/modules/world/OpenCV.build/Release/opencv_world.build/Objects-normal/x86_64/opencl_kernels_video.o /Users/hiraoshugo/openCV/opencv-4.1.0/platforms/osx/osx/build/build-x86_64-macosx/modules/world/opencl_kernels_video.cpp normal x86_64 c++ com.apple.compilers.llvm.clang.1_0.compiler
(1 failure)
============================================================
ERROR: Command '['xcodebuild', 'MACOSX_DEPLOYMENT_TARGET=10.12', 'ARCHS=x86_64', '-sdk', 'macosx', '-configuration', 'Release', '-parallelizeTargets', '-jobs', '4', '-target', 'ALL_BUILD', 'build']' returned non-zero exit status 65

こんなエラーでた。どうやらcmakeのバージョン(3.10.2)がダメらしい。参考
てわけで、cmakeのupgrade

cmake --version
// cmake version 3.10.2
brew upgrade cmake
// .....
cmake --version
// cmake version 3.15.2
python2 build_framework.py osx
// .....

  1. python build_framework.py –contrib <opencv_contribへのパス> osx

そんなこんな。。

結論、こちらのように#include "opencv2/imgproc/imgproc_c.h"をofxCvのWrappers.hに追加した。

modelデータは以下から直接落とした。
http://dl.caffe.berkeleyvision.org/fcn8s-heavy-pascal.caffemodel


最近いろんな出会いがあって楽しい。特に音楽やってる人とよく出会う。
春よりも春らしい。

明日は学生CGコンテスト25周年のパーティーにいってきます。
夏がもうすぐ終わるからね。季節の変わり目。春の訪れ。
秋はいずこへ。

ArtHackDay2018に参加しました

終了して1ヶ月ほど経っちゃったけど、ひょんなことからArtHackDay2018に参加させていただいてました。
個人的にはめちゃくちゃ勉強になったのと、またいつか参加したいなと思うので、感想書いときます。書かないよりはマシ程度で。思い出したら追記もします。
(別の場所で書いたものをより個人的なメモとして書いています。)

ArtHackDayは前々から参加してみたいと思ってたのですが、仕事の関係で日程的に微妙でエントリー忘れてました。

が、幸い、職場の人が参加されていて、Day1Day2が終わった時点で人数少ないからサポートで、ということで急遽参加させていただきました。

一応、Art Hack Day (アートハックデイ)とは、

アートに特化したハッカソン。参加申し込みから選出されたアーティストや技術者、そして研究者が一堂に会し、その場で結成したチームで、短期間でアート作品を制作する。

作ったもの

2台のディスプレイが向き合い、にらめっこや会話をしているような Apophenicという作品。

お互いが、お互いのディスプレイに映る木漏れ日のような映像の中から顔認識をしています。

ここでいう顔認識は、人間が木漏れ日や、シミ、木目などに見つける「顔っぽい」ものを認識することを意味しています。

心霊写真なども同じような現象ですが、これをアポフェニアというそうで、今回の作品ではその現象を利用して、ディスプレイというモノ同士がコミュニケーションしている様を表現しました。

Dlibってライブラリを使った機械学習を利用した顔認識なども試したのですが精度が高くちゃんと顔じゃないと顔と認識しなかった。

今回は「顔っぽい」を見つけることに注力するため、そういう精度のいいものではなく、丸が3つあって、その位置や大きさの関係性から顔っぽさを検出しました。アルゴリズムは取り急ぎ自分で考えたものを実装しています。
個人的には「曖昧な顔認識(ghost)」って呼んでいて、今後アート的な使いみちがありそうな可能性を感じていたりします。

アルゴリズムの話については、
openCvで取ったblobs(輪郭)ひとつひとつに対して、以下の処理を行います。

①まず一旦、仮にRightEye(仮)として登録
②他のblobsとのサイズ、距離を見て、LeftEye(仮)を設定する。該当するのがなければ①へ戻って次のblobに処理を移す。
③他のblobs(仮設定した右目左目を除く)とのサイズ、距離を見てMouthを設定する。なければ①へ戻る
④設定していた右目、左目、口を1つの顔っぽいオブジェクト(ghostFace)として設定する。

みたいな感じ。(すげー漏れありそう)

これをスレッド分けて計算させている感じです。雰囲気が伝われば嬉しい。
各blobsに対して上記の処理を行っていたので別スレッドで計算させる恩恵は大きかったっぽい。

 

そんで作品の話に戻ると、
顔っぽさを認識することで、映像に変化が起こり、その変化によってまた新たな部分に顔っぽさが見出されて映像が変化し...といった具合にディスプレイ同士が勝手にやりとりをし、その相乗効果によって、想像を超えた映像が生み出されるのではないか?的なところまで考えていたのですが、展示までにはどうもそこまでうまくは行かなかった。

パラメータの調整次第ではそんなことも実現できるかも。。
審査員の方からも似たようなご指摘いただいて、たしかにそのとおりなんだよなーと。分かる人にはわかるのかもしれないけど、それだけじゃさみしい。

 

個人的には、曖昧な顔認識っていうような(簡素な)アルゴリズムから自分で考えて実装して作品に組み込むということがたぶん初めてで、しかも2日くらいでなんとかできたというのは我ながら よく頑張りました◎です。半年くらい前の私には想像つかないようなことだったので、一応レベルアップしてたんだなと。
あと作る前に、ある程度頭で設計のイメージしてコーディングに移るという流れが取れたのもよかったです。ちゃんと設計できてないのについつい手を動かして試してみがち〜ってあるあるを払拭できた。

と言ってもできなかったことがあったり、お粗末なコードが多々あったりなので、、精進します…

この作品を作るに至るまで、メンバーの方とオンラインで1,2時間会議したりして、あーでもないこーでもないを繰り返しました。個人的にはそういう時間が貴重に感じるので楽しかったです。

反省点はたくさんありますが、参加できてとてもいい経験ができました。何よりいろんな方と知り合えたのが嬉しい。あとみんなやさしい。

今後、できればこの作品をアップデートもしたいです。

 

openFrameworksで作った.appを配布する

openFrameworksで作ったアプリを共有したい時、どのファイルを共有すればいいのか情報があまりなかったので、メモ。
といっても下記参考サイトをそのまま。

実際どの方法が正しいのか私自身よくわかってないけれど、とりあえずは以下の方法が良さそう。環境はMac OSXでのみ確認、、、確認中です。
Mac同士では問題なさそうだけど。。

手順はふたつ!
まず、XcodeからBuild Phasesを開いて、RunScriptに以下を追加する。

cp -r bin/data "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Resources";

※上をコピペすると"がフォントの違い?でパスとして認識されませんでした。
→「"」だけ手入力で修正したらパスの文字列が赤色になって有効になります。

うえすることで、bin/data以下に入っているイメージとかなんやかんやが、ビルド時にできるOOO.appファイルのResourcesファイルにコピーされるわけですね。
これがうまくいってるかはビルドして生成されるOOO.appを右クリック→パッケージの内容を表示 でResourcesフォルダ確認できます。

で次に、ofAppのsetup()内で以下を追加

ofSetDataPathRoot("../Resources/data/");

うえすることで、bin/dataフォルダではなく、app内のResourcesフォルダからデータ取ってくると指定している。

そんな感じだと思います。

こうすれば、OOO.appを他のPCでも動かせるようになります。
dataフォルダに画像素材とか置く必要ないのであればこんな処理も必要ないだろうけど。

参考:
https://stackoverflow.com/questions/4882572/how-to-bundle-an-openframeworks-application-in-xcode-relative-resource-linking

20190106追記

app化したファイルをAirdropで別のPCに送ると、dataフォルダを参照できないことがありました。実際には、ofxGuiの設定xmlをセーブなどできてもロードできないというもので、たしかにappのコンテンツの中のResourceフォルダのxmlが更新されていませんでした。

詳しいことはわかりませんが、Airdropで送ったappをダウンロードフォルダにおいたまま開くと上のような現象が起こり、一度デスクトップや別フォルダに移動させると正しいdataパスを指定していました。

ofFilePath::getCurrentExePath() などでちらっと確認したところ、Airdropで送りたてのappではprivate/~~の一時的なフォルダにappが置いてあるみたいで、期待するdataフォルダ(この場合は~~~/downloadsにあると思ってた)を参照しないようです。

とにもかくにも上の現象が起こる場合は、一度別のフォルダに移動して開いてみると良いかもしれません。

oF_Enumの値をランダムで取得する

oFのtipsメモです。

※こちらの記事ですが、誤解を招いてしまうことがありました。すいません!
追記でコメント補足しておきます。(201906)

openFrameworksでEnumを使っていろいろする際に、値をランダムで取得したいと思いました。
具体的には、いろんな図形のパーティクル的なものを作る際に、enum(列挙型変数)で TRIANGLE,RECTANGLE, CIRCLE などを選択できるようにしたKatachiクラスを作っておいて、コンストラクタの中で形をランダムで決定するというものです。

「Enum ランダム」のように調べるとあまり日本語で文献がなかったように思ったので、メモしておきます。
参考にしたのは以下
https://stackoverflow.com/questions/2999012/generating-random-enums

結論から書くと、
katachiMode = static_cast<Mode>(round(ofRandom(3)));
という感じ。
static_castenumで設定したModeという型にキャストするということです。
ただし、いつでもこれで解決できるというわけではなさそうで、
contiguous連続的?)な場合でしか使えないとのこと。
おそらく、enumの値を
enum Mode{
Triangle = 0,Circle = 3, ~~
みたいにするとダメよってことだと思っています。深く追求してません。

もし間違っていたら教えていただければ幸いです。。

→間違ってはいないですが特に上のことをする必要もありませんでした。🙏
enumで指定した型(ここではKatachi_Mode)を持つ変数へ値を代入するには、

katachiMode = (KATACHI_MODE)(int)ofRandom(3);

とシンプルにキャストするだけでよかったみたいです。
たしかWindowsでは一度(int)にキャストした上で、再度(KATACHI_MODE)にキャストする必要があったはず。逆にOSXでは直接(KATACHI_MODE)にキャスト可能。
さらに、ここではofRandom(3)としていますが、本当はenumで指定している要素の数を指定したいところ。

ただ如何せんenumには要素数を取得するメソッドはないみたいで、上のstackoverflowのリンクでもあるように、要素の最後にlast,など追加して、このlastを全体の要素数として利用する方法などが調べるとよく出てきます。

このやり方がどうにも腑に落ちないので、vector<string>で要素名のリストを作って、この要素名のサイズを利用することが多いです。
こうしておけば、enumの名前をstringとして取得できるし、enumを増やした際に割と流れで名前を追加できるので漏れが少ない気がします。

正直まだ腑に落ちていないけれど、一旦はこれで落ち着いてます。が、もっといい方法ないでしょうか・・

・・・

で、これを使って以下のようなクラスを作りました。(一部省略)
(gistも修正しました🙇‍♂️)

vector<Katachi> katachiV; をつくって
katachiV.push_back(k);

などでKatachiインスタンスを追加するたびにランダムで四角や三角のオブジェクトを追加することができます。

ミニマムなテストですが、いつか来るであろうVJイベント参加に向けてoFでいろいろできるようにちまちまと作っていきたいと思います。
(以前、interimというIAMASと多摩美のイベントでoFを使ったVJを拝見して感化されていました。)

超余談ですが、クラス名をKatachiのように日本語で作るのいいなと思ってます。
oF開発者ザック・リーバーマンさんが、School for Poetic Computation(SFPC)というのされていて、詩的なコーディングを目指すって思想がありまして、コードの中でもちょっとオサレ意識もつこと大事だなと思います。
まだまだ勉強中ですが、そういうことを今のうちから意識してもいいよなと。