Ayush1245678 commited on
Commit
88ce322
·
verified ·
1 Parent(s): 38f9806

Upload 4 files

Browse files
Files changed (4) hide show
  1. app (2).py +109 -0
  2. requirements.txt +9 -0
  3. student_embeddings (1).pkl +3 -0
  4. test_api.py +23 -0
app (2).py ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import pickle
3
+ import tempfile
4
+ import numpy as np
5
+ from numpy.linalg import norm
6
+
7
+ from fastapi import FastAPI, File, UploadFile
8
+ from deepface import DeepFace
9
+
10
+ # =====================================================
11
+ # PATH CONFIG (VERY IMPORTANT FOR DOCKER)
12
+ # =====================================================
13
+ BASE_DIR = os.path.dirname(os.path.abspath(__file__))
14
+ PKL_PATH = os.path.join(BASE_DIR, "student_embeddings.pkl")
15
+
16
+ MODEL_NAME = "Facenet512"
17
+ THRESHOLD = 0.58
18
+
19
+ # =====================================================
20
+ # FASTAPI APP
21
+ # =====================================================
22
+ app = FastAPI(
23
+ title="Face Recognition API",
24
+ description="DeepFace FaceNet512 based Student Recognition API",
25
+ version="1.0"
26
+ )
27
+
28
+ # =====================================================
29
+ # UTILITY FUNCTIONS
30
+ # =====================================================
31
+ def cosine_similarity(a, b):
32
+ return float(np.dot(a, b) / (norm(a) * norm(b)))
33
+
34
+
35
+ def l2_normalize(x):
36
+ return x / norm(x)
37
+
38
+
39
+ # =====================================================
40
+ # LOAD EMBEDDINGS ONCE (SAFE)
41
+ # =====================================================
42
+ if not os.path.exists(PKL_PATH):
43
+ raise FileNotFoundError(f"❌ student_embeddings.pkl not found at {PKL_PATH}")
44
+
45
+ with open(PKL_PATH, "rb") as f:
46
+ db = pickle.load(f)
47
+
48
+ print(f"✅ Loaded {len(db)} student embeddings")
49
+
50
+ # =====================================================
51
+ # HEALTH CHECK (RENDER FRIENDLY)
52
+ # =====================================================
53
+ @app.get("/")
54
+ def health():
55
+ return {
56
+ "status": "running",
57
+ "model": MODEL_NAME,
58
+ "students_loaded": len(db)
59
+ }
60
+
61
+ # =====================================================
62
+ # FACE RECOGNITION ENDPOINT
63
+ # =====================================================
64
+ @app.post("/recognize")
65
+ async def recognize_face(file: UploadFile = File(...)):
66
+ img_path = None
67
+
68
+ try:
69
+ # Save uploaded image to temp file
70
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".jpg") as tmp:
71
+ tmp.write(await file.read())
72
+ img_path = tmp.name
73
+
74
+ # Extract embedding (lazy call)
75
+ result = DeepFace.represent(
76
+ img_path=img_path,
77
+ model_name=MODEL_NAME,
78
+ enforce_detection=True
79
+ )
80
+
81
+ test_emb = np.array(result[0]["embedding"])
82
+ test_emb = l2_normalize(test_emb)
83
+
84
+ best_match = None
85
+ best_score = -1.0
86
+
87
+ # Compare with database
88
+ for name, db_emb in db.items():
89
+ score = cosine_similarity(db_emb, test_emb)
90
+ if score > best_score:
91
+ best_score = score
92
+ best_match = name
93
+
94
+ decision = "MATCH" if best_score >= THRESHOLD else "NO MATCH"
95
+
96
+ return {
97
+ "student": best_match,
98
+ "similarity": round(best_score, 4),
99
+ "cosine_distance": round(1 - best_score, 4),
100
+ "decision": decision
101
+ }
102
+
103
+ except Exception as e:
104
+ return {"error": str(e)}
105
+
106
+ finally:
107
+ # Always clean temp file
108
+ if img_path and os.path.exists(img_path):
109
+ os.remove(img_path)
requirements.txt ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ fastapi
2
+ uvicorn
3
+ python-multipart
4
+
5
+ numpy==1.23.5
6
+ opencv-python-headless==4.8.1.78
7
+
8
+ tensorflow-cpu==2.13.0
9
+ deepface==0.0.79
student_embeddings (1).pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:dd967195b48d5b82cdf86f3ac5178d2eb34dc574eb224488ce57bee6db3f968c
3
+ size 78827
test_api.py ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import requests
2
+ import sys
3
+
4
+ # Test the health endpoint first
5
+ print("Testing health endpoint...")
6
+ response = requests.get("http://127.0.0.1:8000/")
7
+ print(f"Status: {response.status_code}")
8
+ print(f"Response: {response.json()}")
9
+
10
+ # Test face recognition with an image
11
+ if len(sys.argv) > 1:
12
+ img_path = sys.argv[1]
13
+ print(f"\nTesting face recognition with: {img_path}")
14
+
15
+ with open(img_path, "rb") as f:
16
+ files = {"file": f}
17
+ response = requests.post("http://127.0.0.1:8000/recognize", files=files)
18
+
19
+ print(f"Status: {response.status_code}")
20
+ print(f"Response: {response.json()}")
21
+ else:
22
+ print("\nTo test face recognition, provide an image path:")
23
+ print("python test_api.py <image_path>")