SynthAIzer commited on
Commit
b21d91d
·
verified ·
1 Parent(s): 175a841

Upload 3 files

Browse files
Files changed (3) hide show
  1. app.py +141 -0
  2. requirements.txt +8 -0
  3. yolov8n-face.pt +3 -0
app.py ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import time
3
+ import cv2
4
+ import numpy as np
5
+ import torch
6
+ from ultralytics import YOLO
7
+ from PIL import Image as PILImage
8
+ from keras_facenet import FaceNet
9
+ from transformers import pipeline
10
+ import gradio as gr
11
+ from datetime import datetime, timedelta
12
+ import gc
13
+
14
+ # -----------------------------
15
+ # Device Setup
16
+ # -----------------------------
17
+ DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
18
+ print(f"Using device: {DEVICE}")
19
+
20
+ # -----------------------------
21
+ # Load YOLOv8 Face Model
22
+ # -----------------------------
23
+ MODEL_PATH = "yolov8n-face.pt" # put this file in your Space repository
24
+ face_model = YOLO(MODEL_PATH).to(DEVICE)
25
+
26
+ # -----------------------------
27
+ # Load FaceNet Embedder
28
+ # -----------------------------
29
+ embedder = FaceNet() # CPU mode
30
+
31
+ # -----------------------------
32
+ # Load HuggingFace Age & Gender Models
33
+ # -----------------------------
34
+ age_model = pipeline(
35
+ "image-classification",
36
+ model="prithivMLmods/Age-Classification-SigLIP2",
37
+ device=-1
38
+ )
39
+ gender_model = pipeline(
40
+ "image-classification",
41
+ model="dima806/fairface_gender_image_detection",
42
+ device=-1
43
+ )
44
+
45
+ # -----------------------------
46
+ # Face DB
47
+ # -----------------------------
48
+ FACE_DB = []
49
+ NEXT_ID = 1
50
+
51
+ def clean_gpu():
52
+ if torch.cuda.is_available():
53
+ torch.cuda.empty_cache()
54
+ gc.collect()
55
+
56
+ def cosine_similarity(a, b):
57
+ return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
58
+
59
+ # -----------------------------
60
+ # Main Inference Function
61
+ # -----------------------------
62
+ def process_image(image):
63
+ global NEXT_ID, FACE_DB
64
+ start_time = time.time()
65
+
66
+ rgb_img = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
67
+
68
+ # Detect faces
69
+ results = face_model(rgb_img, verbose=False)
70
+ boxes = results[0].boxes.xyxy.cpu().numpy().astype(int)
71
+
72
+ now = datetime.now()
73
+ FACE_DB = [f for f in FACE_DB if now - f["time"] <= timedelta(hours=1)]
74
+
75
+ faces = []
76
+ for (x1, y1, x2, y2) in boxes:
77
+ face_crop = rgb_img[y1:y2, x1:x2]
78
+ if face_crop.size == 0:
79
+ continue
80
+
81
+ face_embedding = embedder.embeddings([face_crop])[0]
82
+
83
+ assigned_id = None
84
+ age_pred, gender_pred = "unknown", "unknown"
85
+
86
+ # Compare with DB
87
+ if FACE_DB:
88
+ similarities = [cosine_similarity(face_embedding, entry["embedding"]) for entry in FACE_DB]
89
+ best_match_index = int(np.argmax(similarities))
90
+ best_score = similarities[best_match_index]
91
+
92
+ if best_score > 0.6:
93
+ assigned_id = FACE_DB[best_match_index]["id"]
94
+ FACE_DB[best_match_index]["time"] = now
95
+ FACE_DB[best_match_index]["seen_count"] += 1
96
+ age_pred = FACE_DB[best_match_index]["age"]
97
+ gender_pred = FACE_DB[best_match_index]["gender"]
98
+
99
+ if assigned_id is None:
100
+ assigned_id = NEXT_ID
101
+ face_pil = PILImage.fromarray(face_crop)
102
+ try:
103
+ age_pred = age_model(face_pil)[0]["label"]
104
+ gender_pred = gender_model(face_pil)[0]["label"]
105
+ except Exception:
106
+ age_pred, gender_pred = "unknown", "unknown"
107
+
108
+ FACE_DB.append({
109
+ "id": assigned_id,
110
+ "embedding": face_embedding,
111
+ "time": now,
112
+ "seen_count": 1,
113
+ "age": age_pred,
114
+ "gender": gender_pred
115
+ })
116
+ NEXT_ID += 1
117
+
118
+ faces.append({
119
+ "id": assigned_id,
120
+ "age": age_pred,
121
+ "gender": gender_pred,
122
+ "box": [int(x1), int(y1), int(x2), int(y2)]
123
+ })
124
+
125
+ total_time = round(time.time() - start_time, 3)
126
+ clean_gpu()
127
+
128
+ return {"faces": faces, "processing_time_sec": total_time}
129
+
130
+ # -----------------------------
131
+ # Gradio UI
132
+ # -----------------------------
133
+ iface = gr.Interface(
134
+ fn=process_image,
135
+ inputs=gr.Image(type="numpy"),
136
+ outputs="json",
137
+ title="Face Detection + Age/Gender"
138
+ )
139
+
140
+ if __name__ == "__main__":
141
+ iface.launch()
requirements.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ torch
2
+ torchvision
3
+ opencv-python-headless
4
+ ultralytics
5
+ Pillow
6
+ keras-facenet
7
+ transformers
8
+ gradio
yolov8n-face.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d17b38523a994b13ee604b67f02791ca0f43b9f446a32fd7bc44e17c56ead077
3
+ size 6250099