Rubli's picture
Update app.py
0c99d4c verified
Raw History Blame Contribute Delete
5.17 kB
import os
import sys
import gc
import gradio as gr
import torch
import numpy as np
import cv2
import onnxruntime
import spaces
from PIL import Image
from transformers import CLIPImageProcessor
from huggingface_hub import hf_hub_download
# DUMMY GPU FUNCTION (Required for ZeroGPU startup)
@spaces.GPU
def _dummy_gpu_check():
"""
This function is required to satisfy Hugging Face's ZeroGPU startup check.
Our actual models run on CPU to save resources, so this is never used.
"""
return {"status": "ok"}
# CONFIGURATION & SETUP
_DEVICE = "cpu"
FUSION_MODEL_ID = "knmrfr/deepfake-detector"
FUSION_PROCESSOR_ID = "openai/clip-vit-large-patch14"
DETECTRA_REPO = "TensorFold/detectra-v1"
DETECTRA_THRESHOLD = 0.65
FUSION_THRESHOLD = 0.85
_face_cascade = None
def _extract_face(image):
global _face_cascade
if _face_cascade is None:
cascade_path = cv2.data.haarcascades + "haarcascade_frontalface_default.xml"
_face_cascade = cv2.CascadeClassifier(cascade_path)
if image.mode != "RGB": image = image.convert("RGB")
try:
img_bgr = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)
gray = cv2.equalizeHist(cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY))
faces = _face_cascade.detectMultiScale(gray, 1.1, 5, minSize=(30, 30))
if len(faces) == 0: return None
x, y, w, h = faces[0]
return image.crop((x, y, x + w, y + h)).resize((224, 224), Image.BICUBIC)
except Exception:
return None
def _run_detectra(image):
session = None
try:
detectra_path = hf_hub_download(repo_id=DETECTRA_REPO, filename="model.onnx")
session = onnxruntime.InferenceSession(detectra_path, providers=['CPUExecutionProvider'])
input_name = session.get_inputs()[0].name
w, h = image.size
scale = 440 / min(w, h)
new_w, new_h = int(w * scale), int(h * scale)
img_resized = image.resize((new_w, new_h), Image.BILINEAR)
left, top = (new_w - 384) // 2, (new_h - 384) // 2
img_cropped = img_resized.crop((left, top, left + 384, top + 384))
img_array = np.array(img_cropped).astype(np.float32) / 255.0
mean = np.array([0.485, 0.456, 0.406], dtype=np.float32)
std = np.array([0.229, 0.224, 0.225], dtype=np.float32)
img_array = (img_array - mean) / std
img_array = np.transpose(img_array, (2, 0, 1))
img_array = np.expand_dims(img_array, axis=0)
logit = session.run(None, {input_name: img_array})[0]
return float(1 / (1 + np.exp(-logit[0][0])))
except Exception as e:
print(f"Detectra error: {e}")
return 0.0
finally:
if session is not None: del session
gc.collect()
def _run_fusion(image):
model = None
processor = None
try:
model_code_path = hf_hub_download(repo_id=FUSION_MODEL_ID, filename="model.py")
sys.path.insert(0, os.path.dirname(model_code_path))
from model import DeepfakeDetector
model = DeepfakeDetector.from_pretrained(FUSION_MODEL_ID).eval().to(_DEVICE)
processor = CLIPImageProcessor.from_pretrained(FUSION_PROCESSOR_ID)
face = _extract_face(image)
if face is None: return 0.0
inputs = processor(images=face, return_tensors="pt").to(_DEVICE)
with torch.no_grad():
outputs = model(**inputs)
logits = outputs.logits if hasattr(outputs, "logits") else outputs["logits"]
probs = torch.softmax(logits, dim=1)[0]
fake_idx = 1
for i, label in model.id2label.items():
if "fake" in str(label).lower(): fake_idx = int(i); break
return probs[fake_idx].item()
except Exception as e:
print(f"Fusion error: {e}")
return 0.0
finally:
if model is not None: del model
if processor is not None: del processor
gc.collect()
def detect_image(image):
if image is None:
return "No image provided", 0.0, {}
image = image.convert("RGB")
ai_prob = _run_detectra(image)
fusion_prob = _run_fusion(image)
if ai_prob > DETECTRA_THRESHOLD:
verdict = "AI-Generated"
confidence = ai_prob * 100
elif fusion_prob > FUSION_THRESHOLD:
verdict = "Deepfake (Manipulated)"
confidence = fusion_prob * 100
else:
verdict = "Real"
confidence = ((1 - ai_prob) + (1 - fusion_prob)) / 2 * 100
scores = {
"AI_Score": round(ai_prob * 100, 2),
"Deepfake_Score": round(fusion_prob * 100, 2)
}
return verdict, round(confidence, 2), scores
# GRADIO INTERFACE & LAUNCH
demo = gr.Interface(
fn=detect_image,
inputs=gr.Image(type="pil", label="Upload Image"),
outputs=[
gr.Textbox(label="Verdict"),
gr.Number(label="Confidence (%)"),
gr.JSON(label="Detailed Scores")
],
title="Deepfake & AI Image Detector",
description="Upload an image to check if it's Real, AI-Generated, or Manipulated."
)
# Launch at module level so Hugging Face detects the app correctly
if __name__ == "__main__":
demo.launch()