Pranesh64 commited on
Commit
3122e55
Β·
verified Β·
1 Parent(s): 61e47bd

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +43 -27
app.py CHANGED
@@ -5,19 +5,20 @@ 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
 
@@ -31,30 +32,37 @@ def embed(face):
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
  # =========================
@@ -63,9 +71,9 @@ def verify(img, stored):
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")
@@ -74,44 +82,52 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
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()
 
5
  from sklearn.metrics.pairwise import cosine_distances
6
 
7
  # =========================
8
+ # FACE SETUP
9
  # =========================
10
 
11
  face_cascade = cv2.CascadeClassifier(
12
  cv2.data.haarcascades + "haarcascade_frontalface_default.xml"
13
  )
14
 
15
+ def extract_face(image):
16
  if image is None:
17
+ return None, None
18
 
19
  gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
20
  faces = face_cascade.detectMultiScale(gray, 1.3, 5)
21
+
22
  if len(faces) == 0:
23
  return image, None
24
 
 
32
  return vec / np.linalg.norm(vec)
33
 
34
  # =========================
35
+ # STEP FUNCTIONS
36
  # =========================
37
 
38
+ def step_detect(img):
39
+ img, _ = extract_face(img)
40
+ return img
41
+
42
+ def step_enroll(img):
43
+ img, face = extract_face(img)
44
  if face is None:
45
  return img, None, "❌ No face detected"
 
46
 
47
+ emb = embed(face)
48
+ return img, emb, "βœ… Face enrolled"
49
+
50
+ def step_verify(img, stored):
51
+ img, face = extract_face(img)
52
  if face is None or stored is None:
53
  return img, "❌ Missing data", None
54
 
55
  live = embed(face)
56
+ dist = cosine_distances([stored], [live])[0][0]
57
  status = "πŸ”“ UNLOCKED" if dist < 0.35 else "πŸ”’ DENIED"
58
 
59
  fig = go.Figure(go.Indicator(
60
  mode="gauge+number",
61
  value=dist,
62
+ title={"text": status},
63
+ gauge={"axis": {"range": [0, 1]}}
64
  ))
65
+
66
  return img, f"Distance: {dist:.3f}", fig
67
 
68
  # =========================
 
71
 
72
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
73
  page = gr.State(0)
74
+ stored_embedding = gr.State()
75
 
76
+ gr.Markdown("# πŸ” Face Unlock β€” How Mobile Face ID Works")
77
 
78
  with gr.Row():
79
  back = gr.Button("β¬… Back")
 
82
  # ---------- PAGE 0 ----------
83
  page0 = gr.Column(visible=True)
84
  with page0:
85
+ gr.Markdown("## πŸ“Έ Face Detection")
86
  cam0 = gr.Image(sources=["webcam"], type="numpy")
87
  out0 = gr.Image()
88
+ gr.Button("Detect Face").click(step_detect, cam0, out0)
89
 
90
  # ---------- PAGE 1 ----------
91
  page1 = gr.Column(visible=False)
92
  with page1:
93
+ gr.Markdown("## 🧠 Face Enrollment")
94
  cam1 = gr.Image(sources=["webcam"], type="numpy")
95
  out1 = gr.Image()
96
  msg1 = gr.Markdown()
97
+ gr.Button("Enroll Face").click(
98
+ step_enroll,
99
+ cam1,
100
+ [out1, stored_embedding, msg1]
101
+ )
102
 
103
  # ---------- PAGE 2 ----------
104
  page2 = gr.Column(visible=False)
105
  with page2:
106
+ gr.Markdown("## πŸ”“ Face Verification")
107
  cam2 = gr.Image(sources=["webcam"], type="numpy")
108
  out2 = gr.Image()
109
  msg2 = gr.Markdown()
110
  gauge = gr.Plot()
111
+ gr.Button("Verify").click(
112
+ step_verify,
113
+ [cam2, stored_embedding],
114
+ [out2, msg2, gauge]
115
+ )
116
 
117
  # =========================
118
  # NAVIGATION
119
  # =========================
120
 
121
+ def navigate(p, step):
122
+ p = min(2, max(0, p + step))
123
  return (
124
  p,
125
+ gr.update(visible=p == 0),
126
+ gr.update(visible=p == 1),
127
+ gr.update(visible=p == 2)
128
  )
129
 
130
+ back.click(navigate, [page, gr.State(-1)], [page, page0, page1, page2])
131
+ nextb.click(navigate, [page, gr.State(1)], [page, page0, page1, page2])
132
 
133
  demo.launch()