Take’s diary

Macとマイコンに関すること--ワクワクの製作日記

ESP32 + LEPTONサーモカメラで'3Dサーモグラフィー'を作る!!

なんでこんなことを思いついたんでしょう。

 最近、ZEDステレオカメラのソフトをかじっていて、画像の遠近をポイントクラウドで表現する参考プログラムを見ていたからなんです。

f:id:TAKEsan:20170221134238p:plain

ZEDステレオカメラのサンプルアプリ。右側がポイントクラウド。カメラからの距離が3Dで確認できる。

 温度分布をポイントクラウドで表現すれば、平面的な色で表現するよりぐっと認識しやすくなります。つまり一目で温度差が確認できるんじゃないか。ムフフフ。方針さえ決まれば、ワクワクの時間です。ZEDステレオカメラは、あくまでも詳細な距離測定が目玉ですから、コンピュータが表現しなくとも人間は物体の遠近を認識できるので、3Dにする意味をあまり感じませんが、これがLEPTONサーモカメラで測定した温度となるとどうか。

                                

こうなります。Z軸方向が測定した温度に対応しています。一応キーボード入力で、カラーマップの選択、ワイヤーフレームの有無、ポイント自体の大きさ変更が可能。サーモカメラで取り込んだデータの動きはどうでしょうか?。ポイントクラウドの操作はサクサクです。

f:id:TAKEsan:20170221143007j:plain

今回はESP32をLEPTONサーモカメラ(画像上部赤い袴をはいたPIカメラみたいなやつ)データ送信専用として使い、後ろのiMacでデータを受信。OpenFrameworksで加工して表示させました。

f:id:TAKEsan:20170221135555p:plain f:id:TAKEsan:20170221135610p:plain

       メガネ部分は温度が低くなるので。目の部分がえぐれてます。キモチ悪り〜

f:id:TAKEsan:20170221135608p:plain f:id:TAKEsan:20170221135604p:plain

 数年前Kinectで再現していたポイントクラウドとは別の意味で結構衝撃なのですが。私だけかな。

f:id:TAKEsan:20170221135601p:plain

当然ながら温度の高いところは山が高くなるわけで。うちのワンコを写してみたら目が飛び出てしまいました。それを見た本人(本犬)がキャンキャン騒ぐので掲載中止。

 この画像を見て、ESP32が鍵を握ってるなんて信じられます?。(複雑な処理は全てiMacですけど。)取得した画像の温度差がそのまま高低差で表現されます。

 実行させるには動画のフレームレートと解像度をできるだけ上げることが必須。

 元々は、WROOM02に表示機器をダイレクトに取り付けても、画像表示は実用レベルじゃないんじゃないか?という仮定のもと、LEPTONで読み取ったサーモグラフィー画像をWIFIとOSCを組み合わせて、iMaciPhoneに表示させてしまおうという発想でした。色々な条件が一致して、なんとかサーモグラフィーになりましたが、画像の荒さはしょうがないとして、スピードがいまいち。WROOM02の能力以外にも、私のソフト作成能力にも問題があるような....。

 そこで、今回は巷で噂の WROOM02の2倍は早いんじゃないかというESP32を使って、とりあえず今の私の実力でどんだけ早く画像が再現できるかも追求。

大まかな処理の流れは、

  1. LEPTON赤外線カメラから、SPIの垂れ流し信号をESP32で読み取る。
  2. 80x60の14bitグレースケール画像を256色すなわち8bitグレースケールに変更。ついでにセンサー温度、最高最低温度を摂氏に変換。
  3. 80個のグレースケールデータを1行ずつStringにして60回に分けてOSC送信
  4. ついでに読み取った温度もOSC送信。ここまではESP32で実行。
  5. MAC側OSCでデータを受け取り、グレースケールデータ60x80から317x237 に補間-->カラー化-->VBOで3D変換。
  6. VBO表示は自由に拡大縮小、回転できるが触ってるうちに場所がわからなくなるので、念のため読み取り画像の小さな表示もつけて....。

って感じです。今回はiPhoneでの画像再現ではなく、作成の簡単なiMacで動かしてみます。テストなのでOSC通信は、一方通行ESP32-->iMac だけにしました。

ESP32側

 以前WROOM02を使ったLEPTONの赤外線画像送信を試みました。今回は以前のカクカクスピードを改善する目的でESP32を採用。WROOM02のOSC送信プログラムがそのまま使えれば苦労しないのですが、そんな訳ありませんよね。

LEPTON+ESP32でのOSC通信を実現するには、以下の過程が必要です。

ESP32の入手

www.ebay.com

技適付き。ESP8266環境向上委員会 辻直弘さん情報 送料込み3,000円前後。7日で届きました。

色々情報がありますが、iMac上で以下のコマンドを入力するだけ。

mkdir -p ~/Documents/Arduino/hardware/espressif && \
cd ~/Documents/Arduino/hardware/espressif && \
git clone https://github.com/espressif/arduino-esp32.git esp32 && \
cd esp32/tools/ && \
python get.py

 参考:MacでESP32のLチカ(Arduino IDE版) - Qiita

  • ESP8266 OSC 通信ライブラリダウンロード及び修正

OSCライブラリは以下から、お礼を言いながらダウンロード。ARDUINOのliblalyフォルダに入れる。ESP32の場合、このままではエラーになるので、以下の2点を修正。(やはりすんなり実行できない)

 https://github.com/CNMAT/OSC

  • OSCData.h 94行目以下のようにコメントを入れる。 
 #endif
  //OSCData (int32_t);
  #ifndef ESP8266
OSCData (int);
  oscData.c 
  • OSCData.c 30行付近 6行についてコメントを入れるか、消す。
  /*

  OSCData::OSCData(int32_t i){
  error = OSC_OK;
  type = 'i';
  bytes = 4;
  data.i = i;
  }

  */

 

  • SPI他

 SPIは 以前のWROOM02専用の特殊ライブラリではなく、ESP32 ARDUINO IDEの標準ライブラリを使用。以前とコマンド内容が違うので、やはりLEPTONから出力される信号の同期を取るのが、最大の難関でしたが、いつもの様にトライアンドゴー。コンパイルを100回以上繰り返してやっと繋げることができました。結果は、WIFIで信号を流している割には速度が良好。スピード的に理想に近いRaspberry PI環境でのLEPTON再生動画と、あまり変わらないものになりました。LEPTONの画像データはせいぜい9FPS程度とのこと(トランジスタ技術12月号)前回WROOM02+iPhoneでは2FPSくらいなので、大幅にスピードアップしました。これはソース上で、各所に存在していたdelay待ち時間を最小にしても動いたことが大きな理由です。

 LEPTONサーモカメラは、温度計算やチップ制御を実行するために、さらにi2Cの接続が必要というめんどくさいセンサーなのですが、こちらの方は問題なく接続できました。

  • ピンの接続
             LEPTON           ESP32
CS -------------->D5
MOSI------------->D23
MISO------------->D19
CLK ------------->D18
GND ------------->GND
VIN ------------->3V3
SDA ------------->D21
SCL ------------->D22 
  • 今回のESP32側ソースは以下からダウンロードしてください。

                           id:TAKEsan の LEPTON-WROOM32TEST.ino

 たまにシステムダウンすることがありますが、このままの設定で1時間以上動くので許容範囲としました。頻繁にESP32がダウンする場合は、read_lepton_flame の最初の方に入れているdeleyの数値を調節する必要があります。

Mac 側Openframeworks

 前回までは画面のチラツキがあり、かなり不満でした。原因はESP32から送られる画像データが1行ずつなので、1行送られるたびに画像表示していたから。今回は60行分送られた時点で画像表示するよう改良したので、チラツキが全くなくなりました。

 チラツキさえなくなれば、VBOを使って画像を3D化(ポイントクラウド)できます。ただし、以前は2倍に補間して画像を比較的滑らかに表示してましたが、3D化する場合は画素数が不足します。今回は4倍に補間したデータを使いました。実験なので単純な平均値です。ofxCVを利用してバイキュービック補間すればベターですが、そこまでしなくても結果は見ての通りGoodでした。

今回作ったOpenFrameworksソースは以下からダウンロードしてください。 

 oscReceive-LEPTON.zip

VBOについてはOFの大御所。多摩美術大学「田所先生」の例題を応用させていただきました。

openFrameworks 3Dグラフィクス、OpenGL | yoppa org

当然ながら

 OFをインストールしたTX1でも動くわけで、ZEDステレオカメラと組み合わせたら距離と対象物の温度が同時に...。デープラーニングなんか使わなくとも人間と動物くらい簡単に認識できちゃうかも。 

f:id:TAKEsan:20170221132555p:plain

Jetson TX1で以前作ったZEDアプリと今回の3Dサーモグラフィーアプリを同時に実行しているところ。多分OFで組み合わせた場合マルチスレッド化可能。両者のフォーカスを合わせればどんなことができるんでしょうか?ワクワクしてきました。

                               では また。

NVIDIA TX1+OpenFremeworks+DIGITS でTensorRT をさらに加速させる。

メーカー側のお題みたいですが、

 今回はDIGITSで学習させたDetectNET学習済みデータが、TX1で応用可能かどうか確認してみることにしました。さらに、OpnFrameworks(以降OF)のofThreadでマルチスレッド化。ディープラーニング技術が現実的にTX1で簡単に実現可能かどうかもテストしてみました。

f:id:TAKEsan:20170203172051p:plain

実際に母艦環境でKITTIを学習させ(早い話、車の認識)、このデータを利用してTX1に接続したWebカメラで、iMac上の動画を読み取らせて、車を認識させた上にBox2Dでバウンディングパーティクルを車の中心から吹き出させています。60fps!!滑らか〜〜。

         

Movieで再現するとこんな感じ。Box2Dの吹き出すパーティクルについては、多摩美術大学の田所先生のソースを応用させていただきました。

まずDIGITSで学習させたDetectNETデータが、TX1で実行可能か?

 以前使用した学習済みデータは、Jetson-inferense をビルド時に自動的にダウンロードされたデータを使っていました。

github.com

が、現実的に母艦環境のDIGITで学習させたデータが利用できるんでしょうか?。以前も書いたように、「この人なんか怪しい」。GitHub上の質疑応答を見てもなんだかなーです。実際、作者本人以外ネット上で公開している方が存在していないみたいです。で、やってみました。もともとテストデータは人物の認識でした。今回はカメラで取り込んだ動画で、「車」の認識を実現させて見ます。

 まず、当然ですが学習させることから始めます。日本語環境ではこの方のブログがベスト。

soralab.space-ichikawa.com

 私の母艦環境はGTX1080+i7 6700Kなので、縮小データでなく実データで学習させて見ました。3.5時間程度必要。3.5時間といっても30エポックなので、GTX1080はそれなりにかなり早い(現実的なスピード)と思われます。そして車を認識しているかどうか確認してから、作成されたファイルをTX1にコピーします。必要なデータは3つで以下の通り。

f:id:TAKEsan:20170203141858p:plain

わかりにくいのですがデータの保存先がDIGIT上に表示されています(矢印部分) 。ソララボさんが主張している通りグラフが変です。

f:id:TAKEsan:20170203141937p:plain

必要なデータはdeploy.protitxtと、各エポックで作成されるスナップショットデータの一番最後と、

f:id:TAKEsan:20170203141934p:plain

           KITTI変換データのmean.binaryprotoファイルです。

さらに、deploy.prototxt の一番最後を消します。(どうやらPythonクラスはTensorRTでは実行できない模様)

f:id:TAKEsan:20170203141931p:plain

この3つを「car」とか名称をつけたフォルダにまとめて、この前のTX1上のOFプロジェクトのbinにコピー。

takesan.hatenablog.com

さらにプロジェクト中のsrc/ofApp.cppの最初の方2箇所を修正追加(赤部分)

#include "ofApp.h"

#include <include/cudaMappedMemory.h>

#include <include/cudaNormalize.h>

#include <include/detectNet.h>

#include <include/cudaRGB.h>

#include <include/cudaNormalize.h>

 

//標準では、PEDNET,PEDNET_MULTI,FACENETの指定可能。それぞれped-100multiped-500face-120に対応 binフォルダの中にリンクフォルダを入れておく

//リンクファイルは、jetson-inference/build/aarch64/bin に入ってる。

detectNet::NetworkType networkType = detectNet::PEDNET;

//他の学習済みデータを使う場合はCreateを次の用に変更

detectNet* net = detectNet::Create("car/deploy.prototxt.bak", "car/snapshot_iter_19140.caffemodel", "car/mean.binaryproto");

//Create("multiped-500/deploy.prototxt", "multiped-500/snapshot_iter_178000.caffemodel", "multiped-500/mean.binaryproto" );

//この場合はmultiped-500。必要なのは3つのファイル jetson-inference/detectNet.cpp 参照。後の2つの引数がデータ種類によって違うので注意。

//detectNet* net = detectNet::Create(networkType);

....................

 

 最初は時間がかかります(変換作業により3〜4分)が、2回目以降は簡単に実行できるようになります。自分で作成したデータの学習結果がTX1+OFで自由自在に応用できるようになります。が.........、カクカク画面が気に入らない。このままでは、本来のOF上画像処理を始めTX1のGPIOに接続した外部機器までもがカクカクになってしまう...。ってことで次の段階。

f:id:TAKEsan:20170203141927p:plain

TX1側のOFのプロジェクトの中身です。初回でmake -j4 make run すると、〇〇〇.caffemodel.tensorcasdheが作成されるため実行までに3〜4分必要。ターミナルにエラーが表示されていなければ正常に動いてます。ハングしたんじゃないかと心配になりますが...。一度作成されれば次回からはスーイスイ。

               

          

      全体のスピードは、TX1のクロックスピードを最大にしても8ps程度のカクカク動画。

で、マルチスレッド化!!

 どんなことかって言うと、2台のTX1があって、1方はカメラ画像のみ、もう1方は人物や車の認識をしているとして、これを1つのTX1で実行してしまうのと同じことを実現させるのと同じ。マルチスレッドと言うんだそうです。前回までは1スレッドのみの実行だったので、物体認識に時間を取られ、単純な画像表示までカクカクになってました。が、マルチスレッド化すると画像表示が本来のスピードに戻ります。有り余った時間(CPUはIntel Jouleより多少遅いですが、なんつったってTX1は本格的なGPUと、CPUを4つ持ってるんですからこれを最大限使ってやります)でOF本来の画像処理が可能。一方、物体認識用のスレッドは本来のスピードで認識し続けます。やっと認識した結果を、早い方のスレッドに渡してやります。ただし認識処理部分が極端に遅いとイマイチなんですが、今回はまーまーなんで、知らない人はおおおおーっと思うことでしょうね。こんなことは昔から「C」をかじってきた人なら、すぐ思い付くでしょうが、できると分かっていても敷居が高くてなかなか踏み込めません。立て続けにTX1がらみのソフトをかじってきて、できたらいいなーってことをやってみました。TensorRT側はGPUを使っているので、うまくマルチススレッド化できるのかどうか疑問が残りましたが、OFのアドオンofThreadを使ったら、割とあっけなく動いてしまいました。結果は次の動画。

                

今回のカメラデータは1280x720です。そこそこ大きな画面ですが、60fps出てるのが確認できます。肝心の車の認識ですが、どうでしょうか。ほぼリアルタイムなのがわかると思います。この例では高速道路上の車の認識なんですが、街中に入ると若干遅れぎみになります(相対スピードの問題)。

 開発環境がOpenFrameworksなんで、朝飯前なんです。こんなところにフレームワークに乗っかってプログラムを作る意味が出てきます。マルチスレッド化についてはWEB上で画像での比較が見つかりません(私の場合はですが)。2つの動画の比較で、感覚だけでも理解できると思います。認識はほとんどリアルタイムって感じでしょ。画像表示部分に関しては、単純にカメラ画像と認識した部分の図形を表示しているだけですから、まだまだ沢山の画像処理などを実行させても力が有り余ってます。今回のOFプロジェクトはここからダウンロードできます。

take-detct-thread_X.zip 直

 

コンパイル済み実行ファイルと、学習済みデータも入れときましたので、Jetson-inferenseがビルドできていれば動くはずなんですけど、どうでしょうか?。今回はDetectNet上で2クラス以上の物体についても認識可能(色分け可能)にしました。

 ちょっと話が違いますが、今回取り上げたJetson-inferense。TX1のGPUクロックを最大にしても、認識スピードに変化がありません(作者がjetson_clocks.shを実行しなさいと書いているにもかかわらず)。前に試したZEDライブラリは倍近く早くなったのに、不思議。GPUメモリに画像を転送しないと動かないということは、確実に認識エンジンとしてGPUを使ってるはず。っということはまだ改良の余地があるカモです。この辺りも非常にアヤシイ!!。もうしばらくバージョンアップの動向を追っていく必要がありそうです。

調子に乗って

 別スレッドで実行している「クルマ」の認識結果を利用して、ofxBox2Dを使ってパーティクルを動かして見たのが冒頭の画像です。Box2Dで制御されたCircleの動きが自然であることが確認できると思います。一見複雑そうな処理も簡単に実現できました。

 これで「母艦環境でのDIGITSを使った学習-->TX1を使った現場での応用」の基本環境と流れができちゃいました。夢見ていたディープラーニング応用がとても簡単に!!。どうでしょうか?夢中になっちゃいますよね。

f:id:TAKEsan:20170203141542j:plain

                               では また。

 

 

 

Jetson TX1 + OF + TensorRT でディープラーニング segmentation編

ヤッチマッター

 と言っても私のせいではありません。この記事の下書きを書いていたら突然飛んでしまいました。この頃OSX良くないですね。私のiMacでは、Bluetoothとか外部HDとかサファリとかが周期的に調子が悪くなります。使ってる側からすれば、ここまで来ればOSの進化なんかどうでもいいんです。「安定だけ!!」こんなことはどうでもいいでしょうから本題へ。

今回はこんなのです。

f:id:TAKEsan:20170122140304j:plain

         

認識中の動画です。Py Fastere RCNN 並みにカクカク画面ですが、認識中している物体の輪郭が、大雑把ながらも具体的に表示されます。今回は特に認識する対象物を確認しやすくするため、キーボードから選択可能とし、バッテン印で表示させるようにしました。この画像では対象が「車」です。後の方で対象物を変えてます。周りの景色で認識確率の度合いが変わってくるようです。

前回の続きで、

 今度はSegmentationです。前回のDetectnetはせいぜい認識する物体の対象が1つか2つでしたが、今回は20項目程度の認識が可能となります。過去に取り上げたPy Faster RCNNと方向性は似ていますが、それとは少しコンセプトが違い、認識した画像の輪郭を抽出しようという代物です。前回まで見逃してたのですが、jetson-inferrencehttps://github.com/dusty-nv/jetson-inferenceに入っていました。なぜ見逃したのか?-->解説に載っていなかっただけです。作者(多分NVIDIA社員)は動作が鈍いので自信がなかったのでしょうか?2ヶ月ぐらい前に追加されていたのですが、多分取説を書くのがめんどくさかったからだけなんででしょうね。

 jetson-inferrenceのビルド時に、自動的にダウンロードされる学習済みファイルは、道路上で主に見かける20種類のクラスを認識できます。車載カメラからの物体認識を想定しているのでしょう。クラスに対応したラベル(認識物体の名称)は以下の通りです。

        class 00  label 'void'

        class 01  label 'dynamic'

        class 02  label 'ground'

        class 03  label 'road'

        class 04  label 'sidewalk'

        class 05  label 'parking'

        class 06  label 'building'

        class 07  label 'wall'

        class 08  label 'fence'

        class 09  label 'guard rail'

        class 10  label 'bridge tunnel'

        class 11  label 'pole'

        class 12  label 'traffic light'

        class 13  label 'traffic sign'

        class 14  label 'vegetation'

        class 15  label 'terrain'

        class 16  label 'sky'

        class 17  label 'person'

        class 18  label 'car'

        class 19  label 'truck'

        class 20  label 'cycle'

クラスの中には当然人物も存在するので、試しにjetson-inferrenceに入っている写真で確認すると、

f:id:TAKEsan:20170122140449p:plain

標準で入っているsegnet-consoleアプリで人体を含む写真を認識させると、認識した部分が赤で表示されます。他のクラスは違う色で輪郭を囲んでいるのがわかると思います。ただ、これを実行するにはわざわざ作者が添付しているsegNet.batを実行しただけでは動かない。segNet.cppを確認する必要がありました。結局 ./segNet-console peds-006.png test.png fcn-alexnet-cityscapes-hd で動かした結果です。(最終はtest.png画像)

 こんな感じ。添付されている1980x1080ピクセル画像で、認識処理に0.6秒程度必要でした。赤で人物を認識してます。認識範囲がギザギザ=荒いですねー。TX1ではここら辺が限界なんでしょう。セグメンテーションモデルのサンプルアプリはこれだけ。写真しか認識できません。認識する対象物数が多いことから、動画にしたところで1fps強しかスピードがでないとは思いましたが、写真よりマシということで、OFで作ってみました。

前回で味をしめたので、

 簡単にできるんじゃないかって思ってましたが、やはり初心者がCUDAなんてとんでもないことだとつくづく思い知らされました。おかげで頭も体もガクガク。記憶が頻繁に飛んでしまうので、作成中に限界を感じてしまい挫折しそうでしたが、頑張ってみました。完璧に初老の症状です。が、できたものは、OpenFrameworks(以降OF)から見る限りとても簡素なソースになりました。動作はカクカクですが、TX1にインストールしたOFで動くので、ofTheadアドオンでマルチスレッド化すれば、認識画面の結果を待つ間、結果を元にモーターを動かすとか、i2Cに繋いだセンサー値を読み取るとか面白そうなことが、できそうです。

 作成中理解できたsegNet認識エンジンの構造は下図の通り。OFから操作できるのは、クラス番号配列だけにしました。単独クラスだけの認識も可能ですが、全体スピードにさほど違いがありません。なのでこれがベターかと勝手に判断。下図の最終段階で、「各々の確率で最大のクラス番号を出力」とありますが、この部分を修正すると認識率がもっと改善されるはずです(segnet.cpp中身。最大とは言え、90%以上とは限られないのですから、そのあたりのチェック方法が運命の分かれ道)。今回はライブラリソースsegnet.cppの中も修正したので、jetson-inferrenceの再コンパイルが必要です。

f:id:TAKEsan:20170122140630p:plain

セグメンテーションモデルとはどんなものか?

 は、この方のブログを確認してみて下さい。Py Faster RCNN との比較も載っています。

soralab.space-ichikawa.com

今回作ったソースは、

 下図のようなことができます。

f:id:TAKEsan:20170122140336j:plain

カメラから取り込んだ動画でも、写真から認識したものと同じような認識結果でした(iMacに表示した写真画像をカメラで取り込んでいる)。ただ、色分けだけでは認識している対象がなんだかわからないので、明確に判断できるようにしました。(画像ではperson=人々。認識しているところはバッテン印)

f:id:TAKEsan:20170122140414j:plain

 ここでは車を対象としています。(青のバッテン印。車は確実に認識するが、誤認識している部分あり)

 デープラーニングエンジン部分の処理が重く、取り込んだ画素数を上げてもさほどスピードに影響が出ないことから、カメラの画素数を1920x1080として認識精度を上げています。(せいぜい1.6〜1.8fpsのカクカク動画)

実行条件

  • JetPack2.3.0以降の64bit版がインストールしてあること。
  • Jetson-inferrenceをダウンロードしてビルドしてあること。/home/ubuntu に入れないとOFコンパイル時、リンクエラーが出るので注意
  • TX1にOpenframeworksがインストールしてあること。

    TX1には通常Openframeworksはインストールできません。インストールするには手順が必要です。最短で実行したい場合は以下の記事を参考に!!

    takesan.hatenablog.com

実行手順

  1. USBにWebCameraをつなぐ(Logicool製品が一番安心。できればC920以上)。
  2. プロジェクトsegNET.zipを解凍して中にあるtake-segをフォルダごとOF/apps/myAppsへ突っ込む。
  3. さらにsegnet.hsegnet.cppJetson-inferrenceの最上層に突っ込む(重ね書き)。
  4. Jetson-inferrence/build/aarch64/bin  の中の FCN-Alexnet-Cityscapes-HDFCN-Alexnet-SYNTHIA-Summer-HDフォルダへのリンクファイルをOF/apps/myapps/take-seg/binへ入れる。(既に解凍したファイルには同名のフォルダが入ってるので消してから)
  5. Jetson-inferrence/build/aarch64/include フォルダへのリンクファイルをOF/apps/myapps/take-seg/srcに入れる(既に解凍したファイルには同名のフォルダが入ってるので消してから)
  6. すでにビルドしているJetson-inferrence/buildに入り make clean --> cmake ..  --> make -j4  を実行。-->Jetson-inferrenceを再コンパイル
  7. includeリンクファイルの中で、修正が必要なファイルあり-->cudaUtility.h。最初の方の赤文字部分を追加。

    cudaUtility.h

    /*

     * http://github.com/dusty-nv/jetson-inference

     */

     

    #ifndef __CUDA_UTILITY_H_

    #define __CUDA_UTILITY_H_

     

     

    #include </usr/local/cuda-8.0/targets/aarch64-linux/include/cuda_runtime.h>

    #include </usr/local/cuda-8.0/targets/aarch64-linux/include/cuda.h>

    #include <stdio.h>

    #include <string.h>

  8. ZED SDKやOpenCV2.4.13をインストールしていない方は、segNET/config.make の中身の修正が必要です。一番最後に追記した「すいません」以降を確認してください。

  9. OF/apps/myapps/take-seg に移動して いつものようにmake -j4  make run で実行。

ソース内容

 はてなブログでは文字化けしちゃうんで、ダウンロードしてみてください。segNET.zip CUDAライブラリ使用部分は、前回より複雑な処理なのに逆に簡素になりました。(私の能力がアップしたか?! ん なわけねーよな。)

※2017/1/23 ダウンロードファイルが違っていました。Detect-RT.zipからsegNET.zipに修正しました。

※すいません!!解凍したフォルダ「segNET」の中にあるconfig.makeの中身はZED SDKへのリンクも入ってました。このままだとZEDを所有していない方は、リンクエラーになるのでDetect-RT/config.make の80行目 PROJECT_LDFLAGS= 部分を以下に変更してください。

PROJECT_LDFLAGS=-L/usr/lib/aarch64-linux-gnu/tegra -L/usr/local/cuda-8.0/lib64 -L/usr/local/lib -L/home/ubuntu/jetson-inference/build/aarch64/lib -rdynamic /home/ubuntu/jetson-inference/build/aarch64/lib/libjetson-inference.so -lX11 -lpthread -lGLEW -lGLU -lGL -ldl -lrt -lnvcaffe_parser -lnvinfer /usr/local/cuda-8.0/lib64/libcudart.so /usr/local/cuda-8.0/lib64/libnppc.so /usr/local/cuda-8.0/lib64/libnppi.so /usr/local/cuda-8.0/lib64/libnpps.so /usr/local/cuda-8.0/lib64/libcublas.so /usr/local/cuda-8.0/lib64/libcufft.so -ldl -lm -lpthread -lrt -Wl,-rpath,/usr/lib/aarch64-linux-gnu/tegra:/usr/local/lib:/usr/local/cuda-8.0/lib64:/home/ubuntu/jetson-inference/build/aarch64/lib

 

 

                                                    では、また。

 

Jetson TX1 + OF + TensorRT でディープラーニング

今回のお題の内容は、

 TX1にインストールしたOpenframeworks(以後OF)で、以前チラッと紹介したTensorRTを実現させようという試みです。やっとディープラーニングに戻りました。

         

今回の最終画像。TX1+OF+TensorRTで認識した人物をリアルタイムで表示している。前回のOpenCV+HOGと比べて認識率と反応が全く違う。すごい。さすが最新ディープラーニング技術!!

f:id:TAKEsan:20170117201633j:plain

左がTX1+OF+TensorRTで認識させたディスプレイ画面(緑の四角で認識した人物を特定してる)。iMacの人物画像と奥のテレビに映った「さんまさん」も認識してる。

 TensorRTはここに紹介されています。

github.com

 未だにTensorRTって分かってませんが、インストール中にCaffeライブラリをダウンロードしてるんで、多分Caffeの16bit版(例のrun test がうまくいかないやつ)を使ってるだけじゃないか?なんて、今思ってます。結果が良好なんで、使う側にとってはどうでも良いことですけど。

 この中で、Object Detection の学習済みデータを使い、TX1に接続したカメラ画像で、リアルタイムにいろいろ認識させてみるというアプリをOFで実現させてしまいした

 Object Detectionについては、この記事を見ると大体理解できると思います。

soralab.space-ichikawa.com

この方のブログに注目してるんですが、応援方法がわからない....。

 Object Detectionの学習は、非常に時間のかかることが分かると思いますが、今回は、Object Detectionの学習済みデータを利用して、実用的に使うみたいなコンセプト。TX1は、GPUに関して最新のものと比較すると完全に見劣りしますが、本体が非常に小さく、ほどほどのスピードなので、現場で使うには非常に実用的。メーカーが本来考えていたことが実現できたことになります。

Jetson-inferrenceのOF化について

 Jetson-inferrenceをインストールすると、数種類のアプリが実行できますが、この中でも実用的かつ一番面白いと思われるdetectnet-cameraOF化してみました。

このアプリの欠点と思われる部分は、

  • カメラ部分と表示部分にCUDAがらみの処理が多く、私ではちんぷんかんぷん。
  • 表示画像が逆なのに直す「すべ」が分からない(カメラとOpenGL部分の座標の違いか?)。こんな感じ!!。

        f:id:TAKEsan:20170117201706j:plain

    カメラは普通に設置してるのに、画像が逆さま。青い四角で人物を確実に認識してるが......。

  • このソース利用しようとしても、入出力が特殊なので応用が非常に難しい

 OFに移植なんて無理かなと思ってたのですが、ディープラーニングのエンジン部分がとても単純であることが判明。で、やっとできたので記事にしたいと思ったわけです。いつも書いてますがOF化によって、応用範囲がぐんと広がることが約束されます。この画面のMjpeg配信なんか簡単にできちゃいます。

 できたものは、本家アプリの場合6.1fpsに対して、同条件で今回は7.8fpsになりました。早くなったんです!!。早くなったのはなぜ? 感覚的に本家の方は、変換作業が多すぎるような気配があるのですが、この辺りかもしれません。でも私の作ったものの方が早いなんて、とっても嬉しくなります。ソースが短い(こんなにすごいことを実行しているのに....。)のでaddonにする必要もないと思いましたので、ofApp.cppに全部入れちゃいました。ただ、config.makeが特殊(リンクオプションをたくさん追加しているため)なので、ソースダウンロード可能にしときます。--->Detect-RT.zip

 今後このフォルダをコピーすれば、どんどん面白そうなものが作れそうです。感心するのは、全体のスピードは8ps前後で多少カクついていますが、カメラから画像を取り込んでから遅延がほとんどないこと。前回のOpenCV Hogは確実に1秒以上「間」を置いてからの表示なので、リアルタイムではありませんでした。また、今回1080x720と、そこそこ大きい画素数ですが、遅延がほとんどないんです(前回は640x390 HD720にすると6fpsくらいで遅延が3秒!!)これは実用的!!。

 注意点は、以前ビルドしたOpenCV2.4.13の関数を使うと実行エラーが出て動かなくなること。当初の狙いは、前回作ったZEDの深度測定と組み合わせようと思ったのですが、これは不可能のようです。どうやらコンパイラオプションのGLライブラリが競合するようです。検証をしていませんが、OFに標準で入ってるアドオン「ofxOpencv」は、リンクするライブラリが違うので競合しない可能性があります。

 実際の認識性能がどうか?なのですが、この前のOpenCV HOG 認識器の動画と比べれば、違いに気づくと思います。とにかく認識が安定してますし、一度に認識する数も比較になりません。断然良い!!。さすがディープラーニングの最新技術ですよね。ただし、結構誤認識してしまう欠点があります。問題は学習の仕方でしょうか?

 今回のソースを最後に付けます。Jetson-inferrenceをインストールすると、学習済みデータが自動ダウンロードされます。3種類存在するので、これを利用できます。顔認識、人物認識、人物とバッグの認識です。以前は、このフォルダの中のどのデータを利用するのかわからなかったのですが、今回はっきりしたので、最後に付けたソース中に、その辺りもコメントを入れてます。次は母艦のDIGITSでデータを作って、TX1で結果を実行させたいと思っています。尚、今回のモデルはmultiped-500です。昨年の暮れには夢だったことが実現できて幸せ!!。これからは、個人でディープラーニングを活用した実用レベルのソフトが作れそうです。

実行条件

  • JetPack2.3.0以降の64bit版がインストールしてあること。
  • Jetson-inferrenceをダウンロードしてビルドしてあること。/home/ubuntu に入れないとOFコンパイル時、リンクエラーが出るので注意
  • TX1にOpenframeworksがインストールしてあること。

TX1には通常Openframeworksはインストールできません。インストールするには手順が必要です。最短で実行したい場合は以下の記事を参考に!!

takesan.hatenablog.com

実行手順

  1. USBにWebCameraをつなぐ(Logicool製品が一番安心。できればC920以上)。
  2. プロジェクトDetect-RT.zipを解凍したらフォルダごとOF/apps/myAppsへ突っ込む。
  3. Jetson-inferrence/build/aarch64/bin  の中の facenet-120、multiped-500、ped-100フォルダへのリンクファイルをDetect-RT/binへ入れる。(既に解凍したファイルには同名のフォルダが入ってるので消してから)
  4. Jetson-inferrence/build/aarch64/include フォルダへのリンクファイルをDetect-RT/srcに入れる(既に解凍したファイルには同名のフォルダが入ってるので消してから)
  5. ZED SDKやOpenCV2.4.13をインストールしていない方は、Detect-RT/config.make の中身の修正が必要です。一番最後に追記した「すいません」以降を確認してください。
  6. includeリンクファイルの中で、修正が必要なファイルあり-->cudaUtility.h。最初の方の赤文字部分を追加。

    cudaUtility.h

    /*

     * http://github.com/dusty-nv/jetson-inference

     */

     

    #ifndef __CUDA_UTILITY_H_

    #define __CUDA_UTILITY_H_

     

     

    #include </usr/local/cuda-8.0/targets/aarch64-linux/include/cuda_runtime.h>

    #include </usr/local/cuda-8.0/targets/aarch64-linux/include/cuda.h>

    #include <stdio.h>

    #include <string.h>

  7. Detect-RT に移動して いつものようにmake -j4  make run で実行。

ソース内容

 はてなブログでは文字化けしちゃうんで、ダウンロードしてみてください。Detect-RT.zip (複数のクラスがあった場合、認識した部分を表す四角形の色分けをしてません)

※すいません!!解凍したフォルダ「Detect-RT」の中にあるconfig.makeの中身はZED SDKへのリンクも入ってました。このままだとZEDを所有していない方は、リンクエラーになるのでDetect-RT/config.make80行目 PROJECT_LDFLAGS= 部分を以下に変更してください。)

PROJECT_LDFLAGS=-L/usr/lib/aarch64-linux-gnu/tegra -L/usr/local/cuda-8.0/lib64 -L/usr/local/lib -L/home/ubuntu/jetson-inference/build/aarch64/lib -rdynamic /home/ubuntu/jetson-inference/build/aarch64/lib/libjetson-inference.so -lX11 -lpthread -lGLEW -lGLU -lGL -ldl -lrt -lnvcaffe_parser -lnvinfer /usr/local/cuda-8.0/lib64/libcudart.so /usr/local/cuda-8.0/lib64/libnppc.so /usr/local/cuda-8.0/lib64/libnppi.so /usr/local/cuda-8.0/lib64/libnpps.so /usr/local/cuda-8.0/lib64/libcublas.so /usr/local/cuda-8.0/lib64/libcufft.so -ldl -lm -lpthread -lrt -Wl,-rpath,/usr/lib/aarch64-linux-gnu/tegra:/usr/local/lib:/usr/local/cuda-8.0/lib64:/home/ubuntu/jetson-inference/build/aarch64/lib

 

                                           では、また。

Jetson TX1+Openframeworks + ZED で人物認識しながら距離を測定する。

今回の表題は、

 何が何だかわからないと思いますが、次の動画と写真を見て下さい。

          

f:id:TAKEsan:20170111212738j:plain

左がZEDの左側のカメラから取り出した画面。右側がその画像の深度(グレースケールからカラーマップに変えてみた)。キーボードでHキーを打ち込むと、左下にHOG!!が表示されて、人物認識とカメラから人物までの距離測定のはじまりはじまりー。

f:id:TAKEsan:20170111212731p:plain

試しにiMacに表示させた人物写真をZEDに見せると.....認識している!!(距離が0.6m以下だと距離は表示されません)前回と比べるとスピードも内容も格段に進化しました。

 私の姿を認識して、距離を表示してます。TX1上のOpenframeworks、GPU を利用したHogOpenCVの人物認識職別器)で人を検出しながら、ZEDステレオカメラで人物までの距離を認識させるという、何かに役立つような役立たないような実験結果です。

 OpenCVHOGは、GPUを使ってもかなり重い処理。これにZEDの深度認識を組み合わせるのですから、TX1では、持ち前のGPUを最大限使っても悲鳴を上げそう。いつものようにかなり苦労して、やっと13fpsくらいまでになりました。13fpsで遅いって?。いえいえ。この前Intel JouleOpenCL(GPU)を利用して実行した結果が4.4fpsintel i7 6700K CPUオンリー環境で9fps前後ですから、そのスピードに驚嘆!!。しかも対象物までの距離なんか認識させないでですよー。

前回は、

 ofxKuZedアドオンを利用して、TX1上のOpenframeworksでZED カメラを動かして見ました。でも、かなり遅い。ZED SDK に入っているOpenCVサンプルの半分くらいのスピードでした。「面白くない」。原因がZED SDKマトリックスデータをいちいちOpenframeworksのピクセルデータに変換しているからとは分かっていたのですが、ソースを解析するには、このアドオン、あまりにも複雑過ぎます。そこで、もっと簡単なZEDアドオンを探して見ました。それがofxZED https://github.com/andsynchrony/ofxZEDofxKuZEDの作者が参考にしたアドオンだそうです。但し、最新版のZED SDKでは全く動きません。本人が正誤表を作っていますが、これでもダメ。さらに私なりに修正してやっと動きましたが、やはりピクセルデータ変換が災いしてofxKuZedより多少早い程度でした。

 今回はOpenCV のcv::Mat とofPixels間のポインタ受け渡しを利用して、高速にデータ変換が可能なことが分かったopenFrameworksでOpenCV3を使う - Qiitaので、これを利用。ofxZEDアドオンを大幅に変更したものを作りました。

結果は以下の通りです。

f:id:TAKEsan:20170111212813j:plain

ofxKuZed改良版。VGA(672x376)、深度は詳細モード(下に半分写っている白黒画面)で16.49fpsでしたが...。

f:id:TAKEsan:20170111212848j:plain

ofxZED改良版。ofxKuZedと同条件の上に、深度は白黒ではなくOpenCVのカラーマップでマッピングしてかなり負担があるにもかかわらず(3fpsくらい落ちる)、なんと約29fps出てます!!。深度画像なんか必要ない場合は、60fps超えで、HD720(1080x720)の場合は3020fps出ますぞー。

ofxZED改良版について。

 いちいちプログラムを説明してもなんだかなーですので、以下からダウンロード可能にしときました。

   ofxZED.zip

 興味のある方は、中のコメントを確認してみてください(私の理解できている範囲で結構詳細に書いときました)。コンパイル中ofConstants.hやEigenがらみのエラーが出る時は、前回の記事を参考に修正が必要です。

TX1の環境ですが。

  • JetPac 2.3.0以上がインストールしてあること。
  • Openframeworksがインストールしてあること。(以前の記事参照、TX1専用のOF-->ダウンロード可能にしときました!!
  • TX1には通常Openframeworksはインストールできません。インストールするには手順が必要です。最短で実行したい場合は以下の記事を参考に!!

takesan.hatenablog.com

  • Opencv2.4.13以上がインストールしてあること。(以前の記事参照)
  • ZED SDK 1.2.0がインストールしてあること。(以前の記事参照)2017/5/12現在ZED SDKが 2.0になってここで紹介しているプログラムは動きません。修正するつもりですが、バージョンを1.2.0に下げてインストールしてください。
  • ZED ステレオカメラが手元にあること。(当然!!)

※TX1以外のUbuntuマシンでもこのまま動くと思うが未確認。

 ダウンロードしたら解凍して、ofxZEDフォルダをTX1にインストールしたOpenframeworksの中のaddonsフォルダに入れるだけです。コピーが終わったら、ofxZED-->exampleに入って make -j4   でビルド。その後make run で実行です。

 今回は、動くだけです。精度をあまり重視していないので、ZEDのキャリブレーションファイル等は読み込んでいません。

 ofxZED-->srcの中にリンクフォルダzedが存在します。これはZED SDKの中にあるincludeに存在するzedフォルダへのリンクです。このままで良いと思いますがビルド中リンクエラーが出るときは確認して下さい。

HogDescriptorについて。

 OpenCVのHogDescriptorは、細部係数の調整が必要です。調整方法は以下を参考にさせていただきました。

OpenCVとVisual C++による画像処理と認識(13A)----- HOGDescriptorとSVMで人(歩行者)を検出する ----- -----

 この記事中で、検出ウインドウサイズ32x64はOpenCV2.4.13には存在しません。結果的に64x128が一番無難でした。記事の中ではあまり重視していませんがHOGDescriptor::detectMultiScale関数中のscaleの変更は、認識率やスピードの点で、かなり重要でした。参考ソースはCPUだけで実行していますが、今回はGPUライブラリを使っています。

やはり

 Hogは、py-faster-runやCaffeのObjectDetectionと比較すると、認識率ではかなりの開き(背景によって認識率が下がる)があります。次はこれらとZEDの組み合わせでしょうか?どうすればいいんでしょう。誰か教えて。

 

Jetson TX1 + Openframeworks + ofxkuzed で Zedステレオカメラの実験。

前回の記事で

 Jetson TX1にOpenframeworksを動かす環境ができました。どんどん面白い環境ができつつありますが、今回はZedステレオカメラを動かしてみます。この種のステレオカメラとしては、昨今話題になっているIntelのリアルセンスカメが存在します。これはKinectと同じように赤外線センサーで距離を認識するようなので、対象物が周囲と同じ温度になると「多分」距離を認識しなくなります。つまり、炎天下など、外部ではあまり役に立たないことになります。今回のZedステレオカメラは光学式なので、内外部共、周囲の温度の影響は受けませんが、暗闇では当然使い物になりません。両者とも一長一短。せっかくTX1とZEDを持ってるので、認識画像範囲の任意の点で、カメラからの距離を表示させるプログラムをOpenframeworksを使って作って見ました。

※TX1には通常Openframeworksはインストールできません。インストールするには手順が必要です。今まで成功した方はいないと思いますので、最短で実行したい場合は前回の記事を参考に!!

takesan.hatenablog.com

f:id:TAKEsan:20161226215458j:plain

                    今回の機器構成

f:id:TAKEsan:20161226224013j:plain

中央付近をマウスで指定してカメラからの距離を表示させているところ(赤い点と緑の距離)。720pで11fpsくらいです。VGA(672x376)に落とすと18fpsくらいにスピードが上がるので、今回の目標ほぼ達成。

         

 実際に距離を認識している動画。これはカメラ解像度が720p(1080x720)で距離を測定してます。カメラからの距離を確実に判別しているのがわかると思います。

 このZED、基本は2つのカメラを同時に動かして、左右画像を1つの画面に合成して出力しているだけなんです。OpenCVでもステレオカメラで画像深度を測定する例題があります。どうやらフォローするソフトが要なんですね。実行ライブラリはZED SDKをダウンロードすることで手に入りますが、ソースは公開していないようです。まー当然と言えば当然でしょうけど。

 ここの会社が公開しているサンプルとライブラリは、前にも紹介したように、なかなかなんですが、これをOpenframeworksに移植した熱意のある人がいます。「OfxkuZed」。https://github.com/kuflex/ofxKuZed

でも、このaddonは、Windows環境のOpenframeworksしかサポートしていません。Linuxの場合は自分でやってくださいですって。仕方ないので挑戦して見ました。結果的にリンクファイルオプションをどう追加するかだけの問題でした。

 まずZED SDKをダウンロードして、Examplesをビルドします。前バージョンではうまくコンパイルできなかったのですが、V1.2.0になってうまく行くようになりました。で、サンプルの中から、/usr/local/zed/sample/gpu/ogl-->の中にあるどちらかをコンパイルします(mkdir build --> cd build --> cmake .. --> makeの順で実行)。ビルドが成功したら(ここではopenGL_gpu_interropコンパイルした場合)、

/usr/local/zed/sample/gpu/ogl/openGL_gpu_interrop/build/CMakeFiles/ZED_openGL_gpu_interop.dir/link.txtファイル(まさに自分の環境に合ったリンクオプション!!)が、作成されるので、このデータをOpenframeworks環境のプロジェクトフォルダに入っているconfig,makeの中に追加してやります。この方法を使うと、自分の環境によってリンクファイルが自動でカスタマイズされるので超簡単。この前のOpenframeworksのインストールと同じように、真面目に働いているスクリプトが作り出すデータをぶんどっちゃおうという安易な発想です。

 試しにOfxkuZedのお試しサンプルzedExampleの中に入っているconfig.makeを以下に修正。中間付近の PROJECT_LDFLAGS= 以降が該当リンク部分です。多分このままでコンパイルできますが、できない場合は上記ZED SDKのexampleをコンパイルしてlink.txtの中身をコピーして見てください。一応変更したaddonと今回試して見た距離測定プログラムをダウンロード可能にしときます。一今後ZEDを使ったアプリを作成する場合は、このフォルダ(zedExample)をコピーすればOK。

ofxKuZed.zip 直

以下OfxkuZed-->zedExample-->config.make の中身

赤文字部分を追加する。

################################################################################

# CONFIGURE PROJECT MAKEFILE (optional)

#    This file is where we make project specific configurations.

################################################################################

  

################################################################################

# OF ROOT

#    The location of your root openFrameworks installation

#          (default) OF_ROOT = ../../..  

################################################################################

# OF_ROOT = ../../..

  

################################################################################

# PROJECT ROOT

#    The location of the project - a starting place for searching for files

#          (default) PROJECT_ROOT = . (this directory)

#      

################################################################################

# PROJECT_ROOT = .

  

################################################################################

# PROJECT SPECIFIC CHECKS

#    This is a project defined section to create internal makefile flags to  

#    conditionally enable or disable the addition of various features within  

#    this makefile.   For instance, if you want to make changes based on whether

#    GTK is installed, one might test that here and create a variable to check.  

################################################################################

# None

  

################################################################################

# PROJECT EXTERNAL SOURCE PATHS

#    These are fully qualified paths that are not within the PROJECT_ROOT folder.

#    Like source folders in the PROJECT_ROOT, these paths are subject to  

#    exlclusion via the PROJECT_EXLCUSIONS list.

#

#       (default) PROJECT_EXTERNAL_SOURCE_PATHS = (blank)  

#

#    Note: Leave a leading space when adding list items with the += operator

################################################################################

# PROJECT_EXTERNAL_SOURCE_PATHS =  

  

################################################################################

# PROJECT EXCLUSIONS

#    These makefiles assume that all folders in your current project directory  

#    and any listed in the PROJECT_EXTERNAL_SOURCH_PATHS are are valid locations

#    to look for source code. The any folders or files that match any of the  

#    items in the PROJECT_EXCLUSIONS list below will be ignored.

#

#    Each item in the PROJECT_EXCLUSIONS list will be treated as a complete  

#    string unless teh user adds a wildcard (%) operator to match subdirectories.

#    GNU make only allows one wildcard for matching.   The second wildcard (%) is

#    treated literally.

#

#         (default) PROJECT_EXCLUSIONS = (blank)

#

# Will automatically exclude the following:

#

# $(PROJECT_ROOT)/bin%

# $(PROJECT_ROOT)/obj%

# $(PROJECT_ROOT)/%.xcodeproj

#

#    Note: Leave a leading space when adding list items with the += operator

################################################################################

# PROJECT_EXCLUSIONS =

  

################################################################################

# PROJECT LINKER FLAGS

# These flags will be sent to the linker when compiling the executable.

#

# (default) PROJECT_LDFLAGS = -Wl,-rpath=./libs

#

#    Note: Leave a leading space when adding list items with the += operator

#

# Currently, shared libraries that are needed are copied to the  

# $(PROJECT_ROOT)/bin/libs directory.   The following LDFLAGS tell the linker to

# add a runtime path to search for those shared libraries, since they aren't  

# incorporated directly into the final executable application binary.

################################################################################

# PROJECT_LDFLAGS=-Wl,-rpath=./libs

PROJECT_LDFLAGS=-L/usr/lib/aarch64-linux-gnu/tegra   -L/usr/local/zed/lib   -L/usr/local/cuda-8.0/lib64   -L/usr/local/lib -rdynamic /usr/local/zed/lib/libsl_zed.so /usr/local/zed/lib/libsl_depthcore.so /usr/local/zed/lib/libsl_calibration.so /usr/local/zed/lib/libsl_tracking.so /usr/local/zed/lib/libsl_disparityFusion.so /usr/local/zed/lib/libsl_svorw.so /usr/local/zed/lib/libcudpp.so /usr/local/zed/lib/libcudpp_hash.so -lX11 -lpthread -lGLEW -lGLU -lGL /usr/local/lib/libopencv_videostab.so.2.4.13 /usr/local/lib/libopencv_ts.a /usr/local/lib/libopencv_superres.so.2.4.13 /usr/local/lib/libopencv_stitching.so.2.4.13 /usr/local/lib/libopencv_contrib.so.2.4.13 -lglut -lXmu -lXi /usr/local/cuda-8.0/lib64/libcudart.so /usr/local/cuda-8.0/lib64/libnppi.so /usr/local/cuda-8.0/lib64/libnpps.so -lGLU -lGL /usr/local/lib/libopencv_nonfree.so.2.4.13 /usr/local/lib/libopencv_ocl.so.2.4.13 /usr/local/lib/libopencv_gpu.so.2.4.13 /usr/local/lib/libopencv_photo.so.2.4.13 /usr/local/lib/libopencv_objdetect.so.2.4.13 /usr/local/lib/libopencv_legacy.so.2.4.13 /usr/local/lib/libopencv_video.so.2.4.13 /usr/local/lib/libopencv_ml.so.2.4.13 /usr/local/lib/libopencv_calib3d.so.2.4.13 /usr/local/lib/libopencv_features2d.so.2.4.13 /usr/local/lib/libopencv_highgui.so.2.4.13 /usr/local/lib/libopencv_imgproc.so.2.4.13 /usr/local/lib/libopencv_flann.so.2.4.13 /usr/local/lib/libopencv_core.so.2.4.13 /usr/local/cuda-8.0/lib64/libcudart.so /usr/local/cuda-8.0/lib64/libnppc.so /usr/local/cuda-8.0/lib64/libnppi.so /usr/local/cuda-8.0/lib64/libnpps.so /usr/local/cuda-8.0/lib64/libcublas.so /usr/local/cuda-8.0/lib64/libcufft.so -ldl -lm -lpthread -lrt -Wl,-rpath,/usr/lib/aarch64-linux-gnu/tegra:/usr/local/zed/lib:/usr/local/lib:/usr/local/cuda-8.0/lib64

  

################################################################################

# PROJECT DEFINES

#    Create a space-delimited list of DEFINES. The list will be converted into  

#    CFLAGS with the "-D" flag later in the makefile.

#

# (default) PROJECT_DEFINES = (blank)

#

#    Note: Leave a leading space when adding list items with the += operator

################################################################################

# PROJECT_DEFINES =  

  

################################################################################

# PROJECT CFLAGS

#    This is a list of fully qualified CFLAGS required when compiling for this  

#    project.   These CFLAGS will be used IN ADDITION TO the PLATFORM_CFLAGS  

#    defined in your platform specific core configuration files. These flags are

#    presented to the compiler BEFORE the PROJECT_OPTIMIZATION_CFLAGS below.  

#

# (default) PROJECT_CFLAGS = (blank)

#

#    Note: Before adding PROJECT_CFLAGS, note that the PLATFORM_CFLAGS defined in  

#    your platform specific configuration file will be applied by default and  

#    further flags here may not be needed.

#

#    Note: Leave a leading space when adding list items with the += operator

################################################################################

# PROJECT_CFLAGS =  

  

################################################################################

# PROJECT OPTIMIZATION CFLAGS

#    These are lists of CFLAGS that are target-specific.   While any flags could  

#    be conditionally added, they are usually limited to optimization flags.  

#    These flags are added BEFORE the PROJECT_CFLAGS.

#

#    PROJECT_OPTIMIZATION_CFLAGS_RELEASE flags are only applied to RELEASE targets.

#

# (default) PROJECT_OPTIMIZATION_CFLAGS_RELEASE = (blank)

#

#    PROJECT_OPTIMIZATION_CFLAGS_DEBUG flags are only applied to DEBUG targets.

#

# (default) PROJECT_OPTIMIZATION_CFLAGS_DEBUG = (blank)

#

#    Note: Before adding PROJECT_OPTIMIZATION_CFLAGS, please note that the  

#    PLATFORM_OPTIMIZATION_CFLAGS defined in your platform specific configuration  

#    file will be applied by default and further optimization flags here may not  

#    be needed.

#

#    Note: Leave a leading space when adding list items with the += operator

################################################################################

# PROJECT_OPTIMIZATION_CFLAGS_RELEASE =  

# PROJECT_OPTIMIZATION_CFLAGS_DEBUG =  

  

################################################################################

# PROJECT COMPILERS

#    Custom compilers can be set for CC and CXX

# (default) PROJECT_CXX = (blank)

# (default) PROJECT_CC = (blank)

#    Note: Leave a leading space when adding list items with the += operator

################################################################################

# PROJECT_CXX =  

# PROJECT_CC =

 

2017/1/12追記:それから、ofConstants.h にバグがあって、コンパイルエラーになります。これは随分前から指摘があって、まだ修正されていないようです。

Using Eigen library with Makefile (or Eclipse) - linux - openFrameworksに対策が記載されています。

f:id:TAKEsan:20170112135938p:plain

Openframeworksのディレクトリに行き、libs/openFrameworks/utils/ofConstants.hの中身185行目付近に(上図参照)

#ifdef Success

    #undef Success

#endif

を追加します。この後ofxKuZed-->zedExampleに行って make -j4    make run で今回の距離測定アプリの実行確認ができます。

2017/1/27追記:Camera.hpp で include error が出た場合は、/usr/local/zed/inclede/zed/Camera.hpp の最初の方4行について下記のように(赤字部分)自分の環境に合わせて絶対パスを書き込んでください。多分このように直せばOK。

#ifndef CAMERA_HPP

#define CAMERA_HPP

 

#include "zed/Mat.hpp"

#include "zed/utils/GlobalDefine.hpp"

#include </usr/local/cuda-8.0/include/cuda.h>

#include </usr/include/eigen3/Eigen/Core>

#include </usr/include/eigen3/Eigen/Eigen>

#include </usr/local/include/opencv2/opencv.hpp>

 ofxKuZedに入っている標準サンプルを実行してみると....。

 

       

      サンプルプログラムをそのまま実行720pで6fps程度しかスピードが出ません。

 TX1では遅い!!。が、ちゃんと動いてます。 ZED SDKのサンプルと比べるとOpenframeworksの実行画像に変換する手間がある分、スピードは明確に落ちているようです。でも機能を絞ればTX1でも十分に実用スピードになります。何と言ってもOpenframeworks上でのZED稼働により応用範囲が飛躍的に高まりますので、実験には十分な性能です。試しに720pからVGAに変更するとこうなります。

         

カメラ読み取り画像をVGA(672x376)に落とすと11fpsくらいに上がります。さらに不要な処理を削除すれば最大17fps程度にスピードアップ!!

 ZED SDKのExampleは一般受けを狙い3Dで立体化させて「わーっ」と言わせるものが大半ですが、この機器の一押しは画像深度ですから、使う側にとっては、カメラ画像の指定した部分が、カメラからどのくらいの距離か確認できればOKだと思います。一般的な距離センサーで測定できるのは狙った一点だけです。広範囲の測点を同時に計測するのは不可能。ZEDの価値は、その測点での圧倒的な優位性を如何にして利用するかだと、個人的には思ってます。できたのが冒頭の画像です。見た目は単純ですが、これを距離センサーで実現しようとすれば、到底不可能であることが経験者なら理解できると思うんですが。どうでしょうか?。ofxKuZedアドオンのGrayScale関数を利用してるので、0.6〜20mの範囲256段階での距離測定になります。測定上限は20m。上限を2.55mにすると精度は10mmになります(上限20mの場合、精度は78mm)。上限の範囲はキーボードから'0'、'9'を入力することで変更可能です。

 次回はなんと倍くらいにスピードアップ!!。画像中の人物を見つけ出して、その人物までの距離を測定させてみました。

takesan.hatenablog.com

 

                              では、また。

 

Jetson TX1 で Openframeworks 動いた。

諦めかけてたんですよね。

 そもそもTX1のアーキテクチャであるaarch64では、現状Openframeworksのインストールが不可能です。x86-64版でもarm7l版でも......。CPUが違うのだからしょうがない。何回も挑戦しているんですけど全くダメでした。でも、arm7l版を使って、プレビルドライブラリを再コンパイルすりゃー動くんじゃないかって想定のもと、ここ1週間でなんとかなりました。今後Pi3のOSが64bit版にならない限り、Openframeworksのaarc64標準版は発表されないような気がします。で、誰もやってないでしょうから、世界で初めてのインストール成功例だったりして.....。

※2017/1/12:TX1専用のOpenframeworksをアップロードできるようにしました。アップロードされる方は最後の方を確認して下さい。

f:id:TAKEsan:20161219211051j:plain

 鍵を握っているのは、poco、kiss、、tess2、glfw3と呼ばれる4つのライブラリ群と、4つのファイル

config.linuxarmv7l.default.mk、ostype.sh、ofAppGLFWWindow.cpp、config.shared.mk

でした。幸いOpenframeworks内部に、ライブラリ群をインストールするためのapothecaryと呼ばれるスクリプトが存在しているので、再インストールが可能です。が、その都度本来のaarch64をlinuxarmv7lやlinux64に名称を変更して実行させる必要があります。つまり実直なスクリプトを騙してarrch64版をインストールしちゃうという悪どい方法を使います。ファイルに関しては要所を変更すればOK。

 サンプルを動かしたら、なんと実行スピードはiMacと同等!!、逆にiMacより大巾に早いものがいくつかありました。今の所キー入力が難点。大文字のアルファベットと矢印キーだけしか使えません。直ったら紹介しますが、バイナリコードアプリで、TX1がCore i7 3.4GHz+Nvidia GPUが搭載されたiMacに勝つなんて驚くべきことですよね。

        

左がTX1、右がiMacの画面です。Openframeworksのサンプルを同時に走らせているところ。一番時間の必要な画像で、TX1が93fpsiMacが60fps出てます。ちなみにJouleは41fpsくらいです。TX1異常に早い。(iMacが古いといってもCore i7 3.4GHz GPUはGTX675ですよ!!)。Openframeworksには、フレームレートを変更する関数が存在しますが、ここを60fpsに指定するとちゃんと上限が60fpsになるので少し不思議なところ-->スピードリミッター的な部分が外れてしまったのか?

        

   ofxCVというOpenframeworks用のOpenCVアドオンを使って顔認識をさせてます。これも早い。

        

ofxBOX2Dというアドオンのサンプルを実行してます。こんなに早いのは経験無い。なんで早いんだろう? TX1専用のlibGL.soライブラリが相当最適化されている模様。

 前回Intel JouleでもOpenframeworksを動かしましたけれども、画像系の実行スピードは雲泥の差です。Jouleと比較してCPU能力の若干劣るTX1でも、内蔵されているGPU能力の優位性で、こんなにも差が出るなんてすごい。OpenframeworksのZEDステレオカメラアドオンがあり、かなり簡単に画像深度を利用したアプリケーションが作れるみたいなので、今後挑戦してみます。

 TX1に載せたOpenframeworksで、GPIOもMjpeg画像配信も、OSC通信も、ブラウザを介した制御も、高速で簡単に実現できるんです。これは使わない手はない!!。さらに、この前記事にしたTensorRTを使った学習済みディープラーニングライブラリと組み合わせることが実現できたら、Nividiaの難解なCameraライブラリや、画像表示ライブラリを使わなくて済むので、開発が10歩くらい進んでしまいます。

 ※この記事を書いてから1.5ヶ月後。本当に10歩ぐらい進んでしまいました。還暦過ぎて仕事の分野が違っても、ワクワクすればなんとかなるもんですね。

takesan.hatenablog.com

 Openframeworks インストール手順

 インストール手順はピンクの部分です。ピンク文字部分を順番に実行します。途中ファイル内容修正部分は青文字で記述してあります。私のTX1内部eMMCにインストールしているjetpac2.3.0には、何も手をつけていないので、再度インストール確認して見ましたが、下記の方法で問題なく動いています。

● インストールするOS確認

uname -a

表示内容は、

Linux tegra-ubuntu 3.10.96-tegra #1 SMP PREEMPT Wed Sep 28 17:51:08 PDT 2016 aarch64 aarch64 aarch64 GNU/Linux
Jetpack 2.3.0 です。(最新の2.3.1でも可能だと思う)
● 次に、G++のバージョン確認_

g++ --version

表示内容は、

   g++ (Ubuntu/Linaro 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609

最新のJetpacをインストールしていれば特に問題ありません。

● ホームへ移動
cd     でホームへ移動して
Openframeworksダウンロードページからdownload | openFrameworkslinux armv7版をダウンロードして解凍。フォルダ名称をof_v0.9.8とします。(なんでも良いが便宜上。以下そのまま実行できるので)ダウンロードしてフォルダ名称を変更したら、

sudo apt install cmake
nano ~/of_v0.9.8/scripts/apothecary/ostype.sh でostype.shの24行目を以下に変更
  【修正前】elif [ "$ARCH" == "armv7l" ] ; then
  【修正後】elif [ "$ARCH" == "aarch64" ] ; then  にする aarch64に変更

● Openframeworksで使用するライブラリ群のインストール
cd ~/of_v0.9.8/scripts/linux/ubuntu/
sudo ./install_dependencies.sh
アップグレードがあった場合はyでupgradeする。Openframeworksの依存ファイルもyでインストールする。
最後にEnterを押すとpocoインストールとなり、すぐError表示が出てStopするが、気にしない。
● Openframeworks付属のライブラリインストーラapothecaryでpoco、kiss、tess2をaarch64形式でインストール
sudo apt install curl
cd ~/of_v0.9.8/scripts/apothecary
sudo ./apothecary update poco      ——>ビルドに20分以上必要
sudo ./apothecary update kiss
nano ~/of_v0.9.8/scripts/apothecary/ostype.sh  でostype.shの25行目を以下に変更
  【修正前】OS="linuxarmv7l"
  【修正後】OS="linux64" にする。(騙す!!)
sudo ./apothecary update formulas/tess2/tess2.sh   エラーになるが気にしない。
cd ~/of_v0.9.8/scripts/apothecary/build/tess2/Build  ここに行って
make              サンプルファイルmake errorとなるが気にしない。
nano ~/of_v0.9.8/scripts/apothecary/ostype.sh  

でまたまたostype.shの25行目を以下に変更
  【修正前】 OS="linux64"
  【修正後】 OS="linuxarmv7l"   にする。(またまた騙す!!)
今度はpoco、kiss、tess2 のビルドでできた 拡張子.aファイル群(静的ライブラリ)を所定ディレクトリにコピー
cp libtess2.a ../../../../../libs/tess2/lib/linuxarmv7l/
cd ../..                                                –---> apothecary/buildへ移動
cp kiss/libkiss.a ../../../libs/kiss/lib/linuxarmv7l/
cp poco/lib/Linux/aarch64/*.a ../../../libs/poco/lib/linuxarmv7l/
● 入出力関連のライブラリglfw3をaarch64用にビルドして所定ディレクトリにコピー。
cd ~/of_v0.9.8/libs/glfw/lib/linuxarmv7l
git clone https://github.com/glfw/glfw.git
cd glfw
mkdir build
cd build
cmake ..
make -j4
sudo make install
cp src/libglfw3.a ../../ibglfw3.a

● Openframeworksのアプリケーションコンパイルに必要な          

        config.linuxarmv7l.default.mkの内容で全て修正(重ね書き)。
nano of_v0.9.8/libs/openFrameworksCompiled/project/linuxarmv7l/config.linuxarmv7l.default.mk
以下修正内容

###############################################################################
# CONFIGURE CORE PLATFORM MAKEFILE
# This file is where we make platform and architecture specific
# configurations. This file can be specified for a generic architecture or can
# be defined as variants. For instance, normally this file will be located in
# a platform specific subpath such as
#
# $(OF_ROOT)/libs/openFrameworksComplied/linux64
#
# This file will then be a generic platform file like:
#
# configure.linux64.default.make
#
# Or it can specify a specific platform variant like:
#
# configure.linuxarmv6l.raspberrypi.make
#
################################################################################

################################################################################
# include common rules
#
# all linux systems have several rules in common so most of them are included
# from the following file
#
################################################################################

include $(OF_SHARED_MAKEFILES_PATH)/config.linux.common.mk

################################################################################
# PLATFORM CFLAGS
# This is a list of fully qualified CFLAGS required when compiling for this
# platform. These flags will always be added when compiling a project or the
# core library. These flags are presented to the compiler AFTER the
# PLATFORM_OPTIMIZATION_CFLAGS below.
#
# Note: Leave a leading space when adding list items with the += operator
################################################################################
#PLATFORM_CORE_EXCLUSIONS += $(OF_LIBS_PATH)/openFrameworks/app/ofAppEGLWindow.cpp
#PLATFORM_CFLAGS = -Wall -std=c++11
PLATFORM_CFLAGS = -Wall -std=c++14 -DGCC_HAS_REGEX

################################################################################
# PLATFORM LIBRARIES
# These are library names/paths that are platform specific and are specified
# using names or paths. The library flag (i.e. -l) is prefixed automatically.
#
# PLATFORM_LIBRARIES are libraries that can be found in the library search
# paths.
# PLATFORM_STATIC_LIBRARIES is a list of required static libraries.
# PLATFORM_SHARED_LIBRARIES is a list of required shared libraries.
# PLATFORM_PKG_CONFIG_LIBRARIES is a list of required libraries that are
# under system control and are easily accesible via the package
# configuration utility (i.e. pkg-config)
#
# See the helpfile for the -l flag here for more information:
# http://gcc.gnu.org/onlinedocs/gcc/Link-Options.html
#
# Note: Leave a leading space when adding list items with the += operator
################################################################################
#check gstreamer version
ifeq ($(CROSS_COMPILING),1)
ifdef TOOLCHAIN_ROOT
#You have specified TOOLCHAIN_ROOT with an environment variable
else
TOOLCHAIN_ROOT = /opt/cross/bin
endif
ifdef GCC_PREFIX
#You have specified GCC_PREFIX with an environment variable
else
GCC_PREFIX = arm-linux-gnueabihf
endif
PLATFORM_CXX = $(TOOLCHAIN_ROOT)/$(GCC_PREFIX)-g++
PLATFORM_CC = $(TOOLCHAIN_ROOT)/$(GCC_PREFIX)-gcc
PLATFORM_AR = $(TOOLCHAIN_ROOT)/$(GCC_PREFIX)-ar
PLATFORM_LD = $(TOOLCHAIN_ROOT)/$(GCC_PREFIX)-ld
SYSROOT=$(RPI_ROOT)
PLATFORM_CFLAGS += --sysroot=$(SYSROOT)
PLATFORM_HEADER_SEARCH_PATHS += $(SYSROOT)/usr/include/c++/5

PLATFORM_LIBRARY_SEARCH_PATHS += $(SYSROOT)/usr/lib/$(GCC_PREFIX)

PLATFORM_LDFLAGS += --sysroot=$(SYSROOT)
PLATFORM_LDFLAGS += -Wl,-rpath=$(SYSROOT)/usr/lib/$(GCC_PREFIX)
PLATFORM_LDFLAGS += -Wl,-rpath=$(SYSROOT)/lib/$(GCC_PREFIX)
PKG_CONFIG_LIBDIR=$(SYSROOT)/usr/lib/pkgconfig:$(SYSROOT)/usr/lib/arm-linux-gnueabihf/pkgconfig:$(SYSROOT)/usr/share/pkgconfig
endif

修正完了したら保存して終了。
● このままでは、キーボードが使えないのでofAppGLFWWindow.cppを修正
nano ~/of_v0.9.8/libs/openFrameworks/app/ofAppGLFWWindow.cpp

1138〜1150行目の修正
【修正前】
        default:
          key = codepoint;
          break;
     }

     ofAppGLFWWindow * instance = setCurrent(windowP_);
     if(action == GLFW_PRESS || action == GLFW_REPEAT){
        instance->events().notifyKeyPressed(key,keycode,scancode,codepoint);
     }else if (action == GLFW_RELEASE){
        instance->events().notifyKeyReleased(key,keycode,scancode,codepoint);
     }
  }
【修正後】試行錯誤の結果妥協した内容 actionに1を加算しないと入力キーを認識しない。
        default:
          key=keycode;
          break;
     }
     ofAppGLFWWindow * instance = setCurrent(windowP_);
     action+=1;
     if(codepoint==0){
         if(action == GLFW_PRESS ){

           instance->events().notifyKeyPressed(key,keycode,scancode,codepoint);
         }
     }
 }
● Openframeworksのアプリケーションコンパイルに必要なconfig.shared.mkを修正
of_v0.9.8/libs/openFrameworksCompiled/project/makefileCommon/config.shared.mk

91行目

   【修正前】 else ifeq ($(PLATFORM_ARCH),armv7l)
   【修正後】 else ifeq ($(PLATFORM_ARCH),aarch64)

Openframeworksのビルド
cd ~/of_v0.9.8/scripts/linux
./compileOF.sh -j4

エラーなければもう一息。エラーがあったら再度上記確認。
● 最後にlibGL.soをTX1専用のものに変更。
cd /usr/lib/aarch64-linux-gnu
sudo rm libGL.so
sudo ln -s /usr/lib/aarch64-linux-gnu/tegra/libGL.so libGL.so

これで一応インストールは終了。お好みのサンプルフォルダに行き(ここでは一番見た目が派手なやつ)
cd ~/of_v0.9.8/examples/3d/3DPrimitivesExample
webcameraをusbに接続して
make -j4
make run
でビルドして、動かすと。ものすごく早い!!(最初の画像参照)。キーボード入力は今の所1〜9、大文字アルファベットのA〜Z、矢印キーしか受け付けません。escキーは使えないので注意。(もっとも操作上はこれだけあれば十分ですけど)サンプルファイルは小文字入力が必要な場合は大文字に変更してください(ofAPP.cpp内部。keyPressed内に書かれた入力処理のみ受け付ける。keyReleasedに書かれている場合は、keyPressed部分に書き換えればOKです)。どうやらglfw3ライブラリに関してTX1の相性が悪いみたいですが、うまく行ったらまた書き込みます。

 TX1専用Openframeworks ダウンロード-->インストール手順

 上記の方法で必要なライブラリをプレビルドしたOpenframeworksがダウンロードできるようにしました。--->of_v0.9.8.zip (はてなブログでファイル容量の制限があるので、OFをシェイプアップするのに時間がかかりました。掲載が遅れてごめんなさい)

 ダウンロードして解凍します。iMacで圧縮したので余計なファイルが入っていますが、対象フォルダはof_v0.9.8です。

まず依存ファイルをインストール。

sudo apt install cmake

cd of_v0.9.8/scripts/linux/ubuntu/

sudo ./install_dependencies.sh 

かなり時間が必要。最後にpocoのインストールを聞かれるが、インストールしない。(インストールしても良いが意味なし。時間の無駄)

次にOFをコンパイル

cd ..
./compileOF.sh -j4

ここまではいつもの手順です。エラーが出る場合は、質問を受け付けますのでコメントを書いて下さい。最後にTX1 特有の変更。
cd /usr/lib/aarch64-linux-gnu 
sudo rm libGL.so
sudo ln -s /usr/lib/aarch64-linux-gnu/tegra/libGL.so libGL.so

これだけです。

 

                                   では また。