Spaces:
Sleeping
Sleeping
Update app.py
Browse files
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
|
| 9 |
# =========================
|
| 10 |
|
| 11 |
face_cascade = cv2.CascadeClassifier(
|
| 12 |
cv2.data.haarcascades + "haarcascade_frontalface_default.xml"
|
| 13 |
)
|
| 14 |
|
| 15 |
-
def
|
| 16 |
if image is None:
|
| 17 |
-
return
|
| 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 |
-
#
|
| 35 |
# =========================
|
| 36 |
|
| 37 |
-
def
|
| 38 |
-
img,
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
if face is None:
|
| 40 |
return img, None, "β No face detected"
|
| 41 |
-
return img, embed(face), "β
Face enrolled"
|
| 42 |
|
| 43 |
-
|
| 44 |
-
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 |
-
|
| 56 |
-
|
| 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 |
-
|
| 67 |
|
| 68 |
-
gr.Markdown("# π Face Unlock
|
| 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("## πΈ
|
| 78 |
cam0 = gr.Image(sources=["webcam"], type="numpy")
|
| 79 |
out0 = gr.Image()
|
| 80 |
-
gr.Button("Detect").click(
|
| 81 |
|
| 82 |
# ---------- PAGE 1 ----------
|
| 83 |
page1 = gr.Column(visible=False)
|
| 84 |
with page1:
|
| 85 |
-
gr.Markdown("## π§
|
| 86 |
cam1 = gr.Image(sources=["webcam"], type="numpy")
|
| 87 |
out1 = gr.Image()
|
| 88 |
msg1 = gr.Markdown()
|
| 89 |
-
gr.Button("Enroll").click(
|
|
|
|
|
|
|
|
|
|
|
|
|
| 90 |
|
| 91 |
# ---------- PAGE 2 ----------
|
| 92 |
page2 = gr.Column(visible=False)
|
| 93 |
with page2:
|
| 94 |
-
gr.Markdown("## π
|
| 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(
|
|
|
|
|
|
|
|
|
|
|
|
|
| 100 |
|
| 101 |
# =========================
|
| 102 |
# NAVIGATION
|
| 103 |
# =========================
|
| 104 |
|
| 105 |
-
def
|
| 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(
|
| 115 |
-
nextb.click(
|
| 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()
|