| | import gradio as gr |
| | import tensorflow as tf |
| | import tensorflow_hub as hub |
| | import cv2 |
| | import numpy as np |
| | import tempfile |
| | import json |
| | import uuid |
| |
|
| | |
| | detector = hub.load("https://tfhub.dev/tensorflow/ssd_mobilenet_v2/fpnlite_320x320/1") |
| |
|
| | def detect_faces(image): |
| | """Runs TensorFlow SSD model to detect faces in an image.""" |
| | input_tensor = tf.convert_to_tensor([image], dtype=tf.uint8) |
| | detector_output = detector(input_tensor) |
| | boxes = detector_output['detection_boxes'][0].numpy() |
| | scores = detector_output['detection_scores'][0].numpy() |
| | return boxes[scores > 0.5] |
| |
|
| | def euclidean_hash(box): |
| | """Simple hash based on box centroid""" |
| | y1, x1, y2, x2 = box |
| | cx = (x1 + x2) / 2 |
| | cy = (y1 + y2) / 2 |
| | return str(uuid.uuid5(uuid.NAMESPACE_DNS, f"{cx:.4f}-{cy:.4f}")) |
| |
|
| | def process_frame(frame): |
| | h, w, _ = frame.shape |
| | boxes = detect_faces(frame) |
| | result = [] |
| | for box in boxes: |
| | y1, x1, y2, x2 = box |
| | x1a, y1a, x2a, y2a = int(x1 * w), int(y1 * h), int(x2 * w), int(y2 * h) |
| | face_id = euclidean_hash(box) |
| | result.append({ |
| | "id": face_id, |
| | "coords": [x1a, y1a, x2a, y2a] |
| | }) |
| | cv2.rectangle(frame, (x1a, y1a), (x2a, y2a), (0, 255, 0), 2) |
| | cv2.putText(frame, face_id[:6], (x1a, y1a - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2) |
| | return frame, json.dumps(result, indent=2) |
| |
|
| | def video_handler(video): |
| | cap = cv2.VideoCapture(video) |
| | frames = [] |
| | last_json = {} |
| | while True: |
| | ret, frame = cap.read() |
| | if not ret: |
| | break |
| | tagged_frame, json_result = process_frame(frame) |
| | frames.append(tagged_frame) |
| | last_json = json_result |
| | cap.release() |
| | out_path = tempfile.mktemp(suffix=".mp4") |
| | fourcc = cv2.VideoWriter_fourcc(*'mp4v') |
| | out = cv2.VideoWriter(out_path, fourcc, 15, (frames[0].shape[1], frames[0].shape[0])) |
| | for f in frames: |
| | out.write(f) |
| | out.release() |
| | return out_path, last_json |
| |
|
| | iface = gr.Interface( |
| | fn=video_handler, |
| | inputs=gr.Video(), |
| | outputs=[gr.Video(label="Tagged Video"), gr.Textbox(label="Detected Faces JSON")], |
| | title="Multi-Face Recognizer with Unique ID Hashes", |
| | description="Upload or stream a video. Each detected face will be tagged with a short unique hash." |
| | ) |
| |
|
| | iface.launch() |
| |
|