import cv2
import serial
import time
import pygame

# Initialize the Arduino serial connection
arduino = serial.Serial('COM3', 9600)  # Replace 'COM3' with your Arduino's COM port
time.sleep(2)  # Wait for the connection to establish

# Load the pre-trained face detection model
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')

# Initialize the webcam
cap = cv2.VideoCapture(1)

# Get the width and height of the frame
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))

# Define the narrower center tolerance range (e.g., 40% of the frame width and height)
center_tolerance_x = frame_width // 10
center_tolerance_y = frame_height // 5

# Initialize face detection counter
face_detected_counter = 0
frames_required = 50

# Initialize pygame for audio playback
pygame.mixer.init()

# Load the song
pygame.mixer.music.load("C:/Users/J/Downloads/MySunshine.mp3")

while True:
    # Capture frame-by-frame
    ret, frame = cap.read()
    
    if not ret:
        print("Failed to capture frame from webcam. Exiting...")
        break
    
    # Convert frame to grayscale
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    
    # Detect faces
    faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30))
    
    if len(faces) > 0:
        # Get the coordinates of the first detected face
        (x, y, w, h) = faces[0]
        center_x = x + w // 2
        center_y = y + h // 2
        
        # Determine the horizontal position of the face relative to the frame center
        if center_x < frame_width // 2 - center_tolerance_x:
            arduino.write(b'L')  # Face is on the left
        elif center_x > frame_width // 2 + center_tolerance_x:
            arduino.write(b'R')  # Face is on the right
        
        # Determine the vertical position of the face relative to the frame center
        if center_y < frame_height // 2 - center_tolerance_y:
            arduino.write(b'U')  # Face is above the center
        elif center_y > frame_height // 2 + center_tolerance_y:
            arduino.write(b'D')  # Face is below the center

        # Increment the face detected counter
        face_detected_counter += 1
        
        # If face detected for required number of frames, turn on LED and play song
        if face_detected_counter >= frames_required:
            arduino.write(b'F')  # Face detected for required frames
            if not pygame.mixer.music.get_busy():
                pygame.mixer.music.play()
            face_detected_counter = frames_required  # Keep the counter at max value
        else:
            arduino.write(b'N')  # Turn off LED if not yet detected for required frames

        # Draw a rectangle around the face and display coordinates
        cv2.rectangle(frame, (x, y), (x+w, y+h), (255, 0, 0), 2)
        coords_text = f'X: {x} Y: {y} W: {w}'
        cv2.putText(frame, coords_text, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2)
    else:
        # Reset the face detected counter and turn off the LED
        face_detected_counter = 0
        arduino.write(b'N')  # No face detected
        pygame.mixer.music.stop()  # Stop the music if no face is detected
    
    # Display the resulting frame
    cv2.imshow('Face Detection', frame)
    
    # Exit if 'q' is pressed
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# Release the capture
cap.release()
cv2.destroyAllWindows()
pygame.mixer.quit()
