File size: 1,378 Bytes
f0105aa
 
 
 
 
 
 
b6d78be
f0105aa
 
 
 
 
 
 
b6d78be
f0105aa
 
 
 
814589f
b6d78be
f0105aa
 
b6d78be
f0105aa
 
 
17b186a
b6d78be
f0105aa
814589f
 
 
 
 
 
7c06fa0
814589f
 
 
 
7c06fa0
814589f
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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()