Take’s diary

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

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

これだけです。

 

                                   では また。

Intel Joule はEdisonやPi3 との価格差を超えられるか?

Intel Jouleを色々試してみて

 先月の段階で、Ubuntu developer potalよりUbuntuインストール方法が紹介されています。本体eMMCに自動的にインストールされるのですが、前回私の書いた記事より格段に簡単で、画面が安定している感じなので、今回紹介します。そしてmraaの実装と少し高度な動作確認。さらにはOpenCLの動作確認まで触れて見たいと思います。

f:id:TAKEsan:20161206144546j:plain

                                                                私の最終構成です。

f:id:TAKEsan:20161206144543j:plain

             OpenCLまで動いちゃいました

本体内部eMMCに、Ubuntu16.04をインストールする

 今月の初め(2016/12)にJouleにUbuntu14.04をインストールして、インストール煩雑さの挙句GPIO群が使えないなんて記事を書きました。その後Intel Edison ユーザー会https://www.facebook.com/groups/625317624253131/の Hirokazu Egashiraさんにヒントをいただいて、いろいろ試したらとても簡単にインストールできたのでご報告。

 まず、Intel Joule | Ubuntu developer portalに、JouleのUbuntuが発表されていました。最初はUbuntu Coreだけだと思っていたのが大間違いで、最後の方に自信なさげにUbuntu desktopインストール方法が書いてあります(Developer setup Install Ubuntu Classic (desktop) on the Intel Joule)。ただ、リンクされたファイル「tuchuck-xenial-desktop-iso-20161006-0.iso」ではインストール用のUSBが作れませんでした。で、諦めかけて以前Ubuntuのインストールで大変参考になった記事Installing Ubuntu on Intel Joule 570x |Intel Communitiesを見ていたら、最後の方にjosephwinstoniiさんがこの件を書いていました(この方は一体誰?)。よく見るとリンク先が違っているようです。本当は、 http://people.canonical.com/~platform/snappy/tuchuck/tuchuck-xenial-desktop-iso-20161006-0.isoだそうです。ダウンロードに、ものすごく時間がかかるのですが、これを使うと簡単にUbuntuインストール用のUSBメモリーが作れます(現在はリンクが治っている可能性がありますが)。あとはUbuntu developer portalの手順に従ってインストールするだけ。注意点はその記事にも書いてありますが、JouleのBIOSBIOS V#131に更新する必要があることです。

 Intelサイトに

software.intel.com

書いてあるんですが、JouleのBIOSをインストールできるのはWindows環境だけです。書き換えにはJouleと付属USB Cをつなぎます(電源は必要なし)が、接続したディバイスは時間が経つと自動的にキレてしまうようなので、最後のスクリプトを実行する前に、Windowsディバイスマネージャーで、接続されていることを確認してから、コマンドプロンプトスクリプトを実行することで上手くいきました。認識していない場合は、USBを刺し直します。これが失敗すると、今回の方法でUbuntuが上手くインストールできないので。確実にクリアすることが必要となります。

 次に自分の母艦環境(WindowsMacLinux)でUbuntuインストール用のUSBメモリを作ってください。あとは、JouleのUSB3.0へキーボード、ディスプレイ、UbuntuインストールUSBメモリを取り付けてBOOTマネージャーからUSBを指定するだけ。

f:id:TAKEsan:20161206151121j:plain

          Jouleを起動させてF2キーを押すと、こんな画面になります。

f:id:TAKEsan:20161206151122j:plain

         Boot Manegierを選択して、EFI USB Deviceを選択します。

 あっという間に本体eMMCにUbuntu16.04がインストールできちゃいます。(あっとといっても20分程度は必要)Reboot後、派手な初期画面が現れた後(2分程度)、途中で言語やキーボード、Wifiの設定を聞かれるので、基本的な環境を入力します。簡単簡単。「前回のは何だったんだろう」みたいな感じでした。ちなみにカーネルは 「4.4.0-1000-joule」で、Joule専用のようです。

 思い切ってOstroとはさよならすることにしました。WindowsLinuxの母艦とクロスコンパイルするならOstoroでも良いとは思いますが、Edison等とは違い、以下の様にSSDUbuntuをインストールすると、ビルドが相当早いので、母艦の必要性を感じなくなります。内部eMMCにインストールしたUbuntuが母艦の代わりとでも言いましょうか。蛇足ですが、容量の少ないJoule内蔵eMMCにインストールしたUbuntuには、apt updateとapt upgradeを実行した後、最小限のアプリのインストールに留めた方がよろしいかと思います。

Usb3.0に接続したSSDUSBメモリUbuntuをインストールする

 このままでも良いのですが、eMMCはもったいない(IntelはeMMCのを信用していない節があちこちに見受けられる)ことと、絶対容量が不足なので、どうしても外部から起動したくなりますが、USB外部記憶装置にインストールが可能です。

 まず本体eMMCで起動したjouleに外部SDやSSDを接続。さらにインストールUSBを接続します。

f:id:TAKEsan:20161206145100j:plain

今回接続しているSSDSanDisk(128Gで12,000円くらい)、キーボード・マウス兼用の無線アダプタ、インストールSDカードはSONY製を使いました。左上は、OpenCLテスト用に作ったSDカード。BuffaloのSDカードリードライターを使ってます。USBハブは当然3.0用ですよ。お間違えなく。

 次にUbuntuの世界で有名なGpartedをインストール。このソフトでインストールするディスク名称を調べ、一応全領域をext4でフォーマットします。

f:id:TAKEsan:20161206135923j:plain

GpatedでSSD内容を表示させています。すでにUbuntuをインストールしてあるので複数のパーテーションに分かれていますが、最初は全領域ext4でフォーマットします。右上にデイスク名称「sda」が表示されています。

インストールCDの install/predeed.cfg の中身を修正。2箇所(50,90行目付近)修正箇所があります。

f:id:TAKEsan:20161206142708j:plain

  50行目付近の赤線部分を変更。念のため以前の行はコメントをつけています。(元々はmmcblk0)

f:id:TAKEsan:20161206142707j:plain

               90行目付近も同じように修正します。

 この部分をmmcblk0からsda またはその他(環境によってディスク名が変わるのでgpartedで確認したディスク名)に変更して保存。

 修正が完了したらインストールUSBメモリ、外部記憶装置は外さないで、reboot後、F2でブートマネージャーを立ち上げ、Boot Option Menuを選択。今度は下の写真の様にEFI USB DIiviceが2つ出てきます。大雑把な方法ですが、空の方は選択してもブートマネージャに戻ってきますので、もし戻ってきた場合はEFI USB DIivice 1の方を選択すれば、本体eMMCと同じ様に、自動でpredeed.cfgに指定した空のディスクにインストールされます。なんか挙動がおかしかったら、(途中でインストール作業が止まってしまったら)再度リセットスイッチを押して本体eMMCでUbuntuを起動した後、predeed.cfgの中のディスク名称を再度確認してください。インストールできない原因は多分これだけです。正常であれば簡単にインストールできちゃいます。

f:id:TAKEsan:20161206135921j:plain

            Boot Option で EFI eMMC Deviceを選択するだけ。

 現在私はコンパクトSSDを使ってますが、安定して動いてます。早いこと早いこと。もう立派なUbuntuマシンです。Ubuntuディスクトップマシンを持ってるのですが、全く必要無くなってます。

 標準で使うUbuntuを決めたら最初にMraaインストールと動作確認

 JouleでPythonc++からGPIOを制御するには、mraaが最適です。何はともあれ、最初にmraaをインストールします。これが使えなければわざわざJoulを選択する意味がありません。色々な方法で試して見ましたが、最新のソースをダウンロードしてビルドしたものが一番安定している様です。

 ソースはhttps://github.com/intel-iot-devkit/mraaからダウンロード。解凍したフォルダに入ったら、以下を実行。

sudo apt-get install git build-essential swig3.0 python-dev nodejs-dev cmake libjson-c-dev

mkdir build

cd build

cmake ..

make

sudo make install

sudo ldconfig

sudo ldconfig -p | grep mraa

一応nano .bashrc で 最後に

export PYTHONPATH=$PYTHONPATH:$(dirname $(find /usr/local -name mraa.py))

を追加

 インストールしたら、ダウンロードしたファイルにPython のサンプル(mraa-master/examples/python)が入っているので、blink-io8.py---->内部の x=mraa.Gpio(8)をx=mraa.Gpio(101)に変更。sudo python blink-io8.py でボード上のLEDが点灯するはずです。sudoを付けないとGPIO制御ができないので注意。

f:id:TAKEsan:20161206142706j:plain

                       実行前

f:id:TAKEsan:20161206142705j:plain

どうせならってことでボード上のLEDを全部点滅して見ました(GPIO番号 100〜105)CPUモジュール上のLED 2個も点灯できました。

 ところが、オンボードLEDの点灯確認ができますが、手持ちのLEDをピンコネクタに取り付けたてみたのですが、どんなことをしても点灯できない!!。回路図を見ても全てのピンヘッダは3.3Vに昇圧されているのに.....。試しに予備で取っておいたOstroのSDカードで、Intelご自慢のOstroを起動して試してもダメ。なんてことでしょう。Ostroでも動かないなんて。だから取説のサンプルも基板上のLEDだけなんだと、妙に納得したりして.......。

 あ、そうそう。本体のSDカードフォルダに取り付けたSDカードにもインストールできると思いますが、16G以下に限られることと、転送速度が遅いためUbuntuでは体感スピードはかなり遅く感じます(前回検証)。CPUスピードは変わらないので、外部で使うならアリかもしれません。またOSをインストールしたSDカードを入れっぱなしにしておくとうまく起動できない場合があるので注意。

Joule EXpanson ボードのGPIOがmraaで動かない!!-->動いたぁ。

 肝心のGPIOピンに関して、i2cもPWMもGPIOも全く動く気配がありません。回路図を見るとちゃんと3.3Vレベルシフターが入っているし、宣伝でもピン出力は3.3Vと明記している。でもできない.....。ボード上のLEDは100~105番までちゃんとチカルのに。やっぱりカーネルがおかしいのかななどど考えたのですが、blink-io8.pyを利用してテスターでGPIOを確認すると、一瞬3.3Vになって1.8Vに戻る。OFFだと0V。どうやら内部レベルシフターが正常に働いていない。mraaは真面目に動いてるらしい...。80本のピンを3.3Vに昇圧するために実装している9つのレベルシフターが同時におかしくなるわけがないと思っていた矢先、またしてもHirokazu Egashiraさんからのヒントがありました。何でも非売品を買ったとか。それもJoule Ubuntuにインストールしたmraaで動くとか。ネットで探すと該当商品の説明がありました。

Gravity Expansion Shield for Intel Joule SKU: DFR0465 - Robot Wiki

おまけに回路図も真面目に掲載されています。Gravity Expansion Shield for Intel Joule Schematic

 このボードはExpansion Boardに差し込む形で、GPIOに特化したもの。Expansion Boardにセンサー類を直結すればいいのにと素人は思ってしまうのですが、理由があったんです。よく回路図を見ると全て4.7Kの抵抗が入っている。つまりPull Upが必要カモ。もしやと思いテスター片手に4.7k抵抗を大量に買ってテストして見ると、動きました!!。引っ張る電圧を5Vに変えると最大5Vになりました。これでバンザーイです。

 i2cはちょっと厄介。i2c-0は使えません。ユーザーに解放されているのはi2c-1以降のようです。さらにi2cdetectで12c-0以外はアドレスを確認できませんでしたが、Pull-Upすると動きます。i2c出力用にj12j13 2箇所ずつ同じポートが存在しますが 微妙です。私の場合、内部eMMCにインストールしたUbuntuでは、J13側。SSDではJ12側でしか反応しません。抵抗値が微妙の様ですが、i2cに関して一応4.7k抵抗をつけて動いた方ということで(測定器が欲しくなってきた)我慢。この辺りはIntelが資料を公開すれば、解消すると思われます。

 各GPIO接続方法は以下のとおり。抵抗1本でOKです。外部レベルシフターなど昇圧回路が必要無い点がGoodです。でもなんでこんなことをしなければならないのでしょうか?基盤が小さすぎたのかもしれません。

f:id:TAKEsan:20161206142709p:plain

こんな感じで、GPIO制御する場合はPull UPが必要みたいです。見た目でも信号を引っ張ってる感じが伝わってきます

f:id:TAKEsan:20161206142702j:plain

GPIO51番に接続したLEDを光らせる準備。Pull UP用に5Vを使用。LEDはLillypad用の抵抗付きLEDを使ってます。

 --->その後テストしてみましたが、SPIとUARTは初期設定時点でエラーになり(カーネル4.4.0-100 joule)ます。まだベータ版なのでしょうがないですね。この辺りForum: Intel® Joule™ |Intel Communitiesを見ると最新情報が確認できますが、やはり現時点では接続できないようです。方法が見つかったら追記します。

JouleのEXpanson ボードのピンヘッダは裏からも刺せる!!

 この頃気づいたのですが、これは初めて見る構造です。裏からも刺せる。L型のピンを使えばいい。ジュールはCPUが熱くなるので、迂闊に上部にCPUを跨ぐ様なボードを刺せません。結構使う側を考えたアイディアだと思います。

f:id:TAKEsan:20161206142701j:plain

ピンコネクタがスルーなのが確認できます。こんな感じで裏からもピンが刺せます!!良くできてますね。

JouleでOpenframeworksが動く!!

 私の実験用にはOpenframeworksは最適なC++フレームワークなので、これがインストールできてなんぼの世界なのですが、あっけなくインストールできました。全てのサンプルがソコソコ快適なスピードで動きます。画像処理中、若干息つきが出ますが、CPUスピードを調整すると格段に良くなることがわかりました。(sudo apt-get install indicator-cpufreq

 とりあえず、といっても2日間みっちり時間が必要でしたが、i2cとGPIOをMacで操作するWeb物を作って見ました。今まで作ってきたものの応用です。前回スイッチサイエンスRapiroボードで、Edison環境+Python flaskで作っていたものの中で、c++環境のスピードが要求されるプログラムをopenframeworksに組み替えました。いつもの非接触式赤外線センサー(OMRON D6T)とLEDとWebCameraを使用してます。

 今までは、ブラウザ上のボタン操作後、若干のタイムラグがあり、ボタンの反応が鈍かったのですが、前々からやりたかったofHTTPを応用した、カメラとセンサーの合成画像とLED点滅操作が、リアルタイムで操作できる様になりました。これが可能となれば、1年以上ブログを書いてきた今までの集大成ということになります。手順は、

  • Openframeworks linux64 Ubuntuインストールをマニュアルに従ってインストール
  • 今回必要Addonをaddonsにコピー(-masterは消すこと)     Openframeworksのディレクトリに入って

       cd addons
       git clone https://github.com/bakercp/ofxIO
       git clone https://github.com/bakercp/ofxMediaType
       git clone https://github.com/bakercp/ofxSSLManager
       git clone https://github.com/bakercp/ofxTaskQueue
       git clone https://github.com/bakercp/ofxNetworkUtils
       git clone https://github.com/bakercp/ofxJSON
       git clone https://github.com/bakercp/ofxHTTP
       git clone https://github.com/bakercp/ofxJSON
                         git clone https://github.com/bakercp/ofxJSONRPC

  • mraaとの連携ですが、新しく作成したプロジェクトディレクトリ内のファイルconfig.make中1箇所を修正。

f:id:TAKEsan:20161206150044j:plain

       config.makeの赤線部分を追加。要するにmraaライブラリを追加します。

 ofxIOのみ最近修正されたようなのですが、これが原因でコンパイルエラーが出ます。以前のofxIOに入れ替えればOKでした。ofxIOと今回作ったソースを一応ダウンロード可能にしときます。ofxIOを作った本人(開発者の一人)が気づくまで.....。今回作成したプログラムは、ofxHTTPとofxJONPRCで利用するサーバーを同一ポートで立ち上げるなどという作者が考えもつかなかった様なことを実験的に実行して見ましたが、ちゃんと動きました。ofxIO旧バージョンと今回作ったプログラムは、ここからダウンロードしてください。

http://d.hatena.ne.jp/TAKEsan/files/Joule-OF.zip

 解凍したファイルは「ofxIO」をaddonsへコピー。joule-jpeg-newはapp/myAppsヘコピー後フォルダに入ってmake -j4でビルド。sudo make runで実行できます。赤外線センサー(D6T)はスイッチサイエンスで手に入れることが可能(専用のケーブルが別売ですが必ず必要)。LEDは各自用意して下さい。D6Tセンサーはi2c-1へ接続、LEDは、+側がピン番号51接続としてます。

f:id:TAKEsan:20161206142703j:plain

     LedとOmton D6Tの接続状況。i2cはJ12側のi2c-1に接続。LEDはGPIO51番

どんなのかは下の動画をどうぞ。

         

左側はJoule直結ディスプレイ。右側はMacのサファリでJouleのip及びポート番号を指定してJouleを操作しているところです。D6T赤外線センサーは、認識画素数が4X4に対してJoule側で最大で200倍以上の補間をしてます。Mac側からLEDのオンオフ、温度分布のオンオフ、カラーマップの切り替え、補間精度の調整をリアルタイムで操作できました(動画ではLEDのオンオフがはっきり確認できませんでした。スンマセン)。カメラ画像は800X600でほぼリアルタイムですが、温度分布の方はD6Tの送信スピードが間に合わずギクシャクしているように感じます。こんなことはEdisonやPi zeroでは感じなかったので結構感激でした。

 何してんのかわかんないって?。センサーに温度を検知させててカメラ画像とシンクロさせてるんです。おまけで最高最低温度と検知した場所を表示させてマス。つまり安上がりのサーモグラフィーもどきってワケ。周囲より温度の高い「手先」に反応して動いてるでしょ。もちろん暗闇でも動きます。もともと16分割の温度しか検知できないなんて信じられます?。スイッチサイエンスさんが、わかりやすく解説していますMEMS温度センサを使おう | スイッチサイエンス マガジンが、これの大幅改良版です。

f:id:TAKEsan:20161206144547j:plain

   Mac側のサファリ画面です。左下にある5つのボタンでJouleをリアルタイムで操作できます。

 Openframeworksの長所でもある簡単に作成できるOSC通信で、WROOM02やらPi zeroやらとのデータ通信が高速にできることを確認しているので、Jouleとの連携が面白そうですが、目下の目標はJouleによるLeptonサーモセンサーの稼働です。先月号のトランジスタ技術にLEPTONの解説が掲載されてましたが、すでにPi zero でもWROOM02でも接続方法が確立している上に、画像配信まで実現しちゃってます(i2cでの温度取得も!!)ので私の方が2歩ぐらい進んじゃってるカモ。詳しくは過去記事をご覧下さい。でも、さすが専門誌だけあって、読み飛ばしていた英文マニュアルの要点を解説しているのでとても役に立ってます。

 Lepton との接続に関してEdisonでは苦い経験があるので、同じIntel系のJouleでうまく繋がるかどうかわかりませんが、トライしてみます。これが可能ならばLeptonを2つ繋げてステレオ・サーモセンサーができちゃったりして.....。階調の幅が相当あるので画素が少なくともなんとかなるような気が........。

 何と言ってもビルドのサクサク感が今後の開発意欲を高めてくれます。

JouleでOpenCLが動く!!

 これが実現できれば、内臓されたGPUIntel HD Graphics)を利用してさらにスピードアップさせたアプリが作れます。まだテスト段階ですが、物によりCPU単独の2倍程度早くなることが確認できました。海外の記事ではインストール失敗例ばかり(と言っても多分1人だけ)なので、今回の記事が最初だと思います。

 今回の記事でインストールしたUbuntuカーネルは、4.4.0-1000 jouleとなっていますが、OpenCLをインストールするには、4.7.0以上にする必要がある様です。危ないので(結果的にGPIO,PMWは使えるが、i2cが使えなくなった)、SDカードにインストールしたUbuntuUSB3.0接続)で試すのがおすすめ。

f:id:TAKEsan:20161206145101j:plain

       OpenCL実行用には、SDカードにインストールしたUbuntuを使いました。

 お試し用のSDカードにインストールしたUbuntuを立ち上げたら、まずカーネルをアップグレードします。

How to Install Linux Kernel 4.7.2 on Ubuntu 16.04 LTS - LinuxBabe.Comを参考に以下を実行。

wget kernel.ubuntu.com/~kernel-ppa/mainline/v4.7.2/linux-headers-4.7.2-040702_4.7.2-040702.201608201334_all.deb

 

wget kernel.ubuntu.com/~kernel-ppa/mainline/v4.7.2/linux-headers-4.7.2-040702-generic_4.7.2-040702.201608201334_amd64.deb

 

wget kernel.ubuntu.com/~kernel-ppa/mainline/v4.7.2/linux-image-4.7.2-040702-generic_4.7.2-040702.201608201334_amd64.deb

 

sudo dpkg -i linux-*4.7.2*.deb

 多少時間が必要ですが簡単にインストール可能。再度reboot。まともに動くかどうか心配でしたが、特に問題無く動きました。uname -a でバージョンを確認して カーネル4.7.2に変わっていればOK。

今度はOpenclをダウンロード。ダウンロード先は、

OpenCL™ Drivers and Runtimes for Intel® Architecture | Intel® Software

最初の方に説明しているSDKパッケージのlinux 64bit版をダウンロードして解凍。

 色々試して見ましたが、最終的にダメ元でトライした結果、ダウンロードしたディレクトリに入っているinstall_GUI.sh を実行するだけでOKでした。

 インストーラーはUbuntu14.04が基本で、途中「必要ライブラリが無い」と叱られますが、インストールを中断してメッセージに出たライブラリをapt-getでインストール。それでもエラーが出ますが気にせずに続けると、なんとなくインストールできます。

 GPUを認識していないんじゃ無いかって? この画面を見てください。ちゃんと認識してます!!

f:id:TAKEsan:20161206144543j:plain

   OpenCLを認識してます。Joule HDグラフィックス(GPU)とCPUの諸元が表示されました!!

 確認用に一番手っ取り早いOpenCV2.4.13をインストール。コンパイル中はかなりの頻度でGPUコンパイラが動いているので、一般コマンドも最適化されている可能性があります。インストール方法は以下の通り。

sudo apt-get install qt5-qmake

sudo apt-get install qt5-default

sudo apt-get purge python-pip

wget https://bootstrap.pypa.io/get-pip.py

sudo python get-pip.py

sudo add-apt-repository universe

sudo apt-get update

sudo apt-get install cmake git aptitude screen g++ libboost-all-dev \

libgflags-dev libgoogle-glog-dev protobuf-compiler libprotobuf-dev \

bc libblas-dev libatlas-dev libhdf5-dev libleveldb-dev liblmdb-dev \

libsnappy-dev libatlas-base-dev python-numpy libgflags-dev \

libgoogle-glog-dev python-skimage python-protobuf python-pandas

お好きなOpenCVをダウンロード解凍後(今回は2.4.13)ダウンロードしたフォルダに入って

make build

cd build

cmake  -D WITH_OPENCL=ON -D WITH_QT=ON -D WITH_OPENGL=ON -DBUILD_TESTS=OFF -DBUILD_PERF_TESTS=OFF -DBUILD_EXAMPLES=ON -D BUILD_opencv_python2=ON -D PYTHON_EXECUTABLE=$(which python) ..

make

sudo make install

 これで簡単にOpenCVもインストールできます。コンパイルオプションにOPENCLを入れています。

 ダウンロードしたOpenCVの中に入っているOpenCL用のexample(oclディレクトリ内に存在)を実行して見ます。コンパイル方法は、

  g++ 該当ソース.cpp `pkg-config --cflags opencv` `pkg-config --libs opencv`

コンパイラが働いている証拠にOpenCLの中間ファイル(拡張子.clb)ができてます。

f:id:TAKEsan:20161206181431p:plain

oclサンプルのcppファイルをコンパイルした後、中間ファイル拡張子clbができていた。OpenCLがまともに動いてる!!

 実行できないのもありますが、次の2つのプログラムで実行内容を確認して見ました。

 まずfacedetect。これは遅い!!。GPUの恩恵は感じられません。認識用のデータは opencv-2.4.13/data/haarcascades_GPU/haarcascade_frontalface_alt2.xml を指定します。このデータ以外は実行できない様です。なんとなくGPUメモリが原因みたいな感じでした。もともとOpenCVの顔認識サンプルは、遅いことがわかっていたのですが、これはダメ。(Openframeworksの顔認識の方がはるかに早い!!)

 次にhog。これは人物を認識するプログラム。ちゃんとCPUの2倍早くなってることが判明。効率を追求すればこの倍は行く様に思われます。ちなみにTX1ではGPU ONで今回の5.3倍程度(CPUのみで1.9fpsなのでCPUスピードはJouleが若干上で、GPU ONだとTX1が遥かに上)のスピードでした。i7 6700K CPUオンリー環境でもJoule のGPU ONの2倍くらいのスピードなので、このサンプル自体OpenCVGPUのテストとしては、相当効率が悪い様です。

f:id:TAKEsan:20161206144544j:plain

Mac上で人物を表示させて、Jouleに接続したカメラで人物を認識させているところ。実際の人間ならもっと認識率が上がるカモ。GPUが4.4fps前後であることが確認できます。

         

GPUとCPUの切り替えをしている動画です。画面に映っているテレビ画面の動きでスピードの感覚が掴めると思います

 てな訳で一応ちゃんと動きました。外付けGPUにはとても叶いませんが、少しでも早いソフトを作りたい方は最適かと思いますが、いかんせんカーネル4.7.2では、i2cが使えません。(/dev にi2cポートが現れない)対処方法はインテルの資料待ちといったところでしょうか。また、内部エラーが時たま出るので、システムが不安定になります。付け加えると、GPUプログラム実行時Jouleモジュール自体、かなり発熱しますので冷却体制は万全に。

 やっと本題

Intel Joule はEdisonやPi3 との価格差を超えられるか?ですが、

  •  CPUスピードは、Edisonの10倍、Pi3の3倍くらいの差が確実に体感できる。
  • GPIO制御に特別の外付け回路が必要ない(抵抗が必要だが)。
  • 本体のみでプログラム開発がサクサク。
  • はるかに拡張性のあるUbuntu環境が簡単に実現できる。
  • Wifiが実用レベルで動く(Pi3やTX1と比較して非常に安定している)。
  • GPGPU(OpenCL)を使ったプログラムが組めるので、さらにスピードアップが期待できる。

 Ubuntuがノートパソコン並みにサクサク実行できて、GPIOが使えれば、価格差なんか糞食らえになっちゃいます。使用感の次元が違うので、この種の趣味を持つ者とすれば天国ですよね。でもEdison(WROOM02やPi zeroも!!)についてはIOT制御面での優位性は確実にありますので、これらを適所で組み合わせることで素晴らしいモノが作れると思います。

 Pi3を色々試してみると、どうしてもSDカードのスピードの壁に突き当たって来ます。Pi3ユーザーの一人として、こうしてJouleを色々実験してみると、私のPi3へのプログラム処理能力の期待度は、結局Jouleだったんだと分かって来ました。過去、私を含めた批判者の多いモジュールでしたが、Jouleについて初期の頃感じていた不満を1つ1つクリヤしていくと、計り知れない底力を秘めていることを感じてしまいます。

 Joule唯一の欠点は、外部へ持ち出した時、電源への配慮が必要なことでしょうか。 Ubuntu環境では、USB C へ3A程度の電源供給ではシステムが初期ダウンしてしまいます。基板上に電源用のパターンが存在しているので、この辺も追求したら楽しそう.....。

 結論になってませんが、そもそも比較する対象が違うっ。という曖昧な答えを出して今回は終了。

 少し長くなりましたが、今年はこれで終わりにします。これから少し家の修理とか、正月の準備とか、庭の手入れとかに精を出したいと思ってます。そのあたりで何か発見があればまた書きたいと思います。

 

                        では、また。あー疲れた。

 

 

 

Juneちゃん その後。

 やれIntel jouleやら、Nvidia TX1やら、ゲームパソコンやらちょしてる(仙台弁触ってるの意)事に限界を感じてきたので、今回は私のストーカー犬「ジュン」ちゃんの近況です。

 ところでトイプーって毛が抜けないの知ってました?ほっておくと着古した毛糸のセーターみたいに毛玉だらけになっちゃいます。初めの頃は知りませんでした。

 今年は3歳。夏バテ防止のためサマーカット(丸刈り!!)を2回ほど経験してやっとこうなりました。

f:id:TAKEsan:20161127194546j:plain

f:id:TAKEsan:20161127194547j:plain

 お腹のタプタプがチュッチュッチュッ〜なんですけとワンちゃんを飼ってない人はわからないでしょーね。

 モッップ状態。これがカワイくなるんでしょーか?。今までだとある程度長くなると形が整ってくるんですが、今回は全くダメ。基本のカットバランスがものすごく悪い。今までのトリマーさんが変わったみたいなのが大きな理由。変わったトリマーさんはどうやら初心者のようです。自分の娘みたいなもんなんで、「カワイ」くしたいのは飼い主のサガ。

 思い切って、違うところに頼んでみました。

f:id:TAKEsan:20161127201714j:plain

惚れ惚れするようないい女!!

f:id:TAKEsan:20161127201715j:plain

尻尾のくびれが......ソソル。

f:id:TAKEsan:20161127201716j:plain

セクシー!!

3日後

f:id:TAKEsan:20161127202629j:plain

今度のトリマーさんはまつ毛を残してくれたのに気づきましたました。

f:id:TAKEsan:20161127202632j:plain

まつげの先がキュンと跳ね上がってました。

f:id:TAKEsan:20161127202630j:plain

 思い切ってマスカラで黒くしようと思いましたが。気持ち悪くなるのでやめました。もう少し頭の先が伸びると最高。こんな感じで365日見つめられているのもなんか後ろめたさがあったりして.......。

                             ではまた。