Jatin-tec
Add application file
65d7391
import gradio as gr
import torch
from PIL import Image
from typing import Dict, Optional, Tuple
from transformers import AutoImageProcessor, SiglipForImageClassification
from trufor_runner import TruForEngine, TruForResult, TruForUnavailableError
MODEL_ID = "Ateeqq/ai-vs-human-image-detector"
# Use GPU when available so large batches stay responsive.
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
try:
processor = AutoImageProcessor.from_pretrained(MODEL_ID)
model = SiglipForImageClassification.from_pretrained(MODEL_ID)
model.to(device)
model.eval()
except Exception as exc: # pragma: no cover - surface loading issues early.
raise RuntimeError(f"Failed to load model from {MODEL_ID}") from exc
try:
TRUFOR_ENGINE: Optional[TruForEngine] = TruForEngine(device="cpu")
TRUFOR_STATUS = TRUFOR_ENGINE.status_message
except TruForUnavailableError as exc:
TRUFOR_ENGINE = None
TRUFOR_STATUS = str(exc)
def analyze_ai_vs_human(image: Image.Image) -> Tuple[Dict[str, float], str]:
"""Run the Hugging Face detector and return confidences with a readable summary."""
if image is None:
empty_scores = {label: 0.0 for label in model.config.id2label.values()}
return empty_scores, "No image provided."
image = image.convert("RGB")
inputs = processor(images=image, return_tensors="pt").to(device)
with torch.no_grad():
logits = model(**inputs).logits
probabilities = torch.softmax(logits, dim=-1)[0]
scores = {
model.config.id2label[idx]: float(probabilities[idx])
for idx in range(probabilities.size(0))
}
top_idx = int(probabilities.argmax().item())
top_label = model.config.id2label[top_idx]
top_score = scores[top_label]
summary = f"**Predicted Label:** {top_label} \
**Confidence:** {top_score:.4f}"
return scores, summary
def analyze_trufor(image: Image.Image) -> Tuple[str, Optional[Image.Image], Optional[Image.Image]]:
"""Run TruFor inference when available, otherwise return diagnostics."""
if TRUFOR_ENGINE is None:
return TRUFOR_STATUS, None, None
if image is None:
return "Upload an image to run TruFor.", None, None
try:
result: TruForResult = TRUFOR_ENGINE.infer(image)
except TruForUnavailableError as exc:
return str(exc), None, None
summary_lines = []
if result.score is not None:
summary_lines.append(f"**Tamper Score:** {result.score:.4f}")
extras_dict = result.raw_scores.copy()
if result.score is not None:
extras_dict.pop("tamper_score", None)
if extras_dict:
extras = " ".join(f"{key}: {value:.4f}" for key, value in extras_dict.items())
summary_lines.append(f"`{extras}`")
if not summary_lines:
summary_lines.append("TruFor returned no scores for this image.")
return "\n".join(summary_lines), result.map_overlay, result.confidence_overlay
def analyze_image(image: Image.Image) -> Tuple[Dict[str, float], str, str, Optional[Image.Image], Optional[Image.Image]]:
ai_scores, ai_summary = analyze_ai_vs_human(image)
trufor_summary, tamper_overlay, conf_overlay = analyze_trufor(image)
return ai_scores, ai_summary, trufor_summary, tamper_overlay, conf_overlay
with gr.Blocks() as demo:
gr.Markdown(
"""# Image Authenticity Workbench\nUpload an image to compare the AI-vs-human classifier with the TruFor forgery detector."""
)
status_box = gr.Markdown(f"`{TRUFOR_STATUS}`")
image_input = gr.Image(label="Input Image", type="pil")
analyze_button = gr.Button("Analyze", variant="primary", size="sm")
with gr.Tabs():
with gr.TabItem("AI vs Human"):
ai_label_output = gr.Label(label="Prediction", num_top_classes=2)
ai_summary_output = gr.Markdown("Upload an image to view the prediction.")
with gr.TabItem("TruFor Forgery Detection"):
trufor_summary_output = gr.Markdown("Configure TruFor assets to enable tamper analysis.")
tamper_overlay_output = gr.Image(label="Tamper Heatmap", type="pil", interactive=False)
conf_overlay_output = gr.Image(label="Confidence Heatmap", type="pil", interactive=False)
output_components = [
ai_label_output,
ai_summary_output,
trufor_summary_output,
tamper_overlay_output,
conf_overlay_output,
]
analyze_button.click(
fn=analyze_image,
inputs=image_input,
outputs=output_components,
)
image_input.change(
fn=analyze_image,
inputs=image_input,
outputs=output_components,
)
if __name__ == "__main__":
demo.launch()