前提
PC側でキャプチャボードで取得したNintendo Switchの映像を使って、OpenCVのテンプレートマッチングを使用しマッチした場合にシリアル通信をして、Arduinoでモータを振動させたいです。シリアル通信の実装は初めてなので初歩的なことかもしれませんがよろしくお願いします。
実現したいこと
キャプチャボードで取得した映像の中にテンプレート画像に近いものがあると判断した時だけ、モータが回転するようにしたいです。
発生している問題・エラーメッセージ
エラーは出ずテンプレート画像に近いものを認識すると長方形は描くのですが、テンプレート画像に近いものの有無にかかわらずモータが回転してしまいます。
該当のソースコード
PC側
1import cv2 2import numpy as np 3import serial 4import time 5 6#カメラから映像を取得 7capture = cv2.VideoCapture(2) 8 9#カメラから映像を取得できない場合、終了 10if not capture.isOpened(): 11 print('カメラから映像を取得できませんでした') 12 exit() 13 14#テンプレート画像をグレースケールで読み込む 15template = cv2.imread('template_menu.png', 0) 16#テンプレート画像の幅と高さを取得 17w, h = template.shape[::-1] 18 19while True: 20 ret, frame = capture.read() 21 #frameをグレースケールに変換 22 frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) 23 if ret: 24 #テンプレートマッチングを実行 25 result = cv2.matchTemplate(frame_gray, template, cv2.TM_CCOEFF_NORMED) 26 #テンプレートマッチングの結果が0.7以上の位置をすべて取得 27 threshold = 0.7 28 locate = np.where(result >= threshold) 29 30 #テンプレート画像がマッチした位置に長方形を描画 31 for point in zip(*locate[::-1]): 32 cv2.rectangle(frame_gray, point, (point[0] + w, point[1] + h), (255, 0, 0), 3) 33 34 cv2.imshow('frame', frame_gray) 35 36 #0.7以上の場所があればArduinoに振動させる命令を送る 37 if locate != []: 38 ser = serial.Serial('COM21', 9600, timeout=0.1) 39 time.sleep(1) 40 ser.write(b'1') 41 ser.close() 42 43 #qを押した際にbreak 44 k = cv2.waitKey(1) & 0xFF 45 if k == ord('q'): 46 break 47 48 else: 49 break 50 51capture.release() 52cv2.destroyAllWindows()
Arduino側
1void setup() { 2 Serial.begin(9600); 3 pinMode(11, OUTPUT); 4 digitalWrite(11, LOW); 5} 6 7void loop() { 8 char data; 9 data = Serial.read(); 10 if(data == '1'){ 11 digitalWrite(11, HIGH); 12 delay(500); 13 digitalWrite(11, LOW); 14 delay(500); 15 } 16}
試したこと
おそらくPC側の37~41行目がおかしいのだろうと思ってソースコードを少しいじってみましたがうまくいきませんでした。
補足情報(FW/ツールのバージョンなど)
OpenCV 4.6.0
Python 3.9.15
シリアル通信の部分は以下のサイトを参考にしました。
https://tomson784.github.io/memo/python/arduino/2021/05/25/pyserial-arduino.html
あなたの回答
tips
プレビュー