Dzsysop commited on
Commit
9ea7598
·
1 Parent(s): e09906f

webcam - switch to webrtc gradio

Browse files
Files changed (2) hide show
  1. app.py +34 -51
  2. requirements.txt +2 -1
app.py CHANGED
@@ -1,78 +1,61 @@
1
- import gradio as gr
2
  import cv2
3
  import numpy as np
 
 
4
 
5
- # Load the face detection model (using OpenCV's built-in classifier)
6
- # This is a fast, reliable model that works well for real-time applications.
7
  face_cascade = cv2.CascadeClassifier(
8
  cv2.data.haarcascades + 'haarcascade_frontalface_default.xml'
9
  )
10
 
11
- def apply_zorro_mask(frame: np.ndarray) -> np.ndarray:
12
- """
13
- This function is called for every frame from your webcam.
14
- It detects faces and draws a Zorro mask on them.
15
- """
16
  if frame is None:
17
- return None
18
 
19
- # The frame from Gradio is in RGB, but OpenCV uses BGR.
20
- # Convert to BGR for processing, then back to RGB for display.
21
  frame_bgr = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
22
-
23
- # Convert the frame to grayscale, which is required for the face detector
24
  gray = cv2.cvtColor(frame_bgr, cv2.COLOR_BGR2GRAY)
25
 
26
- # Detect faces in the image
27
- # The parameters (scaleFactor, minNeighbors) can be tuned for better performance
28
- faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(60, 60))
29
 
30
- # Loop over all detected faces and draw the mask
31
  for (x, y, w, h) in faces:
32
- # --- Draw the black Zorro mask (a rectangle over the eyes) ---
33
- mask_height = int(h * 0.4) # Make the mask cover the upper part of the face
34
- mask_y = y + int(h * 0.2) # Position it a bit below the top of the face
35
- cv2.rectangle(frame_bgr, (x, mask_y), (x + w, mask_y + mask_height), (0, 0, 0), -1) # -1 fills the rectangle
36
 
37
- # --- Create eye holes (two white circles) ---
 
 
 
38
  eye_y = mask_y + int(mask_height * 0.5)
39
  eye_radius = int(w * 0.1)
40
- # Left eye hole
41
  cv2.circle(frame_bgr, (x + int(w * 0.35), eye_y), eye_radius, (255, 255, 255), -1)
42
- # Right eye hole
43
  cv2.circle(frame_bgr, (x + int(w * 0.65), eye_y), eye_radius, (255, 255, 255), -1)
44
 
45
- # --- Optional: Draw a stylish "Z" mark on the mask ---
46
- cv2.putText(frame_bgr, "Z", (x + w - 30, y + h - 20),
47
- cv2.FONT_HERSHEY_SIMPLEX, 1.5, (0, 0, 255), 3)
 
 
 
 
 
 
 
 
48
 
49
- # Convert the frame back to RGB for Gradio to display
50
- frame_rgb = cv2.cvtColor(frame_bgr, cv2.COLOR_BGR2RGB)
51
- return frame_rgb
52
 
53
- # --- Build the Gradio Interface ---
54
- # The 'Blocks' API gives us more control than the simple 'Interface' API.
55
- with gr.Blocks(title="Real-Time Zorro Mask Sandbox") as demo:
56
- gr.Markdown("# 🎭 Real-Time Zorro Mask Sandbox")
57
- gr.Markdown("Allow webcam access. The mask will be applied to your face in real-time!")
58
 
59
- with gr.Row():
60
- # Input: The live webcam stream. 'streaming=True' is crucial.
61
- input_webcam = gr.Image(sources=["webcam"], streaming=True, label="Your Webcam Feed")
62
- # Output: Where the processed video stream will be shown.
63
- # output_video = gr.Image(label="Live Zorro Mask Output")
64
- output_video = gr.Image(label="Live Zorro Mask Output", streaming=True)
65
 
66
- # This is the magic line that creates the real-time loop.
67
- # It calls 'apply_zorro_mask' for every new frame from 'input_webcam'
68
- # and sends the result to 'output_video'.
69
- input_webcam.change(
70
- fn=apply_zorro_mask,
71
- inputs=input_webcam,
72
- outputs=output_video,
73
- time_limit=3, # Optional: Stops the stream after 10 seconds if no new frames
74
- stream_every=0.05 # Optional: Controls the delay between frames (in seconds). Lower is faster.
75
  )
76
 
77
- # Launch the app
78
  demo.launch()
 
 
1
  import cv2
2
  import numpy as np
3
+ import gradio as gr
4
+ from gradio_webrtc import WebRTC
5
 
6
+ # Load face detector
 
7
  face_cascade = cv2.CascadeClassifier(
8
  cv2.data.haarcascades + 'haarcascade_frontalface_default.xml'
9
  )
10
 
11
+ def process_frame(frame: np.ndarray) -> np.ndarray:
 
 
 
 
12
  if frame is None:
13
+ return frame
14
 
 
 
15
  frame_bgr = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
 
 
16
  gray = cv2.cvtColor(frame_bgr, cv2.COLOR_BGR2GRAY)
17
 
18
+ faces = face_cascade.detectMultiScale(
19
+ gray, scaleFactor=1.1, minNeighbors=5, minSize=(60, 60)
20
+ )
21
 
 
22
  for (x, y, w, h) in faces:
23
+ mask_height = int(h * 0.4)
24
+ mask_y = y + int(h * 0.2)
 
 
25
 
26
+ # black mask
27
+ cv2.rectangle(frame_bgr, (x, mask_y), (x + w, mask_y + mask_height), (0, 0, 0), -1)
28
+
29
+ # eyes
30
  eye_y = mask_y + int(mask_height * 0.5)
31
  eye_radius = int(w * 0.1)
32
+
33
  cv2.circle(frame_bgr, (x + int(w * 0.35), eye_y), eye_radius, (255, 255, 255), -1)
 
34
  cv2.circle(frame_bgr, (x + int(w * 0.65), eye_y), eye_radius, (255, 255, 255), -1)
35
 
36
+ # Z
37
+ cv2.putText(
38
+ frame_bgr, "Z",
39
+ (x + w - 30, y + h - 20),
40
+ cv2.FONT_HERSHEY_SIMPLEX,
41
+ 1.5,
42
+ (0, 0, 255),
43
+ 3
44
+ )
45
+
46
+ return cv2.cvtColor(frame_bgr, cv2.COLOR_BGR2RGB)
47
 
 
 
 
48
 
49
+ # UI
50
+ with gr.Blocks() as demo:
51
+ gr.Markdown("# 🎭 Real-time Zorro Mask (WebRTC)")
 
 
52
 
53
+ webrtc = WebRTC()
 
 
 
 
 
54
 
55
+ webrtc.stream(
56
+ fn=process_frame,
57
+ inputs=webrtc,
58
+ outputs=webrtc,
 
 
 
 
 
59
  )
60
 
 
61
  demo.launch()
requirements.txt CHANGED
@@ -1,3 +1,4 @@
1
  gradio
2
  opencv-python
3
- numpy
 
 
1
  gradio
2
  opencv-python
3
+ numpy
4
+ gradio-webrtc