sprite = Sprite('Tobi')
import cv2
import mediapipe as mp
import serial
import time
import math
# ==========================================
# SETTINGS
# ==========================================
SERIAL_PORT = "COM4"
BAUD_RATE = 9600
CAMERA_INDEX = 0
# ==========================================
# CONNECT TO ARDUINO
# ==========================================
print("Opening Arduino...")
arduino = serial.Serial(
SERIAL_PORT,
BAUD_RATE,
timeout=1
)
time.sleep(2)
print("Arduino connected successfully!")
# ==========================================
# MEDIAPIPE
# ==========================================
mp_hands = mp.solutions.hands
mp_draw = mp.solutions.drawing_utils
hands = mp_hands.Hands(
static_image_mode=False,
max_num_hands=1,
min_detection_confidence=0.7,
min_tracking_confidence=0.7
)
# ==========================================
# CAMERA
# ==========================================
cap = cv2.VideoCapture(CAMERA_INDEX)
if not cap.isOpened():
print("ERROR: Camera could not be opened.")
arduino.close()
exit()
# ==========================================
# VARIABLES
# ==========================================
last_command = ""
# ==========================================
# FINGER DETECTION FUNCTIONS
# ==========================================
def distance(p1, p2):
return math.sqrt(
(p1.x - p2.x) ** 2 +
(p1.y - p2.y) ** 2 +
(p1.z - p2.z) ** 2
)
def finger_is_up(landmarks, tip, pip):
tip_distance = distance(
landmarks[tip],
landmarks[0]
)
pip_distance = distance(
landmarks[pip],
landmarks[0]
)
return tip_distance > pip_distance
def thumb_is_up(landmarks):
thumb_tip_distance = distance(
landmarks[4],
landmarks[0]
)
thumb_ip_distance = distance(
landmarks[3],
landmarks[0]
)
return thumb_tip_distance > thumb_ip_distance
# ==========================================
# MAIN LOOP
# ==========================================
while True:
success, frame = cap.read()
if not success:
print("Could not read camera.")
break
# --------------------------------------
# Mirror image
# --------------------------------------
frame = cv2.flip(frame, 1)
# --------------------------------------
# Convert BGR → RGB
# --------------------------------------
rgb_frame = cv2.cvtColor(
frame,
cv2.COLOR_BGR2RGB
)
# --------------------------------------
# MediaPipe processing
# --------------------------------------
results = hands.process(rgb_frame)
# ======================================
# DEFAULT VALUES
# ======================================
thumb = 0
index = 0
middle = 0
ring = 0
pinky = 0
# ======================================
# HAND DETECTED
# ======================================
if results.multi_hand_landmarks:
for hand_landmarks, handedness in zip(
results.multi_hand_landmarks,
results.multi_handedness
):
# --------------------------------------
# RIGHT HAND ONLY
# --------------------------------------
hand_label = handedness.classification[0].label
if hand_label != "Right":
continue
# --------------------------------------
# DRAW HAND LANDMARKS
# --------------------------------------
mp_draw.draw_landmarks(
frame,
hand_landmarks,
mp_hands.HAND_CONNECTIONS
)
landmarks = hand_landmarks.landmark
# ======================================
# DETECT FIVE FINGERS
# ======================================
# Thumb
thumb = int(
thumb_is_up(landmarks)
)
# Index
index = int(
finger_is_up(
landmarks,
8,
6
)
)
# Middle
middle = int(
finger_is_up(
landmarks,
12,
10
)
)
# Ring
ring = int(
finger_is_up(
landmarks,
16,
14
)
)
# Pinky
pinky = int(
finger_is_up(
landmarks,
20,
18
)
)
# ======================================
# CREATE COMMAND
# ======================================
command = (
str(thumb) + "," +
str(index) + "," +
str(middle) + "," +
str(ring) + "," +
str(pinky) + "\n"
)
# ======================================
# SEND TO ARDUINO
# ======================================
if command != last_command:
arduino.write(
command.encode()
)
print(
"Finger states:",
command.strip()
)
last_command = command
# ======================================
# DISPLAY HAND
# ======================================
cv2.putText(
frame,
"Right Hand",
(20, 40),
cv2.FONT_HERSHEY_SIMPLEX,
0.8,
(0, 255, 0),
2
)
# ======================================
# DISPLAY FINGER STATUS
# ======================================
cv2.putText(
frame,
"Thumb: " +
("UP" if thumb else "DOWN"),
(20, 80),
cv2.FONT_HERSHEY_SIMPLEX,
0.7,
(0, 255, 0) if thumb else (0, 0, 255),
2
)
cv2.putText(
frame,
"Index: " +
("UP" if index else "DOWN"),
(20, 115),
cv2.FONT_HERSHEY_SIMPLEX,
0.7,
(0, 255, 0) if index else (0, 0, 255),
2
)
cv2.putText(
frame,
"Middle: " +
("UP" if middle else "DOWN"),
(20, 150),
cv2.FONT_HERSHEY_SIMPLEX,
0.7,
(0, 255, 0) if middle else (0, 0, 255),
2
)
cv2.putText(
frame,
"Ring: " +
("UP" if ring else "DOWN"),
(20, 185),
cv2.FONT_HERSHEY_SIMPLEX,
0.7,
(0, 255, 0) if ring else (0, 0, 255),
2
)
cv2.putText(
frame,
"Pinky: " +
("UP" if pinky else "DOWN"),
(20, 220),
cv2.FONT_HERSHEY_SIMPLEX,
0.7,
(0, 255, 0) if pinky else (0, 0, 255),
2
)
# ======================================
# SHOW COMMAND
# ======================================
cv2.putText(
frame,
"Command: " +
command.strip(),
(20, 260),
cv2.FONT_HERSHEY_SIMPLEX,
0.65,
(255, 255, 255),
2
)
break
# ==========================================
# NO HAND DETECTED
# ==========================================
else:
thumb = 0
index = 0
middle = 0
ring = 0
pinky = 0
command = "0,0,0,0,0\n"
if command != last_command:
arduino.write(
command.encode()
)
print(
"No Right Hand Detected"
)
last_command = command
cv2.putText(
frame,
"No Right Hand Detected",
(20, 40),
cv2.FONT_HERSHEY_SIMPLEX,
0.8,
(0, 0, 255),
2
)
# ==========================================
# SHOW CAMERA
# ==========================================
cv2.imshow(
"AI Hand Gesture - RGB LED Control",
frame
)
# Press Q to quit
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# ==========================================
# CLEANUP
# ==========================================
print("Stopping...")
arduino.write(
b"0,0,0,0,0\n"
)
time.sleep(0.2)
cap.release()
cv2.destroyAllWindows()
hands.close()
arduino.close()
print("Finished!")
Comments