mirror of
https://github.com/ft-NotArt/ShyEye.git
synced 2025-10-29 12:26:01 +00:00
+ | ShyEye without anxiety when surrounded
This commit is contained in:
parent
e3ab5fe8dc
commit
ccd8993bf5
116
ShyEye/eyeMove/eyeMove.ino
Normal file
116
ShyEye/eyeMove/eyeMove.ino
Normal file
@ -0,0 +1,116 @@
|
||||
#include "Servo.h"
|
||||
|
||||
/*
|
||||
These are just indications used to understand what value is passed through Serial to Arduino
|
||||
*/
|
||||
|
||||
// Move to the left
|
||||
#define SERVO_LMOV 0
|
||||
#define SERVO_LUMOV 1
|
||||
#define SERVO_LDMOV 2
|
||||
|
||||
// Move to the right
|
||||
#define SERVO_RMOV 3
|
||||
#define SERVO_RUMOV 4
|
||||
#define SERVO_RDMOV 5
|
||||
|
||||
// Don't move x axis
|
||||
#define SERVO_NOMOV 6
|
||||
#define SERVO_UMOV 7
|
||||
#define SERVO_DMOV 8
|
||||
|
||||
#define LOOK_LEFT -45
|
||||
#define LOOK_RIGHT 45
|
||||
#define LOOK_UP 45
|
||||
#define LOOK_DOWN -45
|
||||
|
||||
#define START_POS 90
|
||||
|
||||
Servo servoX;
|
||||
Servo servoY;
|
||||
int eyeDir;
|
||||
bool isServoXAttached = true;
|
||||
bool isServoYAttached = true;
|
||||
|
||||
void setup() {
|
||||
servoX.attach(9); // Attach servoX to pin 9
|
||||
servoY.attach(10); // Attach servoY to pin 10
|
||||
|
||||
servoX.write(START_POS);
|
||||
servoY.write(START_POS);
|
||||
delay(1000);
|
||||
|
||||
Serial.begin(9600);
|
||||
Serial.setTimeout(1);
|
||||
|
||||
// Used for debugging
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
}
|
||||
|
||||
void stopServo(Servo &servo, bool &isAttached) {
|
||||
if (isAttached) { // Only detach if it's currently attached
|
||||
servo.detach();
|
||||
isAttached = false;
|
||||
}
|
||||
}
|
||||
|
||||
void moveServo(Servo &servo, int angle, bool &isAttached, int pin) {
|
||||
if (!isAttached) { // Only attach if it's currently detached
|
||||
servo.attach(pin);
|
||||
isAttached = true;
|
||||
}
|
||||
servo.write(angle);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
while (!Serial.available());
|
||||
eyeDir = Serial.readString().toInt();
|
||||
|
||||
switch (eyeDir) {
|
||||
case SERVO_LMOV:
|
||||
moveServo(servoX, START_POS + LOOK_LEFT, isServoXAttached, 9);
|
||||
stopServo(servoY, isServoYAttached);
|
||||
break;
|
||||
|
||||
case SERVO_LUMOV:
|
||||
moveServo(servoX, START_POS + LOOK_LEFT, isServoXAttached, 9);
|
||||
moveServo(servoY, START_POS + LOOK_UP, isServoYAttached, 10);
|
||||
break;
|
||||
|
||||
case SERVO_LDMOV:
|
||||
moveServo(servoX, START_POS + LOOK_LEFT, isServoXAttached, 9);
|
||||
moveServo(servoY, START_POS + LOOK_DOWN, isServoYAttached, 10);
|
||||
break;
|
||||
|
||||
case SERVO_RMOV:
|
||||
moveServo(servoX, START_POS + LOOK_RIGHT, isServoXAttached, 9);
|
||||
stopServo(servoY, isServoYAttached);
|
||||
break;
|
||||
|
||||
case SERVO_RUMOV:
|
||||
moveServo(servoX, START_POS + LOOK_RIGHT, isServoXAttached, 9);
|
||||
moveServo(servoY, START_POS + LOOK_UP, isServoYAttached, 10);
|
||||
break;
|
||||
|
||||
case SERVO_RDMOV:
|
||||
moveServo(servoX, START_POS + LOOK_RIGHT, isServoXAttached, 9);
|
||||
moveServo(servoY, START_POS + LOOK_DOWN, isServoYAttached, 10);
|
||||
break;
|
||||
|
||||
case SERVO_UMOV:
|
||||
stopServo(servoX, isServoXAttached);
|
||||
moveServo(servoY, START_POS + LOOK_UP, isServoYAttached, 10);
|
||||
break;
|
||||
|
||||
case SERVO_DMOV:
|
||||
stopServo(servoX, isServoXAttached);
|
||||
moveServo(servoY, START_POS + LOOK_DOWN, isServoYAttached, 10);
|
||||
break;
|
||||
|
||||
default:
|
||||
stopServo(servoX, isServoXAttached);
|
||||
stopServo(servoY, isServoYAttached);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
130
ShyEye/faceDetection.py
Normal file
130
ShyEye/faceDetection.py
Normal file
@ -0,0 +1,130 @@
|
||||
import cv2
|
||||
import serial
|
||||
import time
|
||||
|
||||
# Used for debug mainly, set to True to see what the camera is recording
|
||||
DRAW_CAMERA = True
|
||||
|
||||
|
||||
"""
|
||||
These are just indications used to understand what value is passed through Serial to arduino
|
||||
In the arduino code, same values will be used but as defines
|
||||
Setting those in this order enables me to only do +1/+2 to choose up or down in addition to left/right direction
|
||||
"""
|
||||
|
||||
# Move to the left
|
||||
SERVO_LMOV = 0
|
||||
SERVO_LUMOV = 1
|
||||
SERVO_LDMOV = 2
|
||||
|
||||
# Move to the right
|
||||
SERVO_RMOV = 3
|
||||
SERVO_RUMOV = 4
|
||||
SERVO_RDMOV = 5
|
||||
|
||||
# Don't move x axis
|
||||
SERVO_NOMOV = 6
|
||||
SERVO_UMOV = 7
|
||||
SERVO_DMOV = 8
|
||||
|
||||
|
||||
SERVO_SPD = 2
|
||||
|
||||
def draw_square(frame, faces, color):
|
||||
for (x, y, w, h) in faces:
|
||||
face_region = frame[y:y+h, x:x+w]
|
||||
cv2.rectangle(frame, (x, y), (x + w, y + h), color, 1)
|
||||
return frame
|
||||
|
||||
|
||||
arduino = serial.Serial(port='/dev/ttyACM0', baudrate=9600, timeout=.1)
|
||||
|
||||
video_capture = cv2.VideoCapture(0)
|
||||
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml")
|
||||
side_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_profileface.xml")
|
||||
detected_faces = []
|
||||
detected_profiles = []
|
||||
|
||||
|
||||
ret, frame = video_capture.read()
|
||||
if ret:
|
||||
frameH, frameW = frame.shape[:2]
|
||||
eyeX = int (frameW / 2)
|
||||
eyeY = int (frameH / 2)
|
||||
|
||||
while True:
|
||||
ret, frame = video_capture.read()
|
||||
if not ret:
|
||||
break
|
||||
|
||||
gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
|
||||
faces = face_cascade.detectMultiScale(gray_frame, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30))
|
||||
detected_faces = faces
|
||||
faces = side_cascade.detectMultiScale(gray_frame, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30))
|
||||
detected_profiles = faces
|
||||
|
||||
target = [int ((frameW / 2) - 10), int ((frameH / 2) - 10), 20, 20]
|
||||
eyeDir = SERVO_NOMOV
|
||||
if len(detected_faces) >= 3 :
|
||||
# anxiety code
|
||||
feur = 3
|
||||
elif len(detected_profiles) != 0 and len(detected_faces) != 0 :
|
||||
arduino.write(bytes(f"{SERVO_NOMOV}", "utf-8"))
|
||||
else :
|
||||
if len(detected_profiles) != 0 and len(detected_faces) == 0 :
|
||||
# get target as the biggest face detected
|
||||
for face in detected_profiles :
|
||||
if face[3] > target[3] : # deep copy as I want to modify target w/out modifying detected_profiles
|
||||
target[0] = face[0]
|
||||
target[1] = face[1]
|
||||
target[2] = face[2]
|
||||
target[3] = face[3]
|
||||
|
||||
# define target as the center of selected face
|
||||
target[0] = int (target[0] + (target[2] / 2) - 10)
|
||||
target[1] = int (target[1] + (target[3] / 2) - 10)
|
||||
target[2] = 20
|
||||
target[3] = 20
|
||||
|
||||
# adjust the 'eye' position as the camera turn around
|
||||
if eyeX < target[0] or eyeX > (target[0] + target[2]) :
|
||||
if eyeX < target[0] :
|
||||
eyeX += SERVO_SPD
|
||||
eyeDir = SERVO_LMOV
|
||||
else :
|
||||
eyeX -= SERVO_SPD
|
||||
eyeDir = SERVO_RMOV
|
||||
else :
|
||||
eyeDir = SERVO_NOMOV
|
||||
if eyeY < target[1] or eyeY > (target[1] + target[3]) :
|
||||
if eyeY < target[1] :
|
||||
eyeY += SERVO_SPD
|
||||
eyeDir += 2
|
||||
else :
|
||||
eyeY -= SERVO_SPD
|
||||
eyeDir += 1
|
||||
|
||||
arduino.write(bytes(f"{eyeDir}", "utf-8"))
|
||||
|
||||
|
||||
if DRAW_CAMERA :
|
||||
# draw detected_faces/profiles on green/blue
|
||||
frame = draw_square(frame, detected_faces, (0, 255, 0))
|
||||
frame = draw_square(frame, detected_profiles, (255, 0, 0))
|
||||
|
||||
# draw target rectangle in red
|
||||
cv2.rectangle(frame, (target[0], target[1]), (target[0] + target[2], target[1] + target[3]), (0, 0, 255), 1)
|
||||
|
||||
# draw crosshair in white
|
||||
cv2.rectangle(frame, (eyeX - 5, eyeY), (eyeX + 5, eyeY), (255, 255, 255), 1)
|
||||
cv2.rectangle(frame, (eyeX, eyeY - 5), (eyeX, eyeY + 5), (255, 255, 255), 1)
|
||||
|
||||
# open a window and show recorded video
|
||||
cv2.imshow("Faces", frame)
|
||||
|
||||
if cv2.waitKey(1) != -1:
|
||||
break
|
||||
|
||||
|
||||
video_capture.release()
|
||||
cv2.destroyAllWindows()
|
||||
Loading…
Reference in New Issue
Block a user