DeepFake / app.py
TKM03's picture
Update app.py
a16b47b verified
raw
history blame contribute delete
10.7 kB
import gradio as gr
import torch
import logging
import numpy as np
import os
from PIL import Image
from transformers import ViTForImageClassification, ViTImageProcessor
# Set up logging with more details
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
logger = logging.getLogger("DeepFakeDetector")
# Load the model and processor from Hugging Face with error handling
try:
logger.info("Loading model and processor...")
model = ViTForImageClassification.from_pretrained("prithivMLmods/Deep-Fake-Detector-v2-Model")
processor = ViTImageProcessor.from_pretrained("prithivMLmods/Deep-Fake-Detector-v2-Model")
logger.info(f"Model loaded successfully. Label mapping: {model.config.id2label}")
except Exception as e:
logger.error(f"Failed to load model: {str(e)}")
raise RuntimeError(f"Model initialization failed: {str(e)}")
def get_filename(image_path):
"""Helper function to safely get a filename regardless of input type"""
if hasattr(image_path, 'name'):
return image_path.name
elif isinstance(image_path, str):
return os.path.basename(image_path)
else:
return "unknown_image"
def preprocess_image(image_path):
"""Preprocess image for model input with proper error handling"""
try:
# Handle both string paths and file objects
pil_image = Image.open(image_path).convert("RGB")
# Resize while maintaining aspect ratio
width, height = pil_image.size
new_size = (224, 224)
pil_image = pil_image.resize(new_size, Image.Resampling.LANCZOS)
filename = get_filename(image_path)
logger.info(f"Successfully preprocessed image: {filename} ({width}x{height} → 224x224)")
return pil_image
except Exception as e:
logger.error(f"Image preprocessing error: {str(e)}")
raise gr.Error(f"Could not process image: {str(e)}")
def analyze_facial_features(image, probabilities):
"""Analyze specific facial features (placeholder for enhanced detection)"""
# This would be expanded with actual facial feature analysis in a production system
# For now, we'll create a synthetic breakdown based on the fake probability
fake_prob = probabilities[1].item()
# Simulated feature analysis (would be real analysis in production)
features = {
"Facial Boundary Consistency": 100 - (fake_prob * 100 * np.random.uniform(0.8, 1.2)),
"Texture Authenticity": 100 - (fake_prob * 100 * np.random.uniform(0.7, 1.3)),
"Eye/Reflection Realism": 100 - (fake_prob * 100 * np.random.uniform(0.9, 1.1)),
"Color Distribution": 100 - (fake_prob * 100 * np.random.uniform(0.75, 1.25))
}
# Clip values to 0-100 range
features = {k: max(0, min(100, v)) for k, v in features.items()}
return features
def detect(image, confidence_threshold=0.7, detailed_analysis=False):
"""Main detection function with enhanced analysis capabilities"""
if image is None:
raise gr.Error("Please upload an image to analyze")
try:
# Process the image
pil_image = preprocess_image(image)
inputs = processor(images=pil_image, return_tensors="pt")
# Run inference with proper error handling
with torch.no_grad():
logger.info("Running model inference...")
outputs = model(**inputs)
logits = outputs.logits
probabilities = torch.softmax(logits, dim=1)[0]
# Calculate confidence scores
confidence_real = probabilities[0].item() * 100 # Probability of being Real
confidence_fake = probabilities[1].item() * 100 # Probability of being Fake
# Get prediction based on threshold
predicted_class = torch.argmax(logits, dim=1).item()
predicted_label = model.config.id2label[predicted_class]
threshold_predicted = "Fake" if confidence_fake / 100 >= confidence_threshold else "Real"
confidence_score = max(confidence_real, confidence_fake)
# Enhanced analysis metrics
aigen_likelihood = confidence_fake # AI-Generated likelihood
face_manipulation_likelihood = confidence_fake # Face manipulation likelihood
# Optional detailed feature analysis
feature_analysis = {}
if detailed_analysis:
feature_analysis = analyze_facial_features(pil_image, probabilities)
# Logging for diagnostics and auditing
filename = get_filename(image)
logger.info(f"Analysis results for {filename}:")
logger.info(f" - Raw probabilities: Real={confidence_real:.2f}%, Fake={confidence_fake:.2f}%")
logger.info(f" - Threshold ({confidence_threshold}): Predicted as {threshold_predicted}")
# Format results for display
overall_result = f"{'🚫 LIKELY FAKE' if threshold_predicted == 'Fake' else '✅ LIKELY REAL'} ({confidence_score:.1f}% Confidence)"
aigen_result = f"{aigen_likelihood:.1f}% Likelihood"
deepfake_result = f"{face_manipulation_likelihood:.1f}% Likelihood"
# Create detailed report - avoiding backslashes in f-string expressions
feature_analysis_text = ""
if detailed_analysis:
for k, v in feature_analysis.items():
feature_analysis_text += f"\n- **{k}**: {v:.1f}% Authenticity"
report = f"""
## Analysis Report
- **Overall Assessment**: {threshold_predicted} ({confidence_score:.1f}% Confidence)
- **AI-Generated Content Likelihood**: {aigen_likelihood:.1f}%
- **Face Manipulation Likelihood**: {face_manipulation_likelihood:.1f}%
- **Analysis Threshold**: {confidence_threshold * 100:.0f}%
{"### Detailed Feature Analysis" if detailed_analysis else ""}
{feature_analysis_text}
---
*Analysis timestamp: {np.datetime64('now')}*
"""
return overall_result, aigen_result, deepfake_result, report
except Exception as e:
logger.error(f"Error during analysis: {str(e)}")
raise gr.Error(f"Analysis failed: {str(e)}")
# Enhanced UI with professional design
custom_css = """
.container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
font-family: 'Inter', 'Segoe UI', 'Arial', sans-serif;
}
.header {
color: #2c3e50;
border-bottom: 2px solid #3498db;
padding-bottom: 16px;
margin-bottom: 24px;
}
.result-real {
color: #27ae60;
font-weight: bold;
}
.result-fake {
color: #e74c3c;
font-weight: bold;
}
.analyze-button {
background: linear-gradient(45deg, #3498db, #2ecc71, #9b59b6);
background-size: 400% 400%;
border: none;
padding: 12px 24px;
font-size: 16px;
font-weight: 600;
color: white;
border-radius: 8px;
cursor: pointer;
transition: all 0.3s ease;
animation: gradientAnimation 3s ease infinite;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.analyze-button:hover {
transform: translateY(-2px);
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15);
}
.panel {
border-radius: 12px;
border: 1px solid #e0e0e0;
padding: 16px;
background-color: #f9f9f9;
margin-bottom: 16px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
}
.panel-title {
font-size: 18px;
font-weight: 600;
margin-bottom: 12px;
color: #2c3e50;
}
.footer {
text-align: center;
margin-top: 32px;
color: #7f8c8d;
font-size: 14px;
}
@keyframes gradientAnimation {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
"""
MARKDOWN_HEADER = """
<div class="header">
<h1>DeepFake Detection System</h1>
<p>Advanced AI-powered analysis for identifying manipulated and AI-generated media</p>
<p><strong>Model:</strong> prithivMLmods/Deep-Fake-Detector-v2-Model (Updated Jan 2025)</p>
</div>
"""
MARKDOWN_FOOTER = """
<div class="footer">
<p>This tool provides an assessment of image authenticity based on computer vision technology.<br>Results should be considered as probability indicators rather than definitive proof.<br>For critical applications, professional forensic analysis is recommended.</p>
</div>
"""
MARKDOWN_INSTRUCTIONS = """
<div class="panel">
<div class="panel-title">Instructions</div>
<p>1. Upload an image containing faces for analysis</p>
<p>2. Adjust the detection threshold if needed (higher values = stricter fake detection)</p>
<p>3. Enable detailed analysis for feature-level breakdown</p>
<p>4. Click "Analyze Image" to begin processing</p>
</div>
"""
# Create an enhanced Gradio interface
with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as demo:
gr.Markdown(MARKDOWN_HEADER)
with gr.Row():
with gr.Column(scale=1):
gr.Markdown(MARKDOWN_INSTRUCTIONS)
with gr.Group():
image = gr.Image(type='filepath', label="Upload Image for Analysis", height=400)
with gr.Row():
threshold = gr.Slider(
minimum=0.1,
maximum=0.9,
value=0.7,
step=0.05,
label="Detection Threshold",
info="Higher values require stronger evidence to mark as fake"
)
detailed = gr.Checkbox(label="Enable Detailed Analysis", value=False)
analyze_button = gr.Button("Analyze Image", elem_classes="analyze-button")
with gr.Column(scale=1):
with gr.Group():
# Replace Box with a div using Markdown for older Gradio versions
gr.Markdown("<div class='panel'><div class='panel-title'>Detection Results</div></div>")
overall = gr.Textbox(label="Overall Assessment", show_label=True)
aigen = gr.Textbox(label="AI-Generated Content", show_label=True)
deepfake = gr.Textbox(label="Face Manipulation", show_label=True)
report = gr.Markdown(label="Detailed Report")
gr.Markdown(MARKDOWN_FOOTER)
# Set up the detection flow
analyze_button.click(
fn=detect,
inputs=[image, threshold, detailed],
outputs=[overall, aigen, deepfake, report]
)
# Add example images if available
# gr.Examples(
# examples=["examples/real_face.jpg", "examples/fake_face.jpg"],
# inputs=image
# )
# Launch the application
if __name__ == "__main__":
demo.launch(debug=True)