Up <target の方向に向く>をプログラミング 作成: 2021-05-21
更新: 2021-05-21


    PC から ssh -X 接続
    $ source ./venv/bin/activate
    (venv) $ cd ~/Tensorflow-YOLOv3
    (venv) $ vi facing.py
    #!/usr/bin/env python ##### モデル tiny YOLO の設定 ################# from core.utils import load_class_names, load_image, draw_boxes, draw_boxes_frame from core.yolo_tiny import YOLOv3_tiny from core.yolo import YOLOv3 # object のクラス class_names, n_classes = load_class_names() iou_threshold = 0.1 confidence_threshold = 0.25 model = YOLOv3_tiny(n_classes=n_classes, iou_threshold=iou_threshold, confidence_threshold=confidence_threshold) import tensorflow as tf inputs = tf.placeholder(tf.float32, [1, *model.input_size, 3]) detections = model(inputs) saver = tf.train.Saver(tf.global_variables(scope=model.scope)) ##### GoPiGo motor ########################## from easygopigo3 import EasyGoPiGo3 egpg = EasyGoPiGo3() from time import sleep egpg.set_speed(10) def rotation( t ): print('t:' + str(t)) if t > 0: egpg.right() sleep(t) else: egpg.left() sleep(-t) egpg.stop() ##### カメラ映像画面の dx に対する GoPiGo 回転時間 t ############## def pixel2t( dx ): abs_dx = abs( dx ) if abs_dx < 60: return round( dx * 3 / 50 ) elif abs_dx < 110: return round( dx * 4.5 / 100 ) elif abs_dx < 160: return round( dx * 6 / 150 ) elif abs_dx < 210: return round( dx * 9 / 200 ) elif abs_dx < 310: return round( dx * 12 / 300 ) else: return round( 12 * dx / abs_dx ) ##### カメラ取込画像 ########################## # ヨコ, タテ CAMERA_WIDTH = 640 CAMERA_HEIGHT = 480 # 中心 img_center_x = CAMERA_WIDTH/2 img_center_y = CAMERA_HEIGHT/2 ##### トラッキング対象 ################# target_class = 'sports ball' # 配列 class_names における target object の番号 target_n を求める for n in range(len(class_names)): if class_names[n] == target_class: target_n = n break ##### exit プロセス ################# import cv2 import sys def destroy(): # GoPiGo クリーンアップ egpg.reset_all() #カメラキャプチャを停止 cap.release() #ストリーミングウインドを閉じる cv2.destroyAllWindows() #プログラムを終了 sys.exit() ##### START ########################## with tf.Session() as sess: # モデル tiny YOLO の読み込み saver.restore(sess, './weights/model-tiny.ckpt') # カメラ映像の読み込み # カメラの番号:0 cap = cv2.VideoCapture(0) while True: ret, frame = cap.read() # ヨコ,タテ frame_size = (frame.shape[1], frame.shape[0]) resized_frame = cv2.resize(frame, dsize=tuple((x) for x in model.input_size[::-1]), interpolation=cv2.INTER_NEAREST) result = sess.run(detections, feed_dict={inputs: [resized_frame]}) #カメラ映像の表示 draw_boxes_frame(frame, frame_size, result, class_names, model.input_size) cv2.imshow('frame', frame) #### target_class の検出 #### boxes_dict = result[0] boxes = boxes_dict[target_n] resize_factor = (frame_size[0] / model.input_size[1], frame_size[1] / model.input_size[0]) if( len(boxes) != 0): print("\nターゲット発見") for box in boxes: coordinates = box[:4] coordinates = [int(coordinates[i] * resize_factor[i % 2]) for i in range(4)] # object の中心 object_center_x = int((coordinates[0]+coordinates[2])/2) # 画像中心からの object 中心のズレ dx = object_center_x - img_center_x print("中心ズレ:" + str(dx)) # dx > 20 ならば,GoPiGo の回転 if abs(dx) > 20: rotation( pixel2t( dx ) ) # 残りの box は取り上げない break # <for box in boxes> ここまで # <if( len(boxes) != 0)> ここまで # 画像ウィンドウをアクティブにして 'q' キーを押すと, break if cv2.waitKey(10) & 0xFF == ord('q'): destroy()


    (venv) $ chmod +x facing.py
    (venv) $ ./facing.py


    このプログラムを実行すると,カメラ画像の読み込みの遅延のために,つぎのようなことが起こる:
      ターゲット発見 中心ズレ:184.0 t:8 ターゲット発見 中心ズレ:183.0 t:8 ターゲット発見 中心ズレ:183.0 t:8 ターゲット発見 中心ズレ:184.0 t:8 ターゲット発見 中心ズレ:184.0 t:8 ターゲット発見 中心ズレ:183.0 t:8
    この場合,GoPiGo は 8 × 6 = 48 秒間,同一方向に回転を続けることになる。

    このトラブル──同じ画像が繰り返し読み込まれる──は,ハードウェアの限界によるものなので,どうしようもない。
    当座の対処として,object_center_x の値が前のループのときの値と ≦ 20 の違いしかないときは,rotation( pixel2t( dx ) ) をスキップするようにプログラムしておく。
    また,egpg.set_speed(10) は遅過ぎるので,egpg.set_speed(50) に変更し,この変更に合わせて pixel2t( dx ) の定義の中の数値を変更する:

    (venv) $ vi facing.py
    #!/usr/bin/env python ##### モデル tiny YOLO の設定 ################# from core.utils import load_class_names, load_image, draw_boxes, draw_boxes_frame from core.yolo_tiny import YOLOv3_tiny from core.yolo import YOLOv3 # object のクラス class_names, n_classes = load_class_names() iou_threshold = 0.1 confidence_threshold = 0.25 model = YOLOv3_tiny(n_classes=n_classes, iou_threshold=iou_threshold, confidence_threshold=confidence_threshold) import tensorflow as tf inputs = tf.placeholder(tf.float32, [1, *model.input_size, 3]) detections = model(inputs) saver = tf.train.Saver(tf.global_variables(scope=model.scope)) ##### GoPiGo motor ########################## from easygopigo3 import EasyGoPiGo3 egpg = EasyGoPiGo3() from time import sleep egpg.set_speed(50) def rotation( t ): print('t:' + str(t)) if t > 0: egpg.right() sleep(t) else: egpg.left() sleep(-t) egpg.stop() ##### カメラ映像画面の dx に対する GoPiGo 回転時間 t ############## def pixel2t( dx ): abs_dx = abs( dx ) if abs_dx < 60: return dx * 0.6 / 50 elif abs_dx < 110: return dx * 0.9 / 100 elif abs_dx < 160: return dx * 1.2 / 150 elif abs_dx < 210: return dx * 2.2 / 200 elif abs_dx < 310: return dx * 2.4 / 300 else: return 2.4 * dx / abs_dx ##### カメラ取込画像 ########################## # ヨコ, タテ CAMERA_WIDTH = 640 CAMERA_HEIGHT = 480 # 中心 img_center_x = CAMERA_WIDTH/2 ##### トラッキング対象 ################# target_class = 'sports ball' # 配列 class_names における target object の番号 target_n を求める for n in range(len(class_names)): if class_names[n] == target_class: target_n = n break ##### exit プロセス ################# import cv2 import sys def destroy(): # GoPiGo クリーンアップ egpg.reset_all() #カメラキャプチャを停止 cap.release() #ストリーミングウインドを閉じる cv2.destroyAllWindows() #プログラムを終了 sys.exit() ##### START ########################## with tf.Session() as sess: # モデル tiny YOLO の読み込み saver.restore(sess, './weights/model-tiny.ckpt') # カメラ映像の読み込み # カメラの番号:0 cap = cv2.VideoCapture(0) # 前回ループのときの object_center_x 値を留める変数 object_center_x_last = img_center_x while True: ret, frame = cap.read() # ヨコ,タテ frame_size = (frame.shape[1], frame.shape[0]) resized_frame = cv2.resize(frame, dsize=tuple((x) for x in model.input_size[::-1]), interpolation=cv2.INTER_NEAREST) result = sess.run(detections, feed_dict={inputs: [resized_frame]}) #カメラ映像の表示 draw_boxes_frame(frame, frame_size, result, class_names, model.input_size) cv2.imshow('frame', frame) #### target_class の検出 #### boxes_dict = result[0] boxes = boxes_dict[target_n] resize_factor = (frame_size[0] / model.input_size[1], frame_size[1] / model.input_size[0]) if( len(boxes) != 0): for box in boxes: coordinates = box[:4] coordinates = [int(coordinates[i] * resize_factor[i % 2]) for i in range(4)] # object の中心 object_center_x = int((coordinates[0]+coordinates[2])/2) if abs( object_center_x - object_center_x_last ) > 20: print("\nターゲット発見") object_center_x_last = object_center_x # 画像中心からの object 中心のズレ dx = object_center_x - img_center_x print("中心ズレ:" + str(dx)) # dx > 20 ならば,GoPiGo の回転 if abs(dx) > 20: rotation( pixel2t( dx ) ) # 残りの box は取り上げない break # <for box in boxes> ここまで # <if( len(boxes) != 0)> ここまで # 画像ウィンドウをアクティブにして 'q' キーを押すと, break if cv2.waitKey(10) & 0xFF == ord('q'): destroy()

    (venv) $ ./facing.py