nanoにインストールしたOpenFrameworksから、OpecCVとDarknet(YOLO)を動かす方法を書きます。nanoでAI系のソフトをインストールして動かしてみたけれど、これを利用して自分の目標とする「何か」を作るとき、その先膨大な解説と格闘しなければならず、大概行き詰まってしまいます。汎用CPUに比べると1/4位のスピード。AIエンジンを利用して応用ソフトを組む場合、インタープリタ型言語であるPython等を使うと、応用部分であきらかに遅くなってしまう傾向がある点は否めません。CythonやSWIGを使えば早くなりますが、結局C言語に戻ってしまうことになります。最初からCやC++等を使って、なるべくCPU処理部分のスピードを上げるのがnanoでは得策と思われます。AIの研究者でもないので基本的な構造学習作業をワープして、即応用に繋がる方法はないものなのでしょうか?。今回は一例としてOpenframeworksとDarknet(yolo)を使って、簡単に応用ソフトを作るためのきっかけがつかめたら良いと考えて記事を書きます。今回作成したYOLOv2-tinyの動画です。認識スピードは遅いものの結構正確でした。認識部分を別スレッドで動かしているので、動画に後から追いつく感じ...なぜOFとDarknet(YOLO)を結びつけるのか?C++はコンパイラ型言語ですから、できあがったアプリの全体スピードが速いことは常識です。ところがプログラム自体も、コンパイル作業も、一般的に非常に煩雑で、専門外の人間にはに取り付き難いことが欠点でもあります。これらの欠点を大きく改善したものがOF(OpenframeWorks)だと私は認識しています。OFの優れている点は、オープンソースであることと、文法構成の工夫で初級段階でも高度なグラフィックソフトが出来てしまうこと。先人の作った様々な画像系・サウンド系・その他のライブラリがAdoonという形で簡単に利用できることです。様々なディバイスでアプリが作れますが、私の経験ではMacのXcode環境よりLinuxの方が構造が簡単でプログラムし易いように思います。初心者にとってはコンパイルが時として上手くいかなかったりすることがありますが、日本では2人の先生が初歩から応用までわかりやすく解説していますので参考にしてください。こじ研(openFrameworks)YOLOはC言語を使って開発されていますから、OFを使ってYOLOが簡単に使えたら、どんなこともできそうな気がします。nanoでAI応用プログラムを作ってとても感無量ってことを前回の記事で書きました。SWAPを作成する以降のコンパイル作業時にメモリが不足して、止まってしまう可能性がありますので、SWIPファイルを最初に作成するのがベターです。nanoでの設定方法は、Jetsonの世界では有名な方(私はサメのおじさんと呼んでます)以下で説明しています。JetsonHacksnanoにOFをインストールする前回の記事でも少しヒントを書いたのですが、以前私が書いた記事を参考にして、nanoへのインストール手順をまとめた方がいます。GitHub実はこの部分の説明をどうしたものか迷っていたので大変助かりました。この記事はOFのコンパイル環境を作る説明だけなので、さらに手順が必要です。以降はOFのディレクトリに入りINSTALL.mdを確認して下さい。前回実行したサンプルを含めてOFのexampleが殆どすべて実行できます。サンプルの内容はmigizoさんが紹介しています。Proと比較しても遜色ないスピードで動きます。QiitaOFでOpenCVを使うYOLOを使うためにはOpenCVライブラリが必要です。機能や性能が限られます(contribやGPUが使えない)が、OFにはofxOpenCvとofxCvという有名なaddonがあります。これらのaddonを使わなくともnanoに元々インストールされているOpenCVライブラリや、最新のOpenCVがOFから簡単に導入できます。nanoに入っているのはバージョン3.3ですが、それ以降のOpenCVを使う場合は別途インストールが必要です。LinuxでOFアプリを作る場合は、myAppsディレクトリの中のemptyExampleをコピーして作って行くことになります。以下の作業でOFからOpenCVが使えるようになります。1.コピーしたemptyExampleディレクトリの名称を変える。"opencv2/core/utility.hpp"等、OpenCVに必要なヘッダーファイルを追加します。後はofApp.cppのsetup()、update()、draw()にOpenCVの様々な関数を書いて実行することができます。宣言すればもっと使いやすくなります。反則ですが慣れて来れば、ofApp.cppの先頭に書き込んでもOKです。ofApp.cppに自分で用意した関数を使う場合はそちらの方が簡単かもしれません(今回はofApp.cppにヘッダー宣言を入れています)3.OFとOpenCVの画像データの受け渡し一番問題になるのはこの辺りで、OFとOpenCVでは画像データの構造が違うので、変換処理が必要です。この部分を簡単にしたのがofxCVアドオンですが、今回はこのアドオンを使用しない(使えない)ので、基本は次の様な感じで変換します。false);この2行の変換処理に関して、全体のスピードには殆ど影響が無いようです。これさえできれば、最新OpenCVの画像処理をOFから自在に利用できるようになります。Darknetのインストールこのソフトは全体がC言語で開発されていることと、導入が非常に簡単な点が大きな利点です。Nvidiaではnano用に簡単に導入できるAIエンジン(Tensorflowやtorch)も公開していますが、短縮版です。一般的に著名な標準版のCaffe、Tensorflow、torch等をnanoに移植するには、非常な煩雑なインストール手順と長大なコンパイル時間を否応にも経験しなければなりません。最終的にはGPUメモリ容量の問題でアウト!。その点Darknetは、Makefileを少し修正すればmakeコマンドだけで標準版がインストールできてしまい、コンパイル時間もnanoの場合5〜6分で終わってしまいます。コンパイル後はコマンド一発で動画や静止画の認識テストや学習まで出来て、画像認識性能や認識スピードも現在の最新のモノと遜色ないと言ったらどんな不満が出てくるんでしょうか?しかもnanoのメモリ4GBでギリギリセーフ。前から紹介してきたDarknetは、16ビット小数点演算指定ができるので、スピードではまさにnano向きなのです。infarencceというjetsonシリーズで非常に有効なTensorRTを利用した3種類の画像認識が出来るソースを公開しています。(よく知られているオレンジやバナナの認識....)でも、前から思っていたのですがWebカメラを使って実行したところ、さほど認識スピードが速くないのです。これはTX1,TX2,Xavierでも同じ印象を受けます。自分で作ったデータを学習させる場合もDIGITSを使った場合、DIGITS本体のインストール作業や実行上の独特の手順が要求されます。最終的に出来たモノはスピードや認識精度共YOLOと互角又は性能が落ちる様に思えます。みなさんも是非試してみることをおすすめます。ある意味これがメーカー水準と言うことになることになると思います。YOLOは完全にnano向きかといえばそうでもありません。v2を使うことになると思います。認識結果もさほど悪く無いことが分かっています。インストールは前回の記事を参考にしてください。ジャーこれを使ってOFでプログラムを書くにはどうすればいいんでしょうか?Darknetは頻繁に修正を行っているので、いつも最新版を利用したいのですが、addonにするとそういうわけにはいかなくなります。Objectファイル)を直接リンクすることにしました。中に以下の様にsrc1という名称のリンクフォルダを作成します。./src13.ofApp.cppにヘッダーファイルを指定する以下のWebCameraを使った例のofApp.cppを参照して下さい。ここではOpenCVのヘッダーも入れています。入っているディレクトリを追加して下さい。LD_LIBRARY_PATH=/home/????/darknet/include:$(LD_LIBRARY_PATH}5.必要ファイルを所定のフォルダにコピーする。OFで動いたYOLOのweightsサンプルデータは以下の3種類です。一応テスト用にダウンロードしてbinフォルダにコピーします。https://pjreddie.com/media/files/yolov3-tiny.weightshttps://pjreddie.com/media/files/yolov2.weightshttps://pjreddie.com/media/files/yolov2-tiny.weightsさらに以下のファイルをdarknet/cfgからyolov3-tiny.cfgyolov2.cfgyolov2-tiny.cfgdarknet/dataから以下のファイルをコピーしますcoco.namesまた、テスト用にbin/dataの中にフォントファイルcooperBlack.ttfをコピーして下さい。cooperBlack.ttfは、of/examples/graphics/fontShapesExample/bin/dataに入っています。余計なファイルも入っていますが、binフォルダの中はこんな感じになります。DarknetをOFからそっくりそのまま使うので、認識スピードがDarknet本体より遅くなることがありません。以下は最も単純なWebCameraを使った画像認識の例です。これを発展させれば音声や画像、GPIOを含めた様々な応用ソフトが作れることになります。ビデオデータをmapに変換している部分もありますし、何より画像認識部分はOFで簡単に書けるマルチスレッドを利用してます。カメラの表示スピードは殆ど落ちないし、2つの認識スレッドを空きを見ながら処理してるので、条件が良ければ標準のものよりスピードがかなり上がります。(v2とv3に関してはtiny版が5fps位上がるようだ。Xcodeからそのままコピーしたのでインデントがおかしいですがご勘弁。OFでは実質update()とdraw()を繰り返しているだけですから、AIを使うと言っても下記のようにこの部分のソース自体は非常に簡潔になります。DetectNet部分をマルチスレッドにする。dragInfo){}OFでYOLOを使う場合の条件yolov3はメモリが不足して使えない。yolov2は設定の変更でなんとか動くが、途中で止まる場合は何回か再実行を試みる。最初の方のパラメーターを4箇所変更してみて下さいbatch=1subdivisions=64width=320height=320※width,heightは32の倍数。tinyは応用できるが現行のサンプルデータはなんか変。プログラム上のバグがある模様。tinyより認識率がかなり落ちるようだが、データ数か学習が失敗してる可能性もある。誤認識が多いということを考慮するとでtinyを使った場合、nanoで問題なくアプリが作れます。それもyolov2-tinyが良い様です。これ以上を望むならTX2やXavierということになりますが、nanoでも殆ど問題ないことが分かりますでしょうか。以下画像は、このアプリを使って実際に実行させた結果です。yolov2.cfgは上記設定。良いが遅い->5fps程度。cfg内容は変更なし。18~25fpsくらいで認識するがバウンディングボックスの範囲が実際より小さく多重認識がある。前にオリジナルデーターで学習させた時の経験上、使ったcfgファイルが今回のサンプルデータと合っていない可能性がある。cfg内容は変更なし。この数値以下にするとかなり小さい対象物も認識するが誤認識も多くなる。これも18~25fpsくらいで認識する。最後に外付けSSDに開発環境を移行する。SDカードでも単独開発できますが、寿命や信頼性の問題、さらにリードライトスピードが遅いので、開発には向きません。SSDにそっくりそのまま移行した方が、OSのレスポンスも早くなります。以下「サメおじさんのブログ」を参考にして、全く問題なく全ての環境がSSDに移行できました。JetsonHacksSDカードに最終環境が残っているので、外部で使う時などは、またSD環境に戻してSSD無しで使えることが利点です。sda1をmmcblk0p1に変更SSDブートの場合はsda1に変更します。スペルを間違うと2度と起動しなくなるので注意が必要です。(その場合でも他のUbuntuマシンを使って修正は可能)この環境ではブート時に一旦SDを見に行ってからSSDにOSを移行する設定なので、SDは取り付けたままにします。SSDを外した場合起動しなくなるので注意が必要。再度SSDを接続してリブートすれば問題なく動きます。Jetsonフォーラムで、M.2スロットに変換ボードを接続すればSSDが接続できるかも....とメーカー側の投稿があり、試してみたら全くディスクとして認識されませんでした。(ダメ元でもう少しトライしてみますけど)アーくやしい!!この頃気候のせいか体調があまり芳しくなく、頭がボーとしていて文章がまとまりません。分かりにくいところはコメントください。nanoが発売されました。B+にMobidiusを追加した価格より、機能面を考慮すると大幅に安いというような衝撃的な仕様でもあります。実際はどうなのかってのが今回の内容。NvidiaのJetson関連ボードはTK1から始まってTX1、TX2、Xavierとなってますが、今回のボードはTK1とTX1の中間ぐらいの構成になってます。いつものように、メーカーの宣伝が派手なので本当のところは?って、誰でも思うところだと思います。私の理想とする環境はかなり偏ってるので、そのつもりで読んでいただければと思います。OSのインストールは超簡単。今までのTXシリーズは内部eMMc起動のために煩わしい手順が必要でした。今回はそれをやめてSSDブートに変更したため、インストールで引っかかりにくくなりました。メーカーのインストール手順で何の問題もありませんが、最初にUbuntuが立ち上がるまではPi3より遙かに早かったとだけは言えます。インストール完了時点でCUDAもCUDNNもOPENCV3.3もインストールされてるので文句の付け様がありません。標準ではWIFIやBlutoothは付いていません。CPUを取り外すとM2コネクタが付いているので汎用のWIFIカードを付けるか、USBドングルってことになります。今回は手っ取り早く余ってるWIFIドングルを使ってみました。Jetsonシリーズの常で、日本語環境には向かないので、インストール時は注意してください。ある程度環境を作ってから日本語化する方が無難。マーSDカード(32GB以上)枚数が経済的に許す限りOSをたくさん作っておけば良いことですから、そんなに心配する必要も無いとは思います。Nanoは最大能力にすると17.48secでした。そんなに早くはありませんが、それでもPI3B+の約3.2倍!!Nanoのオーバークロック方法は、今までのJetsonシリーズとはとは違い、コマンド化されたようです。USB電源から起動可能ですがオーバークロックさせると、システムが止まってしまいます。4A電源(これが上限のようです)とジャンパーピンを取り付ける必要があります。FANを付け足すと一応安心。実際動かしてみると、普通に使うんであればこれ以上のスピードはいらないんじゃないかって思いました。汎用にするには少し問題もあることは使ってる方なら分かると思います。最大の能力を引き出すには、以下2つのコマンドを続けて実行します。jetson_clocksnvpmodelはNanoの場合0か1の2者選択のみのようでした。0が最大で1が最小です。Example(GPUを使ったサンプル)を実行させたものですが、この段階でスピード的にはTX2でした(思っていたよりかなり早かった)。Openframeworksが動くか?動きました。過去に紹介したTX2の手順で基本的に10.01のインストールが可能です。buildsを使う必要があります。tess2及びkissのライブラリも再コンパイルが必要でした。バージョンアップされる可能性があるので、インストール方法は時期を改めて紹介します。builds内容を見ると次期バージョンでは標準でOpenCV4(注目すべきはdnn!!)が使えるようです。Proとスピードが変わらない....。っ!!DARKNET(YOLO)のインストール今までの経験上インストールにはさほど問題なかったのですが、今回も、これを使わせていただきました。ソース内容が時間単位で変更されています、この方は一体どのくらいの能力を秘めてるんでしょう。DARKNETを利用したC++でのソフト開発はなかなかハードルが高いのですが、最後の説明のように本来のスピードを保ったままOpenframeworksに移植できています。Nanoで使うには、Makefileの修正が必要です。以下最初の方で赤文字部分の修正が必要(6行の修正)。NanoはTX1とCUDAアーキテクチャが同じのようです(ここでちょっと手こずりました)。コマンド一発で、一応DARKNETが動く環境ができます。4/27:追記----------------------------------------------------------------------------.bashにCUDAのパスを追加しないとnvccが使えないのでエラーが出ます。arch=compute_62,code=[sm_62,compute_62]*********************************************************ジャー肝心のAI認識です。結論的にはTX2とかXavier並の性能に追いつかせることは無理のようです、いつものようにコツが必要。YOLO3とかYOLO2では満足なスピードは得られません。遅いし、YOLO3に至ってはアプリに組み込むとメモリが完全に不足する雰囲気です。YOLO3がかなりのスピードで実行できているのが気になるところ。YOLO3の学習済みデータの大きさは、標準(大体200MB前後)のものより1/6(35MB)程度なので認識率は正直?です。1080Tilossが最小値から上がってきているの8000回目で止めています。ちなみに採用したデータは6000回目のもので、この時の計算時間はなんとわずか45分でした。グラフが大きく振れているので認識のばらつきがある気配...。以下はYolov2の学習状況ですが、比べてみるとLossの下限を含めてずいぶん違うことが分かると思います。v2でも6000回がベターで学習時間は2時間程度でした。今回はCUDNN_HALF設定(16ビット浮動小数点)なので前回より早かった可能性があります。今回のように本格的な学習作業(画像の大きなモノ)は、nanoではトライするだけ無駄と思われますのでご注意を.....。メモリーが不足して初期段階で止まってしまうと思われます。今回nanoテスト用に使ったサンプルソース(以下の動画)は、元々XavierでYOLO3を動かすために自分で作ったものです。PI3で赤外線センサーカメラ表示処理をした後(左側のディスプレイ)、WIFIで画像データをNanoに送り、認識が確実になるよう画像拡大補間やノイズ処理などを施した上で、画像認識をさせた後(右側のディスプレイ)、その認識座標他を再度PI3に送って認識結果を表示させています。「おうちクラウドAI」と名付けました。離れたところにPI3を置けば、PI3でリアルタイム画像認識をしているような感覚です。赤外線センサーは、Nano直付けでも良い(ただしSPI設定はかなり難しいので今後に期待)のですが、使用用途から考えてWiFiの方が断然有利なので、あえて手間のかかる処理を加えて画像と各種データの送受信をしています。この程度のAI認識ではTinyでも特に問題が無いことが分かります。PI3、Nano双方でGPIOが使えるので応用は無限大!!何よりスピードが早い。今回はLEPTON3(FLIRの赤外線センサーカメラ)の画像読み込みにPIを使ってますが、ESP8266でも可能。3年間積み上げてきたものです。nanoで動くとなると感慨もひとしおです。Nanoって....。判断は皆さんにお任せします。Nanoの記事を追加しました。takesan.hatenablog.com追伸おかげさまで、今まで作ったすべてのモノをさらに進化させて展示することができました。いろいろな意見をいただいて、とても有意義な2日間となりました。みなさんありがとうございました。様々なディバイスで独立した処理を実行しています。BosonとLeptonは今僕にできるサイコウの詳細な表示が実現できました。XavierもnanoもiPhoneやm5Stackでも!!。この画像に写ってるだけでも「おうちクラウドAI」は2系統で同時実行してます。使ってみる!!Tweetもっと読むコメントを書く2019-03-19素敵な花が咲きました。世界洋ラン展で買ってきたパフィオペディラムです。本当はすべてが小豆色のはずだったのですが、2年間育ててやっと咲いた花が「点花」と呼ばれる斑点の付いた花びらでした。パフィオペディラムには原種と整形花があって、この花は整形花に属します。要するに人の手によって改良が加えられた花です。愛好家では必衰の掛け合わせによる親株の名前も全く分からなくなりました。この種の花は独特の人工的な表情があって、好き嫌いがあります。私もどちらかというとあまり好きではありませんでした。購入してから2年目に咲いた花は、少し小さめでしたが、透き通るような白と清楚な緑。鮮やかで全体にちりばめられた小豆色の点と形が、派手と言うよりも清々しくとても印象的でした。月日がたち、毎年咲いていた株も少しずつ小さくなって、5年ぐらい前から花が全く咲かなくなりました。夏場は毎年玄関先の日陰に置いて、冬はいつもの窓際。私にとってはあまりにも素晴らしかったこの花の印象が忘れられなかったんですね。その間に株がどんどん大きくなりました。去年の11月花芽が付いてとても喜んでから5ヶ月。こんな花が咲きました。今までで一番大きな花です。20:09素敵な花が咲きました。さんのDarknetを使って追加学習させてみました。さんのDarknetの場合はhttps://github.com/AlexeyAB/darknetが全てです。できるため、認識スピードがかなり向上できる他に、最近分かったことですが、学習の最適ポイントが掴みやすいなど、かなりの優れものでした(解説を良く読んでみればわかるのですが.....)。前回の学習ではtakesan.hatenablog.comジャンケンの3クラスのみの学習をさせたのですが、どうしてもグーが人間の顔と勘違いしやすい傾向がありました。元画像が赤外線カメラなので、そのような傾向があるかとは思いますが、新たに顔を追加学習させたら、さらに良い結果になりそうな気配です。「どうしたら追加学習できるのか?」ということが、今回のテーマです。顔がGooになってしまうことがある....のですが、顔データを追加学習させると、こうなります⇩この画像はLEPTON3.0はPI3に接続。Xavierで画像表示とジャンケン認識をさせてます。説明を書いてもかえって分かりにくくなるので、今回は要点のみとします。顔の動画を撮影して、2000枚程度の画像を作成した。中にあるpredefined_class.txtに4番目のクラス(今回はFace)を追加する。別のフォルダで顔のみをラベリングして作ったデータを、前回のデータフォルダにコピーする。前回のアノテーション済みの画像の中に顔が写っている場合は、追加指定を行う。入力ミスで思い当たりのないクラスが増えていることがある。自分で設定したクラスがひとりでにできていたら、前に遡って必ずその部分を消すことが必要。これをしないと、学習中意味不明のエラーまたはメモリオーバーが表示されて、悩まされることになる。外してビルドし直した。有効なのは、WEIGHTとHEIGHTの数値を大きくしてトレーニングすること。一般的には416x416。精度を上げるには608x608または832x832とする。yolov3の場合608x608で学習させると、私の環境ではメモリーオーバーで止まる。