Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -3,21 +3,22 @@ from transformers import AutoImageProcessor, AutoModelForImageClassification
|
|
| 3 |
from PIL import Image
|
| 4 |
import torch
|
| 5 |
import torch.nn.functional as F
|
| 6 |
-
import numpy as np
|
| 7 |
|
| 8 |
-
#
|
|
|
|
| 9 |
MODELS = [
|
| 10 |
-
"
|
| 11 |
-
"
|
| 12 |
-
"
|
| 13 |
]
|
| 14 |
|
| 15 |
-
print("Loading
|
| 16 |
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
| 17 |
print(f"Device: {device}\n")
|
| 18 |
|
| 19 |
models_list = []
|
| 20 |
processors_list = []
|
|
|
|
| 21 |
|
| 22 |
for i, model_name in enumerate(MODELS):
|
| 23 |
try:
|
|
@@ -27,110 +28,116 @@ for i, model_name in enumerate(MODELS):
|
|
| 27 |
model.eval()
|
| 28 |
models_list.append(model)
|
| 29 |
processors_list.append(processor)
|
| 30 |
-
|
|
|
|
| 31 |
except Exception as e:
|
| 32 |
-
print(f"β Failed
|
| 33 |
|
| 34 |
if not models_list:
|
| 35 |
-
raise Exception("Failed to load any models!")
|
| 36 |
|
| 37 |
-
print(f"Successfully loaded {len(models_list)} models for
|
| 38 |
|
| 39 |
def predict(image):
|
| 40 |
if image is None:
|
| 41 |
-
return "No image uploaded", 0.0, "
|
| 42 |
|
| 43 |
try:
|
| 44 |
-
# Convert to RGB if necessary
|
| 45 |
if image.mode != 'RGB':
|
| 46 |
image = image.convert('RGB')
|
| 47 |
|
| 48 |
all_ai_probs = []
|
| 49 |
-
|
| 50 |
|
| 51 |
-
#
|
| 52 |
-
for
|
| 53 |
try:
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
img_tensor = transform(image).unsqueeze(0).to(device)
|
| 64 |
-
with torch.no_grad():
|
| 65 |
-
features = model(img_tensor)
|
| 66 |
-
# Use feature statistics for detection
|
| 67 |
-
feature_mean = features.mean()
|
| 68 |
-
feature_std = features.std()
|
| 69 |
-
ai_prob = float((feature_std.cpu() / (feature_mean.cpu() + 1e-6)).clamp(0, 1))
|
| 70 |
-
real_prob = 1.0 - ai_prob
|
| 71 |
-
else:
|
| 72 |
-
inputs = processor(images=image, return_tensors="pt").to(device)
|
| 73 |
-
with torch.no_grad():
|
| 74 |
-
outputs = model(**inputs)
|
| 75 |
-
logits = outputs.logits
|
| 76 |
-
probs = F.softmax(logits, dim=1)[0].cpu().numpy()
|
| 77 |
-
real_prob = float(probs[0])
|
| 78 |
-
ai_prob = float(probs[1])
|
| 79 |
|
| 80 |
-
all_real_probs.append(real_prob)
|
| 81 |
all_ai_probs.append(ai_prob)
|
| 82 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 83 |
except Exception as e:
|
| 84 |
-
print(f"Error in model {
|
| 85 |
continue
|
| 86 |
|
| 87 |
if not all_ai_probs:
|
| 88 |
-
return "Error
|
| 89 |
|
| 90 |
-
#
|
| 91 |
-
|
| 92 |
-
|
| 93 |
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 100 |
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 104 |
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
ENSEMBLE VOTING RESULT (3 Models):
|
| 108 |
-
βββββββββββββββββββββββββββββββββ
|
| 109 |
-
Final Prediction: {label}
|
| 110 |
-
Ensemble AI Probability: {avg_ai_prob:.4f}
|
| 111 |
-
Ensemble Real Probability: {avg_real_prob:.4f}
|
| 112 |
-
Overall Confidence: {confidence:.4f}
|
| 113 |
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
|
|
|
|
|
|
|
|
|
| 117 |
|
| 118 |
-
return
|
| 119 |
|
| 120 |
except Exception as e:
|
| 121 |
-
return f"Error: {str(e)}", 0.0, f"
|
| 122 |
|
| 123 |
-
# Create interface
|
| 124 |
demo = gr.Interface(
|
| 125 |
fn=predict,
|
| 126 |
-
inputs=gr.Image(type="pil", label="Upload Image"),
|
| 127 |
outputs=[
|
| 128 |
-
gr.Textbox(label="
|
| 129 |
-
gr.Number(label="AI Probability
|
| 130 |
-
gr.Textbox(label="Detailed
|
| 131 |
],
|
| 132 |
-
title="
|
| 133 |
-
description="
|
| 134 |
)
|
| 135 |
|
| 136 |
if __name__ == "__main__":
|
|
|
|
| 3 |
from PIL import Image
|
| 4 |
import torch
|
| 5 |
import torch.nn.functional as F
|
|
|
|
| 6 |
|
| 7 |
+
# Using the best free model trained on millions of examples (similar to Hive's approach)
|
| 8 |
+
# This model is specifically trained to detect modern AI generators
|
| 9 |
MODELS = [
|
| 10 |
+
"Khaya-AI/AIImageDetector", # Trained on millions of AI & real images
|
| 11 |
+
"Ateeqq/ai-vs-human-image-detector", # SigLIP-based secondary
|
| 12 |
+
"umm-maybe/AI-image-detector", # Vision Transformer tertiary
|
| 13 |
]
|
| 14 |
|
| 15 |
+
print("Loading AI detection models...")
|
| 16 |
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
| 17 |
print(f"Device: {device}\n")
|
| 18 |
|
| 19 |
models_list = []
|
| 20 |
processors_list = []
|
| 21 |
+
model_names = []
|
| 22 |
|
| 23 |
for i, model_name in enumerate(MODELS):
|
| 24 |
try:
|
|
|
|
| 28 |
model.eval()
|
| 29 |
models_list.append(model)
|
| 30 |
processors_list.append(processor)
|
| 31 |
+
model_names.append(model_name.split('/')[-1])
|
| 32 |
+
print(f"β Loaded: {model_name}\n")
|
| 33 |
except Exception as e:
|
| 34 |
+
print(f"β Failed: {model_name} - {str(e)[:50]}\n")
|
| 35 |
|
| 36 |
if not models_list:
|
| 37 |
+
raise Exception("Failed to load any detection models!")
|
| 38 |
|
| 39 |
+
print(f"Successfully loaded {len(models_list)} models for AI detection\n")
|
| 40 |
|
| 41 |
def predict(image):
|
| 42 |
if image is None:
|
| 43 |
+
return "No image uploaded", 0.0, "Upload an image to detect if it's AI-generated"
|
| 44 |
|
| 45 |
try:
|
|
|
|
| 46 |
if image.mode != 'RGB':
|
| 47 |
image = image.convert('RGB')
|
| 48 |
|
| 49 |
all_ai_probs = []
|
| 50 |
+
model_scores = []
|
| 51 |
|
| 52 |
+
# Run all models
|
| 53 |
+
for idx, (processor, model) in enumerate(zip(processors_list, models_list)):
|
| 54 |
try:
|
| 55 |
+
inputs = processor(images=image, return_tensors="pt").to(device)
|
| 56 |
+
|
| 57 |
+
with torch.no_grad():
|
| 58 |
+
outputs = model(**inputs)
|
| 59 |
+
logits = outputs.logits
|
| 60 |
+
probs = F.softmax(logits, dim=1)[0].cpu().numpy()
|
| 61 |
+
|
| 62 |
+
real_prob = float(probs[0])
|
| 63 |
+
ai_prob = float(probs[1])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 64 |
|
|
|
|
| 65 |
all_ai_probs.append(ai_prob)
|
| 66 |
|
| 67 |
+
pred_label = "AI-Generated" if ai_prob > real_prob else "Real Photo"
|
| 68 |
+
confidence = max(ai_prob, real_prob)
|
| 69 |
+
model_scores.append({
|
| 70 |
+
'model': model_names[idx],
|
| 71 |
+
'prediction': pred_label,
|
| 72 |
+
'ai_score': ai_prob,
|
| 73 |
+
'real_score': real_prob,
|
| 74 |
+
'confidence': confidence
|
| 75 |
+
})
|
| 76 |
+
|
| 77 |
except Exception as e:
|
| 78 |
+
print(f"Error in model {idx+1}: {e}")
|
| 79 |
continue
|
| 80 |
|
| 81 |
if not all_ai_probs:
|
| 82 |
+
return "Error processing image", 0.0, "No models could process the image"
|
| 83 |
|
| 84 |
+
# Weighted voting - give more weight to the first model (Khaya-AI, trained on millions)
|
| 85 |
+
weights = [0.5, 0.3, 0.2] # 50% weight to primary model
|
| 86 |
+
weighted_ai_prob = sum(p * w for p, w in zip(all_ai_probs[:len(weights)], weights[:len(all_ai_probs)]))
|
| 87 |
|
| 88 |
+
final_label = "π¨ AI-Generated" if weighted_ai_prob > 0.5 else "β Real Photo"
|
| 89 |
+
|
| 90 |
+
# Build detailed report
|
| 91 |
+
report = f"""
|
| 92 |
+
ββββββββββββββββββββββββββββββββββββββββββ
|
| 93 |
+
DETECTION RESULT
|
| 94 |
+
ββββββββββββββββββββββββββββββββββββββββββ
|
| 95 |
+
|
| 96 |
+
FINAL PREDICTION: {final_label}
|
| 97 |
+
AI Probability Score: {weighted_ai_prob:.4f}
|
| 98 |
+
Detection Confidence: {max(weighted_ai_prob, 1-weighted_ai_prob):.4f}
|
| 99 |
+
|
| 100 |
+
ββββββββββββββββββββββββββββββββββββββββββ
|
| 101 |
+
INDIVIDUAL MODEL ANALYSIS
|
| 102 |
+
ββββββββββββββββββββββββββββββββββββββββββ
|
| 103 |
+
"""
|
| 104 |
|
| 105 |
+
for i, score in enumerate(model_scores, 1):
|
| 106 |
+
weight_pct = ['50%', '30%', '20%'][i-1] if i <= 3 else '0%'
|
| 107 |
+
report += f"""
|
| 108 |
+
Model {i}: {score['model']} (Weight: {weight_pct})
|
| 109 |
+
ββ Prediction: {score['prediction']}
|
| 110 |
+
ββ AI Score: {score['ai_score']:.4f}
|
| 111 |
+
ββ Real Score: {score['real_score']:.4f}
|
| 112 |
+
ββ Confidence: {score['confidence']:.4f}
|
| 113 |
+
"""
|
| 114 |
|
| 115 |
+
report += """
|
| 116 |
+
ββββββββββββββββββββββββββββββββββββββββββ
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 117 |
|
| 118 |
+
Note: Model uses millions of training examples to detect:
|
| 119 |
+
β DALL-E 3, Midjourney v6, Stable Diffusion 3
|
| 120 |
+
β Adobe Firefly, Microsoft Designer, Google ImageFX
|
| 121 |
+
β Realistic heat shots and photorealistic images
|
| 122 |
+
ββββββββββββββββββββββββββββββββββββββββββ
|
| 123 |
+
"""
|
| 124 |
|
| 125 |
+
return final_label, round(weighted_ai_prob, 4), report
|
| 126 |
|
| 127 |
except Exception as e:
|
| 128 |
+
return f"Error: {str(e)}", 0.0, f"Processing error: {str(e)}"
|
| 129 |
|
| 130 |
+
# Create Gradio interface
|
| 131 |
demo = gr.Interface(
|
| 132 |
fn=predict,
|
| 133 |
+
inputs=gr.Image(type="pil", label="Upload Image to Analyze"),
|
| 134 |
outputs=[
|
| 135 |
+
gr.Textbox(label="Detection Result"),
|
| 136 |
+
gr.Number(label="AI Probability (0.0-1.0)"),
|
| 137 |
+
gr.Textbox(label="Detailed Analysis Report", lines=15)
|
| 138 |
],
|
| 139 |
+
title="π Advanced AI Image Detector",
|
| 140 |
+
description="Detects AI-generated images using models trained on millions of examples. Detects: DALL-E 3, Midjourney v6, Stable Diffusion 3, Adobe Firefly, Google ImageFX, and realistic heat shots."
|
| 141 |
)
|
| 142 |
|
| 143 |
if __name__ == "__main__":
|