シールvsニューラルネットワーク2.またはRaspberry ZeroでSqueezeNet v.1.1をリアルタイムで(ほぼ)実行します

みなさんこんにちは!



それほど深刻ではなく、実用面で特に有用でない最初の部分を書いた後、私の良心は私をわずかに飲み込んだ。 そして、私は始めたことを終わらせることにしました。 つまり、ニューラルネットワークの同じ実装を選択して、Rasperry Pi Zero Wでリアルタイムに(もちろん、このようなハードウェアで可能な限り)実行します。 彼女を実生活のデータから追い出し、Habréの結果を明らかにする。



ご注意 実行可能なコードと、最初の部分よりもカットされた猫がいくつかあります。 写真では、それぞれコットとタラ。



画像






どのネットワークを選択しますか?



ラズベリー鉄の弱さのために、ニューラルネットワークの実現の選択肢は小さいことを思い出します。 すなわち:



1. SqueezeNet。

2. YOLOv3 Tiny。

3. MobileNet。

4. ShuffleNet。



最初の部分でSqueezeNetを支持する選択はどの程度正しかったのですか? したがって、漠然とした疑念に苦しめられて、誰かが私の前にそのような質問をしたことがある場合、私はグーグルに決めました。 彼は不思議に思って詳細に調査したことが判明しました。 希望する人はソースを参照できます。 私はそれから単一の写真に自分自身を制限します:



画像



画像から、ImageNetデータセットでトレーニングされた異なるモデルの1つの画像の処理時間は、SqueezeNet v.1.1で最も短いことがわかります。 これを行動の指針とする。 YOLOv3は比較に含まれていませんでしたが、覚えている限りでは、YOLOはMobileNetよりも高価です。 つまり また、SqueezeNetに比べて速度が劣っています。



選択したネットワークの実装



ImageNetデータセット(Caffeフレームワーク)でトレーニングされたSqueezeNetの重みとトポロジーはGitHubで見つけることができます。 念のため、後で比較できるように両方のバージョンをダウンロードしました。 ImageNetを選ぶ理由 この利用可能なすべてのセットには、クラスの最大数(1000個)があります。そのため、ニューラルネットワークの結果は非常に興味深いものになるでしょう。



今回は、Raspberry Zeroがカメラからのフレーム認識をどのように扱うかを見ていきます。 ここに彼は、今日の投稿の謙虚な働き者です。



画像



コードの基礎として、 最初のパートで述べたAdrian Rosebrockブログ、つまりここからソースを取得しました 。 しかし、私はそれを大幅に耕さなければなりませんでした:



1.モデルをMobileNetSSDとSqueezeNetで置き換えます。

2.条項1の実装により、クラスの数が1000に拡張されました。しかし同時に、マルチカラーフレーム(SSD機能)でオブジェクトを強調表示する機能は削除されました。

3.コマンドラインからの引数の受け取りを削除します(何らかの理由で、このようなパラメーターの入力は煩わしいです)。

4. VideoStreamメソッドと、Adrianに愛されているimutilsライブラリを削除します。 当初、この方法はカメラからビデオストリームを取得するために使用されていました。 しかし、私のカメラをRaspberry Zeroに接続すると、愚かにも機能せず、「違法な指示」のようなものが出ました。

5.認識された画像にフレームレート(FPS)を追加し、FPS計算を書き換えます。

6.保存フレームを作成して、この投稿を書き込みます。



Rapbian Stretch OSを搭載したraspberry、Python 3.5.3、およびpip3を介してインストールされたOpenCV 3.4.1をインストールすると、次のことが判明し、開始されました。



ここにコード
import picamera from picamera.array import PiRGBArray import numpy as np import time from time import sleep import datetime as dt import cv2 #    prototxt = 'models/squeezenet_v1.1.prototxt' model = 'models/squeezenet_v1.1.caffemodel' labels = 'models/synset_words.txt' #    rows = open(labels).read().strip().split("\n") classes = [r[r.find(" ") + 1:].split(",")[0] for r in rows] #    print("[INFO] loading model...") net = cv2.dnn.readNetFromCaffe(prototxt, model) print("[INFO] starting video stream...") #   camera = picamera.PiCamera() camera.resolution = (640, 480) camera.framerate = 25 #   camera.start_preview() sleep(1) camera.stop_preview() #     raw rawCapture = PiRGBArray(camera) #   FPS t0 = time.time() #     for frame in camera.capture_continuous(rawCapture, format="bgr", use_video_port=True): #    blob frame = rawCapture.array blob = cv2.dnn.blobFromImage(frame, 1, (224, 224), (104, 117, 124)) #    blob,     net.setInput(blob) preds = net.forward() preds = preds.reshape((1, len(classes))) idxs = int(np.argsort(preds[0])[::-1][:1]) #  FPS FPS = 1/(time.time() - t0) t0 = time.time() #    ,   FPS,    text = "Label: {}, p = {:.2f}%, fps = {:.2f}".format(classes[idxs], preds[0][idxs] * 100, FPS) cv2.putText(frame, text, (5, 25), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2) print(text) cv2.imshow("Frame", frame) #     Raspberry fname = 'pic_' + dt.datetime.now().strftime('%Y-%m-%d_%H-%M-%S') + '.jpg' cv2.imwrite(fname, frame) #    SD  key = cv2.waitKey(1) & 0xFF #    `q`    if key == ord("q"): break #   raw       rawCapture.truncate(0) print("[INFO] video stream is terminated") #    cv2.destroyAllWindows() camera.close()
      
      







結果



コードは、このフォームで次に認識されるフレームであるRaspberryに接続されたモニターの画面に表示されます。 フレームの上部には、最も可能性の高いクラスのみが表示されます。



画像



そのため、コンピュータマウスは非常に高い確率でマウスとして識別されました。 同時に、画像は0.34 FPSの頻度(つまり、約3秒ごと)で更新されます。 カメラを持って次のフレームが処理されるのを待つのは少し面倒ですが、生きることはできます。 ところで、SDカード上のフレームの保存を削除すると、処理速度は0.37〜0.38 FPSに増加します。 分散させる方法は他にもあります。 いずれにせよ、次の投稿のためにこの質問を残します。



それとは別に、ホワイトバランスをおaびします。 実際には、バックライトがオンになっているIRカメラはRapberryに接続されていたため、ほとんどのフレームはかなり奇妙に見えます。 しかし、ニューラルネットワークの各ヒットはより価値があります。 明らかに、トレーニングセットのホワイトバランスはより正確でした。 さらに、読者がニューラルネットワークを見るのとほぼ同じように、生のフレームのみを挿入することにしました。



まず、SqueezeNetバージョン1.0(左側のフレーム)と1.1(右側)の動作を比較しましょう。



画像



バージョン1.1は1.0の2.5倍高速で動作することがわかります(0.34 FPS対0.15)。 速度のゲインは明白です。 この例の認識精度について結論を下す価値はありません。精度は、オブジェクト、照明、グレア、影などに対するカメラの位置に大きく依存するためです。



v.1.0に対するv1.1のこのような大幅な速度の利点を考慮して、その後SqueezeNet v.1.1のみが使用されました。 モデルのパフォーマンスを評価するために、 手元に来たさまざまなオブジェクトにカメラを向け、出力で次のフレームを受け取りました。



画像



キーボードはマウスよりも悪いです。 おそらく、トレーニングセットでは、ほとんどのキーボードは白色でした。



画像



画面をオンにすると、携帯電話はかなり明確に定義されます。 スクリーンがオフのセルは、ニューラルネットワークをセルとしてカウントしません。



画像



空のカップは、コーヒーカップとしてかなり許容できると定義されています。 これまでのところ、すべてが順調に進んでいます。



画像



はさみはさらにひどくなり、ネットでは頑固にヘアクリップとして定義されています。 ただし、ブルズアイに当たらない場合は、少なくともリンゴの木)



タスクを複雑にしましょう



ブタのニューラルネットワークに注意を要することを試してみましょう。 手作りの子供用おもちゃに出会いました。 私はほとんどの読者がそれをおもちゃの猫だと思っていると信じています。 私たちの初歩的な人工知能によって何が考えられるのだろうか。



画像



左側のフレームでは、IRライトがファブリックからすべてのストリップを消去しました。 その結果、おもちゃはかなりまともな確率で酸素マスクとして定義されました。 どうして? おもちゃの形は本当に酸素マスクに似ています。



右側のフレームでは、指をIRハイライトで覆ったため、おもちゃに縞模様が現れ、ホワイトバランスがより信頼できるものになりました。 実際、これはこの投稿で多かれ少なかれ普通に見える唯一のフレームです。 しかし、ニューラルネットワークには、混乱したイメージの詳細が非常に豊富にあります。 彼女はそのおもちゃをスウェットシャツだと特定しました。 これも「空への指」のようには見えないと言わなければなりません。 「リンゴの木」になければ、少なくともリンゴ園でヒットします)。



さて、私たちは行動のクライマックスにスムーズに近づきました。 最初の投稿で詳しく説明されている、議論の余地のない勝者がリング入ります。 また、最初のフレームからニューラルネットワークの脳を簡単に取り出します。



画像



猫が実際にその位置を変えないのは不思議ですが、毎回異なって決定されます。 そして、この観点から、それはスカンクに最も似ています。 2番目は、ハムスターに似ています。 角度を変えてみましょう。



画像



ええ、あなたが上から猫を撮影した場合、それは正しく決定されますが、フレーム内の猫の体の位置を少し変更するだけで、ニューラルネットワークのためにそれは犬になります-シベリアンハスキーとマラミュート(エスキモーそり犬)のそれぞれ。



画像



そして、この選択は、異なる品種の犬が猫のそれぞれの別々のフレームで定義されるという点で美しいです。 さらに、品種は繰り返されません)



画像



ところで、ニューラルネットワークでは、これが犬ではなく猫であることが明らかになります。 つまり、SqueezeNet v.1.1は、分析が困難なこのようなオブジェクトであっても、それでも自身を証明することができました。 テストの開始時にオブジェクトを認識し、最後に猫を猫として認識するというニューラルネットワークの成功を考えると、今回は堅実な戦闘の引き分けを宣言します)



まあ、それがすべてです。 ラズベリーとアニメーションオブジェクトと無生物オブジェクトのビューになったオブジェクトで提案されたコードを試してみてください。 Rapberry Pi B +でFPSを測定している人には特に感謝します。 データを送信した人を参照して、この投稿に結果を含めることを約束します。 私はそれが1 FPSよりもかなり大きくなるはずだと信じています!



この投稿からの情報の一部が娯楽や教育目的に役立つこと、そして誰かが新しいアイデアを思い付くことさえあることを願っています。



良い週をお過ごしください! またお会いしましょう)



画像



UPD1:Raspberry Pi 3B +では、上記のスクリプトは小さなFPSで2の頻度で動作します。



UPD2:Movidius NCSを使用したRPi 3B +では、スクリプトは6 FPSで実行されます。



All Articles