import cv2 import mediapipe as mp import numpy as np import gradio as gr # --- MediaPipe setup --- mp_hands = mp.solutions.hands hands = mp_hands.Hands(min_detection_confidence=0.7) mp_draw = mp.solutions.drawing_utils # --- Global canvas --- canvas = None def paint(frame: np.ndarray) -> np.ndarray: global canvas h, w, _ = frame.shape if canvas is None: canvas = np.zeros((h, w, 3), dtype=np.uint8) # Convert to RGB for MediaPipe rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) results = hands.process(rgb) if results.multi_hand_landmarks: lm = results.multi_hand_landmarks[0].landmark[mp_hands.HandLandmark.INDEX_FINGER_TIP] x, y = int(lm.x * w), int(lm.y * h) cv2.circle(canvas, (x, y), 8, (0, 0, 255), -1) # Blend live frame and canvas return cv2.addWeighted(frame, 0.5, canvas, 0.5, 0) def clear_canvas(): global canvas canvas = None with gr.Blocks() as demo: gr.Markdown("## 🖌️ Virtual Painter\nMove your index finger in front of the camera to draw!") webcam = gr.Image(label="Input", sources="webcam", type="numpy") output = gr.Image(type="numpy") clear_btn = gr.Button("Clear Canvas") # Stream webcam → paint() → output webcam.stream(fn=paint, inputs=webcam, outputs=output) clear_btn.click(fn=clear_canvas, inputs=None, outputs=None) demo.launch()