OpenCVを搭載したRaspberry Piロボットタンク

かつては、ArduinoとRaspberry Piでロボットマシンを組み立てることが好きでした。 私はコンストラクターをプレイするのが好きでしたが、もっと何かが欲しかったのです。



そしてかつて、Aliexpressをさまよう、私はタンク用のアルミニウムシャーシに出会いました。 この作成は、カートと比較してフェラーリのようなプラスチック車と比較して見えました。



私は自分自身に新年の贈り物を作り、戦車が到着し、組み立てられ、それからそれを復活させなければなりませんでした。 タイプライターからラズベリー自体、電力変換器、モーターコントローラー、バッテリーを取り外しました。 これらはすべて戦車に搭載され、喜んで獲得しました。



さらに、タキシング用のシンプルなREST APIがpythonとAndroidで記述されました。これは、このAPIをプルすることでタンクを制御できるのと同じシンプルなプログラムです。



戦車は撃たなければならず、次のステップは彼のカメラの外観でした。 カメラ本体で推測することはできませんでした-開いた状態では、彼はカメラを保持せず、閉じた状態では-レンズがカメラから飛び出したほどきつい。 苦しんでいたので、私は単にカメラのテープをハウジングのカバーに貼り付けました。 これで、戦車は部屋を走り回るだけでなく、写真を撮ることもできました。



画像



戦車が自宅の車よりも優れていることは注目に値します。堅い床やカーペットの上を走るのとは違いません。 車輪の移動は、回転できないほど柔らかい柔らかいカーペットの上を滑ります。



さらに、カメラからの写真に依存して、自律航法の方向にタンクを開発したかった。 私はコンピュータービジョンの世界に飛び込み、OpenCVを発見しなければなりませんでした。 それはすべて、色と輪郭の認識から始まりました-赤い円を紙に印刷し、テレビに接着して、見つかるまでロボットを回転させました。



アイデアは、部屋に見えるオブジェクト(ソファ、テレビ、テーブル)をカラフルな円でマークし、ロボットに色でナビゲートする方法を教えることでした。



OpenCVを使用して、目的の色の輪郭(許容範囲内)が検索され、次に輪郭の中から円が検索されました。



主な問題は、任意のオブジェクトの適切な色のランダムな円であると思われました。



ただし、主な問題は、照明によって色が非常に変化しやすいように見えることであるため、(たとえば)赤が認識される範囲は、元の色に非常に遠く似た色合いに拡大する必要がありました。 または、画像から目的の色を選択しますが、いずれの場合も赤ではなく、茶色の色合いでした。



赤い丸を検索:



import cv2 import numpy as np import sys def mask_color(img, c1, c2): img = cv2.medianBlur(img, 5) hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) mask = cv2.inRange(hsv, c1, c2) mask = cv2.erode(mask, None, iterations=2) mask = cv2.dilate(mask, None, iterations=2) return mask def find_contours(img): gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) blurred = cv2.GaussianBlur(gray, (5, 5), 0) thresh = cv2.threshold(blurred, 30, 255, cv2.THRESH_BINARY)[1] thresh = cv2.bitwise_not(thresh) im2, cnts, hierarchy = cv2.findContours(thresh, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE) cp_img = img.copy() cv2.drawContours(cp_img, cnts, -1, (0,255,0), 3) return cp_img def find_circles(img): gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) blurred = cv2.medianBlur(gray,5) circles = cv2.HoughCircles(blurred,cv2.HOUGH_GRADIENT,1,20,param1=50,param2=30,minRadius=0,maxRadius=0) cimg = img if circles is not None: circles = np.uint16(np.around(circles)) for i in circles[0,:]: cv2.circle(img,(i[0],i[1]),i[2],(255,0,0),2) cv2.circle(img,(i[0],i[1]),2,(0,0,255),3) print "C", i[0],i[1],i[2] return cimg def find_circle(img, rgb): tolerance = 4 hsv = cv2.cvtColor(rgb, cv2.COLOR_BGR2HSV) H = hsv[0][0][0] c1 = (H - tolerance, 100, 100) c2 = (H + tolerance, 255, 255) c_mask = mask_color(img, c1, c2) rgb = cv2.cvtColor(c_mask,cv2.COLOR_GRAY2RGB) cont_img = find_contours(rgb) circ_img = find_circles(cont_img) cv2.imshow("Image", circ_img) cv2.waitKey(0) if __name__ == '__main__': img_name = sys.argv[1] img = cv2.imread(img_name) rgb = np.uint8([[[0, 0, 255 ]]]) find_circle(img, rgb)
      
      





色の認識が停止し始め、猫を写真狩りするためのタンクを使用して、Haarカスケードに気を取られました。 猫は自分自身をうまく偽装し、半分のケースでカスケードをミスさせました(誰も知らない場合、OpenCVにはシールで特別に訓練されたHaarカスケードが付属しています-それを使って使用してください)。



猫の狩猟はロボットに有益な結果をもたらしました-静的カメラで狩猟物体を捕まえることが常に可能ではなかったため、2つのサーボモーター(およびRaspberryを介してそれらを制御するPWMモジュール)を備えた三脚を設置しました。



部屋の写真から絞り出すことができるもののトピックに関する私の研究を続けて、私は自然にニューラルネットワークに来ました。 Tensorflowチュートリアルを飲み込んだ後、タンクの写真の検出器で処理しました。結果は有望でした。テレビ、テーブル、ソファ、猫、冷蔵庫がエラーなく認識されました。



これらの実験はコンピューター上で実行されましたが、TFをRaspberry Piに転送するということは、小さなことでした。 幸いなことに、GitHubにはユニークな人が住んでいます。GitHubは忍耐力があり、すべての依存関係と長い時間のコンパイル時間のインストールを破り、収集したRaspberry PiのTensorflowを共有しました。



ただし、このトピックをさらに研究した結果、OpenCVが停止せず、その貢献者がTNNで学習したニューラルネットワークとの統合を提供するDNNモジュール(Deep Neural Networks)をリリースしたことが明らかになりました。 このソリューションは開発がはるかに便利であり、TF自体も必要ありません。 TF向けのモバイルSSDニューラルネットワークの最新バージョンは、OpenCVの最新バージョンによってもはや取り上げられなくなったため、少し手間をかける必要がありました。 私は見なければなりませんでした

Mobile SSDの動作バージョンを確認してください。 さらに、DNNはOpenCV 3.4でのみ正常に機能しますが、Raspberryのこのバージョンは見つかりませんでした。 TensorFlowをいじるよりもずっと簡単なので、自分で収集する必要がありました。 同時に、Raspbian(Stretch)の最新の重みでOpenCVをアセンブルすることはできませんでしたが、前世代(Jessie)の最新バージョンではすべてが正常に起動しました。



Tensorflowを使用せずにDNNを使用したサンプルコード。



オブジェクトの名前の原因となるいくつかのファイルがTFからプルされ、TF自体への依存が削除されました(ファイルからの読み取りのみがありました)。

Githubソースコード。



 import cv2 as cv import tf_labels import sys DNN_PATH = "---path-to:ssd_mobilenet_v1_coco_11_06_2017/frozen_inference_graph.pb" DNN_TXT_PATH = "--path-to:ssd_mobilenet_v1_coco.pbtxt" LABELS_PATH = "--path-to:mscoco_label_map.pbtxt" tf_labels.initLabels(PATH_TO_LABELS) cvNet = cv.dnn.readNetFromTensorflow(pb_path, pb_txt) img = cv.imread(sys.argv[1]) rows = img.shape[0] cols = img.shape[1] cvNet.setInput(cv.dnn.blobFromImage(img, 1.0/127.5, (300, 300), (127.5, 127.5, 127.5), swapRB=True, crop=False)) cvOut = cvNet.forward() for detection in cvOut[0,0,:,:]: score = float(detection[2]) if score > 0.25: left = int(detection[3] * cols) top = int(detection[4] * rows) right = int(detection[5] * cols) bottom = int(detection[6] * rows) label = tf_labels.getLabel(int(detection[1])) print(label, score, left, top, right, bottom) text_color = (23, 230, 210) cv.rectangle(img, (left, top), (right, bottom), text_color, thickness=2) cv.putText(img, label, (left, top), cv.FONT_HERSHEY_SIMPLEX, 1, text_color, 2) cv.imshow('img', img) cv.waitKey()
      
      





一般的に、現在、戦車の写真はニューラルネットワークによって認識できます。これは、ランドマークの認識に関してナビゲーションの非常に重要なステップです。 それにもかかわらず、完全なナビゲーションのためのいくつかの写真では十分ではなく、障害物までの距離を測定する必要がありました。 そのため、ロボットはエコーサウンダーに見えました。 音響器をRaspberryに接続するには、少し作業する必要があります。音響器は信号を5Vに戻し、Raspberryは3.3Vを受け取ります。 膝の上では、この問題は主にブラッドボード抵抗器によって解決されますが、私はロボットにそのようなスカムバッグを作りたくありませんでした。 その結果、必要なすべてを行うLevel Shifterチップが見つかりました。これは指の爪のサイズです。



さらに、ロボットの外観に夢中になりました-超小型回路とエコーサウンダー付きのカメラが段ボールに貼り付けられているのはあまり好きではありませんでした。 私たちの世界での技術の発展により、時間とお金を合理的に投資してレーザーでプラスチックを切断することができます。 一般に、レーザーマシンを使用したワークショップを見つけ、この素晴らしいマシンの指示を少し時間をかけて研究しました。最初の試みからは程遠いマイクロチップ用パネルとエコーサウンダー付きカメラを切り取りました。



画像



すべてが自律航法の準備ができていますが、タスクはそれほど単純ではないことが判明し、最初の試みで私は幾分埋没しました。 私は休憩して、よく考えて、アナログを勉強することにしました。 おそらく、このナビゲーションは別の記事のトピックとして役立つでしょう。



将来の使用のベースとしてロボットを提供するRESTインターフェース:



 GET /ping GET /version GET /name GET /dist POST /fwd/on POST /fwd/off POST /back/on POST /back/off POST /left/on POST /left/off POST /right/on POST /right/off POST /photo/make GET /photo/:phid GET /photo/list POST /cam/up POST /cam/down POST /cam/right POST /cam/left POST /detect/haar/:phid POST /detect/dnn/:phid
      
      





参照:



  1. OpenCV DNN
  2. OpenCV-3.4.1と互換性のあるSSD MobileNet
  3. Raspberry PiのTensorflow
  4. GitHubロボットのRESTサーバーコード
  5. Raspbian JessieのDNNサポートを使用してOpenCV 3.4.1をビルドする



All Articles