Hi all,
I am brand new to the Arduino language, but I know some python. I have created code that takes input from a webcam, and using OpenCV finds the coordinates for a face and aims servos to aim a projectile at it.
my python code is here:
import cv2
from cv2 import imshow
import serial
import time
arduino = serial.Serial('COM5', 9600, timeout=2)
time.sleep(1)
cap = cv2.VideoCapture(0)
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
while True:
ret, frame = cap.read()
grey = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(grey, 1.3, 5)
# detectMultiScale(screen, scaleFactor (smaller value = more accurate, slower), minNeighbours(how accurate is the algorithm?), minimumSize(O), maxSize(O))
for (x, y, w, h) in faces: #x and y gives the coordinates of the top right corner of the face
cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0 , 0), 1)
cv2.circle(frame, ((x + w//2), (y + h//2)), 1, (0, 0, 255), 5)
global Xcoordinate
Xcoordinate = x + w//2 # 43 - 600
global Ycoordinate
Ycoordinate = y + h//2 #43 - 400
global rectYLength
rectYLength= h #200 - 45
dataX = str((Xcoordinate//15) + 70)
dataY = str((Ycoordinate//20) + 20)
dataX = '0'*(3-len(dataX)) + dataX
dataY = '0'*(3-len(dataY)) + dataY
coordinates = dataX + dataY
arduino.write(coordinates.encode("utf-8"))
arduinoValues = arduino.read()
decodedValues = str(arduinoValues[0:len(arduinoValues)].decode("utf-8"))
print("sent: " + coordinates)
print("received: " + decodedValues)
time.sleep(0.1)
if faces == ():
print("No face detected")
dataX = str(90)
dataY = str(0)
dataX = '0'*(3-len(dataX)) + dataX
dataY = '0'*(3-len(dataY)) + dataY
coordinates = dataX + dataY
arduino.write(coordinates.encode("utf-8"))
imshow('frame', frame)
if cv2.waitKey(1) == ord('q'):
break
cap.release()
cv2.destroyAllWindows
and my Arduino code is here:
#include <Servo.h>
Servo serx;
Servo sery;
int angleX = 0;
int angleY = 0;
void setup() {
// put your setup code here, to run once:
sery.attach(9);
serx.attach(10);
sery.write(0);
serx.write(90);
Serial.begin(9600);
}
void loop()
{
// put your main code here, to run repeatedly:
while (Serial.available() > 0)
{
String data = Serial.readString();
int str_len = data.length() + 1;
char char_array[str_len];
data.toCharArray(char_array, str_len);
char dataX[3] = {data[0], data[1], data[2]};
char dataY[4] = {data[3], data[4], data[5], '\0'};
angleX = atoi(dataX);
angleY = atoi(dataY);
Serial.print("x: ");
Serial.println(dataX);
Serial.print("y: ");
Serial.println(dataY);
Serial.print("data: ");
Serial.println(char_array);
sery.write(angleY);
serx.write(angleX);
delay(100);
}
}
I have managed to make the code work, however, it is quite laggy and slow, and I have tried to eliminate a few unnecessary lines to speed it up. I thought that removing the lines below would speed things up, however for some reason the servos stop taking input when I do that.
arduinoValues = arduino.read()
decodedValues = str(arduinoValues[0:len(arduinoValues)].decode("utf-8"))
print("sent: " + coordinates)
print("received: " + decodedValues)
I have tried to figure this out for a while and I would really appreciate it if someone could explain this or a way to decrease the lag. Any help would be gratefully received, thanks!