Smart Attendance - Liveness Detection Model

This repository contains the face liveness detection (anti-spoofing) models used in the Smart Attendance System. The model determines if a face presented to the camera is a real person (live) or a spoof attempt (e.g., a photo, video replay, or printout).

Versions

Version File Format Input colour order Threshold
v2 (current) liveness_mobilenetv2_final.keras Keras 3 (.keras) RGB 0.9297 (calibrated)
v1 liveness_mobilenet_v2.h5 Keras 2 weights (.h5) BGR not calibrated

Both files stay in this repository. The application loads v2.

v2 Details

  • Architecture: MobileNetV2 backbone, then GlobalAveragePooling, BatchNormalization, Dropout, Dense(128, ReLU), Dropout, Dense(1, Sigmoid).
  • Task: Binary classification, class_names = ["Spoof", "Real"]. The output is the probability of Real.
  • Input shape: (224, 224, 3).
  • Preprocessing: tf.keras.applications.mobilenet_v2.preprocess_input, which scales pixels to [-1.0, 1.0].
  • Threshold: 0.9297026991844177. Scores at or above this value count as live.
  • Test metrics: accuracy 0.9697, ROC-AUC 0.9934, PR-AUC 0.9662.
  • Full settings are in liveness_inference_config.json.

How to use v2

import cv2
import numpy as np
import keras

model = keras.models.load_model("liveness_mobilenetv2_final.keras", compile=False)
THRESHOLD = 0.9297026991844177

def score_face(face_rgb: np.ndarray) -> float:
    resized = cv2.resize(face_rgb, (224, 224)).astype(np.float32)
    batch = np.expand_dims((resized / 127.5) - 1.0, axis=0)  # mobilenet_v2.preprocess_input
    return float(model.predict(batch, verbose=0)[0][0])

# face_rgb: an RGB face crop as a uint8 numpy array
is_live = score_face(face_rgb) >= THRESHOLD

v1 Details

  • Architecture: MobileNetV2 base (pretrained on ImageNet, fine-tuned) with a custom classification head.
  • Input Shape: (224, 224, 3).
  • Preprocessing: convert to BGR (the model was trained on BGR images from OpenCV), resize to (224, 224), and normalize with (x / 127.5) - 1.0.
  • Output: a single sigmoid probability. Near 1.0 indicates a live person, near 0.0 a spoof.

Architecture Specification (v1)

base_model = tf.keras.applications.MobileNetV2(
    input_shape=(224, 224, 3),
    include_top=False,
    weights=None
)
x = base_model.output
x = tf.keras.layers.GlobalAveragePooling2D()(x)
x = tf.keras.layers.Dropout(0.001)(x)
outputs = tf.keras.layers.Dense(1, activation="sigmoid")(x)
model = tf.keras.models.Model(inputs=base_model.input, outputs=outputs)

How to use v1

import cv2
import numpy as np
import tensorflow as tf

# Reconstruct model and load weights
base_model = tf.keras.applications.MobileNetV2(
    input_shape=(224, 224, 3),
    include_top=False,
    weights=None
)
x = base_model.output
x = tf.keras.layers.GlobalAveragePooling2D(name="global_average_pooling2d_3")(x)
x = tf.keras.layers.Dropout(0.001, name="dropout_3")(x)
outputs = tf.keras.layers.Dense(1, activation="sigmoid", name="dense_3")(x)
model = tf.keras.models.Model(inputs=base_model.input, outputs=outputs)
model.load_weights("liveness_mobilenet_v2.h5", by_name=True)

# Ensure face_crop is in BGR format before passing
face_bgr = cv2.cvtColor(face_crop, cv2.COLOR_RGB2BGR)
face_normalized = (cv2.resize(face_bgr, (224, 224)).astype(np.float32) / 127.5) - 1.0
prediction = model.predict(np.expand_dims(face_normalized, axis=0))[0][0]
print(f"Liveness score: {prediction}")
Downloads last month
33
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support

Space using prathamrajbhar/smart-attendance-liveness-detection 1