Spaces:
Sleeping
Sleeping
Upload 4 files
Browse files- app.py +35 -0
- requirements.txt +5 -0
- siamese_model.h5 +3 -0
- utils.py +65 -0
app.py
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import gradio as gr
|
| 2 |
+
import os
|
| 3 |
+
import cv2
|
| 4 |
+
import numpy as np
|
| 5 |
+
from utils import load_model, preprocess, verify_identity
|
| 6 |
+
|
| 7 |
+
model = load_model("siamesemodel.h5")
|
| 8 |
+
registration_dir = "registered_users"
|
| 9 |
+
|
| 10 |
+
def register_user(name, image):
|
| 11 |
+
user_path = os.path.join(registration_dir, name)
|
| 12 |
+
os.makedirs(user_path, exist_ok=True)
|
| 13 |
+
image.save(os.path.join(user_path, f"{name}_1.jpg"))
|
| 14 |
+
return f"User {name} registered successfully."
|
| 15 |
+
|
| 16 |
+
def verify(image):
|
| 17 |
+
result = verify_identity(model, image, registration_dir)
|
| 18 |
+
return result
|
| 19 |
+
|
| 20 |
+
with gr.Blocks() as demo:
|
| 21 |
+
gr.Markdown("## 🧠 Siamese Face Verification")
|
| 22 |
+
with gr.Tab("Register"):
|
| 23 |
+
name = gr.Textbox(label="Enter Your Name")
|
| 24 |
+
reg_img = gr.Image(source="webcam", label="Click Your Photo", shape=(105,105))
|
| 25 |
+
reg_btn = gr.Button("Register")
|
| 26 |
+
reg_output = gr.Textbox()
|
| 27 |
+
reg_btn.click(fn=register_user, inputs=[name, reg_img], outputs=reg_output)
|
| 28 |
+
|
| 29 |
+
with gr.Tab("Verify"):
|
| 30 |
+
ver_img = gr.Image(source="webcam", label="Click Your Photo", shape=(105,105))
|
| 31 |
+
ver_btn = gr.Button("Verify")
|
| 32 |
+
ver_output = gr.Textbox()
|
| 33 |
+
ver_btn.click(fn=verify, inputs=ver_img, outputs=ver_output)
|
| 34 |
+
|
| 35 |
+
demo.launch()
|
requirements.txt
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
gradio
|
| 2 |
+
tensorflow
|
| 3 |
+
opencv-python
|
| 4 |
+
numpy
|
| 5 |
+
Pillow
|
siamese_model.h5
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:d7ca682c8cb287f75eb7dd9b687f61e600150dde688d88034e0a20dbc2ebfca0
|
| 3 |
+
size 467626624
|
utils.py
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import numpy as np
|
| 3 |
+
import tensorflow as tf
|
| 4 |
+
from PIL import Image
|
| 5 |
+
import cv2
|
| 6 |
+
|
| 7 |
+
IMG_SIZE = (105, 105) # same size you trained on
|
| 8 |
+
|
| 9 |
+
# Load the trained Siamese model
|
| 10 |
+
def load_model(model_path):
|
| 11 |
+
model = tf.keras.models.load_model(model_path, custom_objects={'L1Dist': L1Dist})
|
| 12 |
+
return model
|
| 13 |
+
|
| 14 |
+
# Custom L1 distance layer (used in Siamese networks)
|
| 15 |
+
class L1Dist(tf.keras.layers.Layer):
|
| 16 |
+
def __init__(self, **kwargs):
|
| 17 |
+
super().__init__()
|
| 18 |
+
|
| 19 |
+
def call(self, input_embedding, validation_embedding):
|
| 20 |
+
return tf.math.abs(input_embedding - validation_embedding)
|
| 21 |
+
|
| 22 |
+
# Preprocess image for model input
|
| 23 |
+
def preprocess(image):
|
| 24 |
+
# Convert to numpy array if it's PIL
|
| 25 |
+
if isinstance(image, Image.Image):
|
| 26 |
+
image = np.array(image)
|
| 27 |
+
|
| 28 |
+
image = cv2.resize(image, IMG_SIZE)
|
| 29 |
+
image = image / 255.0
|
| 30 |
+
image = np.expand_dims(image, axis=0) # (1, 105, 105, 3)
|
| 31 |
+
return image
|
| 32 |
+
|
| 33 |
+
# Verify identity by comparing input image to stored validation images
|
| 34 |
+
def verify_identity(model, input_img, users_folder, detection_threshold=0.5):
|
| 35 |
+
input_processed = preprocess(input_img)
|
| 36 |
+
|
| 37 |
+
highest_score = 0
|
| 38 |
+
identity = "Unknown"
|
| 39 |
+
|
| 40 |
+
for user in os.listdir(users_folder):
|
| 41 |
+
user_path = os.path.join(users_folder, user)
|
| 42 |
+
if not os.path.isdir(user_path):
|
| 43 |
+
continue
|
| 44 |
+
|
| 45 |
+
for img_file in os.listdir(user_path):
|
| 46 |
+
img_path = os.path.join(user_path, img_file)
|
| 47 |
+
|
| 48 |
+
try:
|
| 49 |
+
val_img = Image.open(img_path).convert('RGB')
|
| 50 |
+
except:
|
| 51 |
+
continue
|
| 52 |
+
|
| 53 |
+
val_processed = preprocess(val_img)
|
| 54 |
+
|
| 55 |
+
# Predict
|
| 56 |
+
result = model.predict([input_processed, val_processed])[0][0]
|
| 57 |
+
|
| 58 |
+
if result > highest_score:
|
| 59 |
+
highest_score = result
|
| 60 |
+
identity = user
|
| 61 |
+
|
| 62 |
+
if highest_score < detection_threshold:
|
| 63 |
+
return "User not recognized."
|
| 64 |
+
else:
|
| 65 |
+
return f"Verified: {identity} (Confidence: {highest_score:.2f})"
|