はじめに
- 【MXNet】写真に写っている人を数える(Faster RCNN resnet101を用いた物体検出) - パソコン関連もろもろ
- 【MXNet】物体検出(detect only one class) - パソコン関連もろもろ
- 【Realtime Object Detection】動画に対して物体検出(ssd_512_mobilenet1.0) - パソコン関連もろもろ
上の3つで習得したものを組み合わせて、人を検出したらLEDが光るシステムを作ってみた。
超音波センサー?赤外線センサー?いやいやどちらも違います。
深層学習を用いた物体検出です。
メリットとして人以外の動物に反応しない。プログラムを変更すれば犬には反応して猫には反応しないなどが可能。
Webカメラの画像をPCで受信。そのPCで画像に対して学習済みモデルを適応し、ArduinoにLEDのon、offの命令を送っている。
環境
Windows10 Pro NVIDIA GeForce GTX1080 Python 3.7.7 Arduino IDE 1.8.12 Arduino Uno R3
バージョン確認(pip freeze)
インストールが必要なのは「mxnet-cu101]と「gluoncv」と「opencv-python」と「pyserial」のみ。pip install https://repo.mxnet.io/dist/python/cu101/mxnet_cu101-1.6.0-py2.py3-none-win_amd64.whl pip install gluoncv pip install opencv-python pip install pyserial
その他は勝手についてくる。
certifi==2020.4.5.1 chardet==3.0.4 cycler==0.10.0 gluoncv==0.7.0 graphviz==0.8.4 idna==2.6 kiwisolver==1.2.0 matplotlib==3.2.1 mxnet-cu101 @ https://repo.mxnet.io/dist/python/cu101/mxnet_cu101-1.6.0-py2.py3-none-win_amd64.whl numpy==1.16.6 opencv-python==4.2.0.34 Pillow==7.1.2 portalocker==1.7.0 pyparsing==2.4.7 pyserial==3.4 python-dateutil==2.8.1 pywin32==227 requests==2.18.4 scipy==1.4.1 six==1.14.0 tqdm==4.46.0 urllib3==1.22
Pythonコード
import mxnet as mx import gluoncv import serial, time import cv2 ctx = mx.gpu() # Load the model net = gluoncv.model_zoo.get_model('ssd_512_resnet50_v1_voc', pretrained=True, root='./model', ctx=ctx) net.reset_class(["person"], reuse_weights=['person']) # Compile the model for faster speed net.hybridize() # Load the webcam handler cap = cv2.VideoCapture(0, cv2.CAP_DSHOW) # letting the camera autofocus time.sleep(1) ser =serial.Serial("COM3", 9600) while(True): # Load frame from the camera ret, frame = cap.read() # Image pre-processing frame = mx.nd.array(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)).astype('uint8') rgb_nd, frame = gluoncv.data.transforms.presets.ssd.transform_test(frame, short=512, max_size=700) # Run frame through network class_IDs, scores, bounding_boxes = net(rgb_nd.as_in_context(ctx)) n_box = class_IDs.shape[1] count = 0 for n in range(n_box): if(scores[0][n].asscalar()>0.8): count += 1 if(count==0): ser.write(b'0') else: ser.write(b'1') # Display the result img = gluoncv.utils.viz.cv_plot_bbox(frame, bounding_boxes[0], scores[0], class_IDs[0], class_names=net.classes, thresh=0.8) gluoncv.utils.viz.cv_plot_image(img) time.sleep(0.2) # escを押したら終了 if cv2.waitKey(1) == 27: break ser.write(b'0') ser.close() cap.release() cv2.destroyAllWindows()
Arduinoスケッチ
void setup() { Serial.begin(9600); pinMode(13, OUTPUT); digitalWrite(13, LOW); } void loop() { byte var; var = Serial.read(); switch(var){ case '0': digitalWrite(13, LOW); break; case '1': digitalWrite(13, HIGH); break; default: break; } }