import cv2
import mediapipe as mp
import numpy as np
mp_hands = mp.solutions.hands
hands = mp_hands.Hands(
static_image_mode=False,
max_num_hands=1,
min_detection_confidence=0.7,
min_tracking_confidence=0.7
)
mp_draw = mp.solutions.drawing_utils
cap = cv2.VideoCapture(0)
if not cap.isOpened():
print("❌ لا يمكن فتح الكاميرا!")
exit()
cv2.namedWindow("AIR - WRITING", cv2.WINDOW_NORMAL)
cv2.resizeWindow("AIR - WRITING", 800, 600)
mode = "IDLE"
color = (0, 255, 0)
thickness = 5
eraser_size = 60
line_counter = 0
canvas = np.zeros((480, 640, 4), dtype=np.uint8)
def is_finger_up(hand_landmarks, finger_tip_id, finger_pip_id):
tip = hand_landmarks.landmark[finger_tip_id]
pip = hand_landmarks.landmark[finger_pip_id]
return tip.y < pip.y
def is_hand_open(hand_landmarks):
fingers_up = [
is_finger_up(hand_landmarks, 8, 6),
is_finger_up(hand_landmarks, 12, 10),
is_finger_up(hand_landmarks, 16, 14),
is_finger_up(hand_landmarks, 20, 18),
]
return all(fingers_up)
prev_x, prev_y = None, None
while True:
ret, frame = cap.read()
if not ret:
break
frame = cv2.flip(frame, 1)
h, w, _ = frame.shape
rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
results = hands.process(rgb_frame)
frame = cv2.cvtColor(rgb_frame, cv2.COLOR_RGB2BGR)
if results.multi_hand_landmarks:
for hand_landmarks in results.multi_hand_landmarks:
mp_draw.draw_landmarks(frame, hand_landmarks, mp_hands.HAND_CONNECTIONS,
mp_draw.DrawingSpec(color=(0, 255, 255), thickness=2),
mp_draw.DrawingSpec(color=(255, 0, 0), thickness=2))
index_tip = hand_landmarks.landmark[8]
cx, cy = int(index_tip.x * w), int(index_tip.y * h)
cv2.circle(frame, (cx, cy), 8, (0, 255, 255), -1)
index_up = is_finger_up(hand_landmarks, 8, 6)
middle_up = is_finger_up(hand_landmarks, 12, 10)
ring_up = is_finger_up(hand_landmarks, 16, 14)
pinky_up = is_finger_up(hand_landmarks, 20, 18)
if index_up and not middle_up and not ring_up and not pinky_up:
mode = "DRAW"
elif is_hand_open(hand_landmarks):
mode = "ERASE"
else:
mode = "IDLE"
if mode == "DRAW":
if prev_x is not None and prev_y is not None:
cv2.line(canvas, (prev_x, prev_y), (cx, cy), color + (255,), thickness)
prev_x, prev_y = cx, cy
elif mode == "ERASE":
cv2.circle(canvas, (cx, cy), eraser_size, (0, 0, 0, 0), -1)
prev_x, prev_y = None, None
else:
prev_x, prev_y = None, None
else:
prev_x, prev_y = None, None
alpha = canvas[:, :, 3] / 255.0
for c in range(3):
frame[:, :, c] = canvas[:, :, c] * alpha + frame[:, :, c] * (1 - alpha)
status_text = f"{mode}"
color_text = "GREEN" if color == (0, 255, 0) else "RED" if color == (0, 0, 255) else "BLUE"
cv2.putText(frame, status_text, (20, 40), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2)
cv2.putText(frame, color_text, (150, 40), cv2.FONT_HERSHEY_SIMPLEX, 1, color, 2)
cv2.putText(frame, f"LINE: {thickness}", (280, 40), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2)
cv2.putText(frame, f"ERASER: {eraser_size}", (420, 40), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2)
cv2.putText(frame, "ESC: Exit", (650, 40), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 255, 255), 2)
cv2.imshow("AIR - WRITING", frame)
key = cv2.waitKey(1) & 0xFF
if key == 27:
break
if key == ord('c'):
if color == (0, 255, 0):
color = (0, 0, 255)
elif color == (0, 0, 255):
color = (255, 0, 0)
else:
color = (0, 255, 0)
if key == ord('e'):
thickness = min(thickness + 2, 20)
if key == ord('q'):
thickness = max(thickness - 2, 1)
if key == ord('s'):
timestamp = int(cv2.getTickCount() / cv2.getTickFrequency())
filename = f"drawing_{timestamp}.png"
canvas_bgr = cv2.cvtColor(canvas, cv2.COLOR_BGRA2BGR)
cv2.imwrite(filename, canvas_bgr)
print(f"✅ تم حفظ الرسم كـ {filename}")
cap.release()
cv2.destroyAllWindows()