Up tracking.py 作成 作成: 2021-05-13
更新: 2021-05-18


    PC から ssh -X 接続
    $ source ./venv/bin/activate
    (venv) $ cd ~/Tensorflow-YOLOv3
    (venv) $ vi tracking.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)) ##### servo の設定 ########################## import RPi.GPIO as GPIO # GPIOの設定 GPIO.setmode(GPIO.BOARD) pan_servo_pin = 16 tilt_servo_pin = 18 GPIO.setup(pan_servo_pin, GPIO.OUT) GPIO.setup(tilt_servo_pin, GPIO.OUT) # PWM (Pulse Width Modulation) の設定 # SG90 の周波数は50Hz (周期20ms) pan_servo_pwm = GPIO.PWM(pan_servo_pin, 50) tilt_servo_pwm = GPIO.PWM(tilt_servo_pin, 50) ##### servo の動作 (関数) ########################## from time import sleep # 指定角度 (単位 : 度) にサーボを定位 def servo_angle(servo, degree): duty = 9.5 * degree / 180 + 7.25 if servo == 'pan' : pan_servo_pwm.ChangeDutyCycle(duty) else: tilt_servo_pwm.ChangeDutyCycle(duty) sleep(2) ##### カメラ取込画像 ########################## # ヨコ, タテ CAMERA_WIDTH = 640 CAMERA_HEIGHT = 480 # 中心 img_center_x = CAMERA_WIDTH/2 img_center_y = CAMERA_HEIGHT/2 ##### カメラ映像画面の dx, dy に対するサーボの dpan, dtilt の比例定数 (実験値) pixel2deg = -0.1 ##### トラッキング対象 ################# 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(): #サーボモータをストップ servo_angle('pan', 0) pan_servo_pwm.stop() servo_angle('tilt', 0) tilt_servo_pwm.stop() #GPIOをクリーンアップ GPIO.cleanup() #カメラキャプチャを停止 cap.release() #ストリーミングウインドを閉じる cv2.destroyAllWindows() #プログラムを終了 sys.exit() ##### START ########################## # pan, tilt を 0° (Duty比 7.25) からスタート pan_deg = 0 pan_servo_pwm.start(7.25) sleep(2) tilt_deg = 0 tilt_servo_pwm.start(7.25) sleep(2) 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] resize_factor = (frame_size[0] / model.input_size[1], frame_size[1] / model.input_size[0]) boxes = boxes_dict[target_n] 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_center_y = int((coordinates[1]+coordinates[3])/2) # 画像中心からの object 中心のズレ dx = object_center_x - img_center_x dy = object_center_y - img_center_y print("中心ズレ:" + str(dx) + ", " + str(dy)) # カメラ方向からの角度ズレ dpd = round( pixel2deg * dx ) dtd = round( pixel2deg * dy ) print("角度ズレ:" + str(dpd) + ", " + str(dtd)) # dxが大きいとき,pan 駆動 if abs(dx) > 20: servo_angle('pan', pan_deg) # モータ入力値の更新 # +, - は,ズレを解消するサーボの回転方向に依存) pan_deg = pan_deg + dpd # dyが大きいとき,tilt 駆動 if abs(dy) > 15: servo_angle('tilt', tilt_deg) # モータ入力値の更新 # +, - は,ズレを解消するサーボの回転方向に依存) tilt_deg = tilt_deg - dtd # 残りの box は取り上げない break # <for box in boxes> ここまで # <if( len(boxes) != 0)> ここまで # 画像ウィンドウをアクティブにして 'q' キーを押すと, break if cv2.waitKey(10) & 0xFF == ord('q'): destroy()


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