読者です 読者をやめる 読者になる 読者になる

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

 

 

                                                    では、また。