Pranesh64 commited on
Commit
61e47bd
Β·
verified Β·
1 Parent(s): 495aa3e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +73 -137
app.py CHANGED
@@ -2,180 +2,116 @@ import gradio as gr
2
  import numpy as np
3
  import cv2
4
  import plotly.graph_objects as go
5
- from sklearn.decomposition import PCA
6
  from sklearn.metrics.pairwise import cosine_distances
7
 
8
- # ===============================
9
- # FACE DETECTION
10
- # ===============================
11
 
12
  face_cascade = cv2.CascadeClassifier(
13
  cv2.data.haarcascades + "haarcascade_frontalface_default.xml"
14
  )
15
 
16
- def detect_face(image):
17
  if image is None:
18
- return None, None
19
 
20
  gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
21
  faces = face_cascade.detectMultiScale(gray, 1.3, 5)
22
-
23
  if len(faces) == 0:
24
  return image, None
25
 
26
  x, y, w, h = faces[0]
27
- cv2.rectangle(image, (x, y), (x+w, y+h), (0,255,0), 2)
28
-
29
- face = gray[y:y+h, x:x+w]
30
- face = cv2.resize(face, (64,64))
31
  return image, face.flatten()
32
 
33
- def face_to_embedding(face_vector):
34
- np.random.seed(42)
35
- proj = np.random.randn(face_vector.shape[0], 128)
36
- emb = face_vector @ proj
37
- emb = emb / np.linalg.norm(emb)
38
- return emb
39
-
40
- # ===============================
41
- # VISUALS
42
- # ===============================
43
-
44
- def plot_embedding(embedding):
45
- fig = go.Figure()
46
- fig.add_trace(go.Scatter(
47
- y=embedding[:50],
48
- mode="lines+markers"
49
- ))
50
- fig.update_layout(
51
- title="Face Embedding (Vector Representation)",
52
- height=300
53
- )
54
- return fig
55
-
56
- def plot_3d(enroll, live):
57
- pca = PCA(n_components=3)
58
- reduced = pca.fit_transform(np.vstack([enroll, live]))
59
-
60
- fig = go.Figure()
61
- fig.add_trace(go.Scatter3d(
62
- x=[reduced[0,0]], y=[reduced[0,1]], z=[reduced[0,2]],
63
- mode="markers+text",
64
- text=["Enrolled"],
65
- marker=dict(size=6)
66
- ))
67
- fig.add_trace(go.Scatter3d(
68
- x=[reduced[1,0]], y=[reduced[1,1]], z=[reduced[1,2]],
69
- mode="markers+text",
70
- text=["Live"],
71
- marker=dict(size=6)
72
- ))
73
-
74
- fig.update_layout(title="3D Face Embedding Space")
75
- return fig
76
 
77
- # ===============================
78
  # LOGIC
79
- # ===============================
80
 
81
- def enroll(image):
82
- img, face = detect_face(image)
83
  if face is None:
84
- return img, None, "❌ No face detected", None
 
85
 
86
- emb = face_to_embedding(face)
87
- return img, emb, "βœ… Face enrolled", plot_embedding(emb)
88
-
89
- def verify(image, stored, threshold):
90
- img, face = detect_face(image)
91
  if face is None or stored is None:
92
- return img, "❌ Missing face or enrollment", None, None
93
-
94
- live = face_to_embedding(face)
95
- dist = cosine_distances([stored], [live])[0][0]
96
 
97
- status = "πŸ”“ UNLOCKED" if dist < threshold else "πŸ”’ DENIED"
 
 
98
 
99
- gauge = go.Figure(go.Indicator(
100
  mode="gauge+number",
101
  value=dist,
102
- gauge={
103
- "axis": {"range": [0,1]},
104
- "threshold": {"value": threshold}
105
- },
106
  title={"text": status}
107
  ))
 
108
 
109
- return img, f"Distance: {dist:.3f}", gauge, plot_3d(stored, live)
110
-
111
- # ===============================
112
- # NAVIGATION
113
- # ===============================
114
-
115
- def next_tab(t): return min(t+1, 2)
116
- def prev_tab(t): return max(t-1, 0)
117
-
118
- # ===============================
119
  # UI
120
- # ===============================
121
 
122
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
123
- gr.Markdown("# πŸ” How Face Unlock Works (Visual)")
124
- tab_state = gr.State(0)
 
 
125
 
126
  with gr.Row():
127
  back = gr.Button("β¬… Back")
128
  nextb = gr.Button("Next ➑")
129
 
130
- with gr.Tabs(selected=0) as tabs:
131
-
132
- with gr.Tab("πŸ“Έ Capture"):
133
- cam1 = gr.Image(
134
- sources=["webcam"],
135
- type="numpy",
136
- streaming=True
137
- )
138
- out1 = gr.Image()
139
- gr.Button("Detect").click(detect_face, cam1, [out1, gr.State()])
140
-
141
- with gr.Tab("🧠 Enroll"):
142
- cam2 = gr.Image(
143
- sources=["webcam"],
144
- type="numpy"
145
- )
146
- out2 = gr.Image()
147
- msg2 = gr.Markdown()
148
- emb_state = gr.State()
149
- plot2 = gr.Plot()
150
-
151
- gr.Button("Enroll Face").click(
152
- enroll,
153
- cam2,
154
- [out2, emb_state, msg2, plot2]
155
- )
156
-
157
- with gr.Tab("πŸ”“ Verify"):
158
- cam3 = gr.Image(
159
- sources=["webcam"],
160
- type="numpy"
161
- )
162
- out3 = gr.Image()
163
- threshold = gr.Slider(0.1, 0.8, 0.35)
164
- msg3 = gr.Markdown()
165
- gauge = gr.Plot()
166
- space3d = gr.Plot()
167
-
168
- gr.Button("Verify").click(
169
- verify,
170
- [cam3, emb_state, threshold],
171
- [out3, msg3, gauge, space3d]
172
- )
173
-
174
- back.click(prev_tab, tab_state, tab_state).then(
175
- lambda i: i, tab_state, tabs
176
- )
177
- nextb.click(next_tab, tab_state, tab_state).then(
178
- lambda i: i, tab_state, tabs
179
- )
180
 
181
  demo.launch()
 
2
  import numpy as np
3
  import cv2
4
  import plotly.graph_objects as go
 
5
  from sklearn.metrics.pairwise import cosine_distances
6
 
7
+ # =========================
8
+ # FACE UTILITIES
9
+ # =========================
10
 
11
  face_cascade = cv2.CascadeClassifier(
12
  cv2.data.haarcascades + "haarcascade_frontalface_default.xml"
13
  )
14
 
15
+ def detect(image):
16
  if image is None:
17
+ return image, None
18
 
19
  gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
20
  faces = face_cascade.detectMultiScale(gray, 1.3, 5)
 
21
  if len(faces) == 0:
22
  return image, None
23
 
24
  x, y, w, h = faces[0]
25
+ cv2.rectangle(image, (x,y), (x+w,y+h), (0,255,0), 2)
26
+ face = cv2.resize(gray[y:y+h, x:x+w], (64,64))
 
 
27
  return image, face.flatten()
28
 
29
+ def embed(face):
30
+ vec = face @ np.random.randn(face.shape[0], 128)
31
+ return vec / np.linalg.norm(vec)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
 
33
+ # =========================
34
  # LOGIC
35
+ # =========================
36
 
37
+ def enroll(img):
38
+ img, face = detect(img)
39
  if face is None:
40
+ return img, None, "❌ No face detected"
41
+ return img, embed(face), "βœ… Face enrolled"
42
 
43
+ def verify(img, stored):
44
+ img, face = detect(img)
 
 
 
45
  if face is None or stored is None:
46
+ return img, "❌ Missing data", None
 
 
 
47
 
48
+ live = embed(face)
49
+ dist = cosine_distances([stored],[live])[0][0]
50
+ status = "πŸ”“ UNLOCKED" if dist < 0.35 else "πŸ”’ DENIED"
51
 
52
+ fig = go.Figure(go.Indicator(
53
  mode="gauge+number",
54
  value=dist,
55
+ gauge={"axis":{"range":[0,1]}},
 
 
 
56
  title={"text": status}
57
  ))
58
+ return img, f"Distance: {dist:.3f}", fig
59
 
60
+ # =========================
 
 
 
 
 
 
 
 
 
61
  # UI
62
+ # =========================
63
 
64
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
65
+ page = gr.State(0)
66
+ emb_state = gr.State()
67
+
68
+ gr.Markdown("# πŸ” Face Unlock – How It Works")
69
 
70
  with gr.Row():
71
  back = gr.Button("β¬… Back")
72
  nextb = gr.Button("Next ➑")
73
 
74
+ # ---------- PAGE 0 ----------
75
+ page0 = gr.Column(visible=True)
76
+ with page0:
77
+ gr.Markdown("## πŸ“Έ Capture Face")
78
+ cam0 = gr.Image(sources=["webcam"], type="numpy")
79
+ out0 = gr.Image()
80
+ gr.Button("Detect").click(detect, cam0, out0)
81
+
82
+ # ---------- PAGE 1 ----------
83
+ page1 = gr.Column(visible=False)
84
+ with page1:
85
+ gr.Markdown("## 🧠 Enroll Face")
86
+ cam1 = gr.Image(sources=["webcam"], type="numpy")
87
+ out1 = gr.Image()
88
+ msg1 = gr.Markdown()
89
+ gr.Button("Enroll").click(enroll, cam1, [out1, emb_state, msg1])
90
+
91
+ # ---------- PAGE 2 ----------
92
+ page2 = gr.Column(visible=False)
93
+ with page2:
94
+ gr.Markdown("## πŸ”“ Verify Face")
95
+ cam2 = gr.Image(sources=["webcam"], type="numpy")
96
+ out2 = gr.Image()
97
+ msg2 = gr.Markdown()
98
+ gauge = gr.Plot()
99
+ gr.Button("Verify").click(verify, [cam2, emb_state], [out2, msg2, gauge])
100
+
101
+ # =========================
102
+ # NAVIGATION
103
+ # =========================
104
+
105
+ def nav(p, step):
106
+ p = min(2, max(0, p+step))
107
+ return (
108
+ p,
109
+ gr.update(visible=p==0),
110
+ gr.update(visible=p==1),
111
+ gr.update(visible=p==2)
112
+ )
113
+
114
+ back.click(nav, [page, gr.State(-1)], [page, page0, page1, page2])
115
+ nextb.click(nav, [page, gr.State(1)], [page, page0, page1, page2])
 
 
 
 
 
 
 
 
116
 
117
  demo.launch()