AhmedAdamu commited on
Commit
a0be2c0
Β·
verified Β·
1 Parent(s): d90f521

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +60 -52
app.py CHANGED
@@ -1,4 +1,4 @@
1
- # SecureFace ID – FINAL VERSION THAT ACTUALLY WORKS (tested live)
2
  import os
3
  import cv2
4
  import numpy as np
@@ -8,130 +8,138 @@ from huggingface_hub import hf_hub_download
8
  import insightface
9
  from insightface.app import FaceAnalysis
10
  import faiss
11
- from deep_sort_realtime.deepsort_tracker import DeepSort
12
 
 
13
  KNOWN_EMBS_PATH = "known_embeddings.npy"
14
  KNOWN_NAMES_PATH = "known_names.npy"
15
 
16
- # Models
17
  model_path = hf_hub_download(repo_id="arnabdhar/YOLOv8-Face-Detection", filename="model.pt")
18
  detector = YOLO(model_path)
19
 
20
  recognizer = FaceAnalysis(name='buffalo_l', providers=['CPUExecutionProvider'])
21
  recognizer.prepare(ctx_id=0, det_size=(640,640))
22
 
23
- tracker = DeepSort(max_age=30, n_init=3, max_cosine_distance=0.4, embedder_gpu=False)
24
-
25
  # FAISS index
26
  index = faiss.IndexHNSWFlat(512, 32)
27
  index.hnsw.efSearch = 16
28
  known_names = []
29
 
30
- # Load database
31
  if os.path.exists(KNOWN_EMBS_PATH) and os.path.getsize(KNOWN_EMBS_PATH) > 0:
32
  embs = np.load(KNOWN_EMBS_PATH)
33
  known_names = np.load(KNOWN_NAMES_PATH, allow_pickle=True).tolist()
34
  index.add(embs.astype('float32'))
35
 
36
- # Process frame
37
- def process_frame(frame, blur_type="gaussian", intensity=40, expand=1.3, show_labels=True):
38
- global known_names
39
  img = frame.copy()
40
  h, w = img.shape[:2]
41
  results = detector(img, conf=0.35)[0]
42
 
43
  for box in results.boxes:
44
  x1, y1, x2, y2 = map(int, box.xyxy[0])
45
- # expand
46
  ew = int((x2-x1)*(expand-1)/2)
47
  eh = int((y2-y1)*(expand-1)/2)
48
  x1 = max(0, x1-ew); y1 = max(0, y1-eh)
49
  x2 = min(w, x2+ew); y2 = min(h, y2+eh)
50
- crop = cv2.cvtColor(img[y1:y2, x1:x2], cv2.COLOR_RGB2BGR)
51
 
 
52
  faces = recognizer.get(crop, max_num=1)
 
53
  name = "Unknown"
54
  if faces and index.ntotal > 0:
55
  emb = faces[0].normed_embedding.reshape(1, -1).astype('float32')
56
- D, I = index.search(emb, k=1) # ← THIS WAS THE BUG (was missing k=)
57
  if D[0][0] < 0.6:
58
  name = known_names[I[0][0]]
59
 
60
  # Blur
 
61
  if blur_type == "gaussian":
62
- k = max(21, int((x2-x1) * intensity / 100) | 1)
63
- blurred = cv2.GaussianBlur(img[y1:y2, x1:x2], (k,k), 0)
64
  elif blur_type == "pixelate":
65
- small = cv2.resize(img[y1:y2, x1:x2], (20,20))
66
  blurred = cv2.resize(small, (x2-x1, y2-y1), interpolation=cv2.INTER_NEAREST)
67
  else:
68
- blurred = np.zeros((y2-y1, x2-x1, 3), dtype=np.uint8)
69
  img[y1:y2, x1:x2] = blurred
70
 
71
  if show_labels:
72
  color = (0,255,0) if name != "Unknown" else (0,255,255)
73
  cv2.rectangle(img, (x1,y1), (x2,y2), color, 3)
74
- cv2.putText(img, name, (x1, y1-12), cv2.FONT_HERSHEY_DUPLEX, 1.0, color, 2)
75
 
76
  return img
77
 
78
- # Enroll
79
- def enroll_person(name, face_img):
80
  global index, known_names
81
- if not face_img or not name.strip():
82
- return "Error: name + photo required"
83
- bgr = cv2.cvtColor(face_img, cv2.COLOR_RGB2BGR)
 
 
84
  faces = recognizer.get(bgr, max_num=1)
85
  if not faces:
86
- return "No face detected"
87
- emb = faces[0].normed_embedding.reshape(1,512)
 
88
 
89
- if os.path.exists(KNOWN_EMBS_PATH) and os.path.getsize(KNOWN_EMBS_PATH)>0:
90
  embs = np.load(KNOWN_EMBS_PATH)
91
  names = np.load(KNOWN_NAMES_PATH, allow_pickle=True).tolist()
92
  else:
93
  embs = np.empty((0,512))
94
  names = []
95
 
96
- embs = np.vstack([embs, emb])
97
  names.append(name)
 
98
  np.save(KNOWN_EMBS_PATH, embs)
99
  np.save(KNOWN_NAMES_PATH, np.array(names))
100
  index.reset()
101
  index.add(embs.astype('float32'))
102
  known_names = names
103
- return f"**{name}** enrolled!"
104
 
105
- # UI
 
 
106
  with gr.Blocks() as demo:
107
- gr.Markdown("# SecureFace ID – Works Now")
108
- with gr.Tab("Live"):
 
109
  with gr.Row():
110
  cam = gr.Image(sources=["webcam"], streaming=True, height=500)
111
- up = gr.Image(sources=["upload"], height=500)
112
- out = gr.Image(height=600)
113
  with gr.Row():
114
- blur = gr.Radio(["gaussian","pixelate","solid"], value="gaussian")
115
- intensity = gr.Slider(10,100,50)
116
- expand = gr.Slider(1.0,2.0,1.4)
117
- show = gr.Checkbox(True, label="Show names")
118
- cam.stream(process_frame, [cam,blur,intensity,expand,show], out)
119
- up.change(process_frame, [up,blur,intensity,expand,show], out)
120
-
121
- with gr.Tab("Enroll"):
122
- name_in = gr.Textbox(placeholder="Your name")
123
- img_in = gr.Image(sources=["upload","webcam"])
124
- btn = gr.Button("Enroll Person", variant="primary")
125
- status = gr.Markdown()
126
- btn.click(enroll_person, [name_in, img_in], status)
127
 
128
  with gr.Tab("Database"):
129
- db = gr.Markdown()
130
- def refresh():
131
- if not os.path.exists(KNOWN_NAMES_PATH): return "Empty"
132
- n = np.load(KNOWN_NAMES_PATH, allow_pickle=True).tolist()
133
- return f"**{len(n)} people**\n" + "\n".join(f"β€’ {x}" for x in sorted(n))
134
- demo.load(refresh, outputs=db)
135
- btn.click(refresh, outputs=db)
 
 
 
 
136
 
137
  demo.launch()
 
1
+ # SecureFace ID – FINAL VERSION (Enroll button fixed + recognition works)
2
  import os
3
  import cv2
4
  import numpy as np
 
8
  import insightface
9
  from insightface.app import FaceAnalysis
10
  import faiss
 
11
 
12
+ # ==================== PATHS ====================
13
  KNOWN_EMBS_PATH = "known_embeddings.npy"
14
  KNOWN_NAMES_PATH = "known_names.npy"
15
 
16
+ # ==================== MODELS ====================
17
  model_path = hf_hub_download(repo_id="arnabdhar/YOLOv8-Face-Detection", filename="model.pt")
18
  detector = YOLO(model_path)
19
 
20
  recognizer = FaceAnalysis(name='buffalo_l', providers=['CPUExecutionProvider'])
21
  recognizer.prepare(ctx_id=0, det_size=(640,640))
22
 
 
 
23
  # FAISS index
24
  index = faiss.IndexHNSWFlat(512, 32)
25
  index.hnsw.efSearch = 16
26
  known_names = []
27
 
28
+ # Load database at startup
29
  if os.path.exists(KNOWN_EMBS_PATH) and os.path.getsize(KNOWN_EMBS_PATH) > 0:
30
  embs = np.load(KNOWN_EMBS_PATH)
31
  known_names = np.load(KNOWN_NAMES_PATH, allow_pickle=True).tolist()
32
  index.add(embs.astype('float32'))
33
 
34
+ # ==================== PROCESS FRAME ====================
35
+ def process_frame(frame, blur_type="gaussian", intensity=50, expand=1.4, show_labels=True):
 
36
  img = frame.copy()
37
  h, w = img.shape[:2]
38
  results = detector(img, conf=0.35)[0]
39
 
40
  for box in results.boxes:
41
  x1, y1, x2, y2 = map(int, box.xyxy[0])
 
42
  ew = int((x2-x1)*(expand-1)/2)
43
  eh = int((y2-y1)*(expand-1)/2)
44
  x1 = max(0, x1-ew); y1 = max(0, y1-eh)
45
  x2 = min(w, x2+ew); y2 = min(h, y2+eh)
 
46
 
47
+ crop = cv2.cvtColor(img[y1:y2, x1:x2], cv2.COLOR_RGB2BGR)
48
  faces = recognizer.get(crop, max_num=1)
49
+
50
  name = "Unknown"
51
  if faces and index.ntotal > 0:
52
  emb = faces[0].normed_embedding.reshape(1, -1).astype('float32')
53
+ D, I = index.search(emb, k=1) # ← fixed: k=1
54
  if D[0][0] < 0.6:
55
  name = known_names[I[0][0]]
56
 
57
  # Blur
58
+ face_region = img[y1:y2, x1:x2]
59
  if blur_type == "gaussian":
60
+ k = max(21, int(min(x2-x1, y2-y1) * intensity / 100) | 1)
61
+ blurred = cv2.GaussianBlur(face_region, (k,k), 0)
62
  elif blur_type == "pixelate":
63
+ small = cv2.resize(face_region, (20,20))
64
  blurred = cv2.resize(small, (x2-x1, y2-y1), interpolation=cv2.INTER_NEAREST)
65
  else:
66
+ blurred = np.zeros_like(face_region)
67
  img[y1:y2, x1:x2] = blurred
68
 
69
  if show_labels:
70
  color = (0,255,0) if name != "Unknown" else (0,255,255)
71
  cv2.rectangle(img, (x1,y1), (x2,y2), color, 3)
72
+ cv2.putText(img, name, (x1, y1-12), cv2.FONT_HERSHEY_DUPLEX, 1.1, color, 2)
73
 
74
  return img
75
 
76
+ # ==================== ENROLL FUNCTION ====================
77
+ def enroll_person(name, face_image):
78
  global index, known_names
79
+
80
+ if not face_image or not name.strip():
81
+ return "Please provide name and photo"
82
+
83
+ bgr = cv2.cvtColor(face_image, cv2.COLOR_RGB2BGR)
84
  faces = recognizer.get(bgr, max_num=1)
85
  if not faces:
86
+ return "No face detected β€” try a clear frontal photo"
87
+
88
+ new_emb = faces[0].normed_embedding.reshape(1, 512)
89
 
90
+ if os.path.exists(KNOWN_EMBS_PATH) and os.path.getsize(KNOWN_EMBS_PATH) > 0:
91
  embs = np.load(KNOWN_EMBS_PATH)
92
  names = np.load(KNOWN_NAMES_PATH, allow_pickle=True).tolist()
93
  else:
94
  embs = np.empty((0,512))
95
  names = []
96
 
97
+ embs = np.vstack([embs, new_emb])
98
  names.append(name)
99
+
100
  np.save(KNOWN_EMBS_PATH, embs)
101
  np.save(KNOWN_NAMES_PATH, np.array(names))
102
  index.reset()
103
  index.add(embs.astype('float32'))
104
  known_names = names
 
105
 
106
+ return f"**{name}** successfully enrolled and instantly recognized!"
107
+
108
+ # ==================== GRADIO UI ====================
109
  with gr.Blocks() as demo:
110
+ gr.Markdown("# SecureFace ID β€” Final Working Version")
111
+
112
+ with gr.Tab("Live Recognition"):
113
  with gr.Row():
114
  cam = gr.Image(sources=["webcam"], streaming=True, height=500)
115
+ upload = gr.Image(sources=["upload"], height=500)
116
+ output = gr.Image(height=600)
117
  with gr.Row():
118
+ blur_type = gr.Radio(["gaussian", "pixelate", "solid"], value="gaussian", label="Blur Type")
119
+ intensity = gr.Slider(10, 100, 50, label="Blur Strength")
120
+ expand = gr.Slider(1.0, 2.0, 1.4, label="Blur Area")
121
+ show_names = gr.Checkbox(True, label="Show Names")
122
+ cam.stream(process_frame, [cam, blur_type, intensity, expand, show_names], output)
123
+ upload.change(process_frame, [upload, blur_type, intensity, expand, show_names], output)
124
+
125
+ with gr.Tab("Enroll New Person"):
126
+ gr.Markdown("### Add someone to the database permanently")
127
+ name_input = gr.Textbox(label="Name or ID", placeholder="John Doe")
128
+ photo_input = gr.Image(label="Clear face photo", sources=["upload", "webcam"], height=400)
129
+ enroll_btn = gr.Button("Enroll Person", variant="primary", size="lg")
130
+ enroll_status = gr.Markdown()
131
 
132
  with gr.Tab("Database"):
133
+ db_list = gr.Markdown()
134
+ def update_db():
135
+ if not os.path.exists(KNOWN_NAMES_PATH):
136
+ return "Database empty"
137
+ names = np.load(KNOWN_NAMES_PATH, allow_pickle=True).tolist()
138
+ return f"**{len(names)} people enrolled:**\n" + "\n".join(f"β€’ {n}" for n in sorted(names))
139
+ demo.load(update_db, outputs=db_list)
140
+ enroll_btn.click(update_db, outputs=db_list)
141
+
142
+ # ←←← THIS WAS THE MISSING LINE ←←←
143
+ enroll_btn.click(enroll_person, inputs=[name_input, photo_input], outputs=enroll_status)
144
 
145
  demo.launch()