Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,11 +1,10 @@
|
|
| 1 |
import gradio as gr
|
| 2 |
-
from PIL import Image, ImageStat
|
| 3 |
-
from fpdf import FPDF
|
| 4 |
import io
|
| 5 |
|
| 6 |
-
#
|
| 7 |
# EURISTIC AI DETECTOR
|
| 8 |
-
#
|
| 9 |
def heuristic_ai_detector(image):
|
| 10 |
if image.size[0] < 10 or image.size[1] < 10:
|
| 11 |
return "Realistic", 0
|
|
@@ -24,84 +23,74 @@ def heuristic_ai_detector(image):
|
|
| 24 |
label = "AI Generated" if score >= 50 else "Realistic"
|
| 25 |
return label, score
|
| 26 |
|
| 27 |
-
#
|
| 28 |
-
# HEATMAP
|
| 29 |
-
#
|
| 30 |
def generate_heatmap(image, score):
|
| 31 |
base = image.convert("RGBA")
|
| 32 |
overlay = Image.new("RGBA", base.size, (255, 0, 0, int(score*2.55)))
|
| 33 |
return Image.alpha_composite(base, overlay)
|
| 34 |
|
| 35 |
-
#
|
| 36 |
-
# PDF in-memory (funziona HF Spaces)
|
| 37 |
-
# -----------------------------
|
| 38 |
-
def create_pdf(image, text):
|
| 39 |
-
pdf = FPDF()
|
| 40 |
-
pdf.add_page()
|
| 41 |
-
pdf.set_font("Arial", size=12)
|
| 42 |
-
pdf.multi_cell(0, 6, txt=text)
|
| 43 |
-
|
| 44 |
-
# Convert image in RGB e salva in BytesIO
|
| 45 |
-
buf_img = io.BytesIO()
|
| 46 |
-
image.convert("RGB").save(buf_img, format="PNG")
|
| 47 |
-
buf_img.seek(0)
|
| 48 |
-
|
| 49 |
-
# Salva immagine nel PDF usando fpdf
|
| 50 |
-
temp_img_path = "/tmp/temp_image.png"
|
| 51 |
-
with open(temp_img_path, "wb") as f:
|
| 52 |
-
f.write(buf_img.read())
|
| 53 |
-
pdf.image(temp_img_path, x=10, y=pdf.get_y()+10, w=180)
|
| 54 |
-
|
| 55 |
-
# Salva PDF in BytesIO per Gradio
|
| 56 |
-
pdf_bytes = io.BytesIO()
|
| 57 |
-
pdf.output(pdf_bytes)
|
| 58 |
-
pdf_bytes.seek(0)
|
| 59 |
-
pdf_bytes.name = "report.pdf" # GRADIO richiede .name per scaricare
|
| 60 |
-
return pdf_bytes
|
| 61 |
-
|
| 62 |
-
# -----------------------------
|
| 63 |
# FUNZIONE PRINCIPALE
|
| 64 |
-
#
|
| 65 |
def check_image(image):
|
| 66 |
label, score = heuristic_ai_detector(image)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 67 |
if label == "AI Generated":
|
| 68 |
-
explanation =
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
|
|
|
|
|
|
| 75 |
else:
|
| 76 |
-
explanation =
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
|
|
|
|
|
|
| 83 |
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 88 |
|
| 89 |
-
|
| 90 |
-
# INTERFACCIA GRADIO
|
| 91 |
-
# -----------------------------
|
| 92 |
-
iface = gr.Interface(
|
| 93 |
-
fn=check_image,
|
| 94 |
-
inputs=gr.Image(type="pil", label="Carica immagine"),
|
| 95 |
-
outputs=[
|
| 96 |
-
gr.Image(type="pil", label="Evidenziazione sospetta"),
|
| 97 |
-
gr.Textbox(label="Analisi dettagliata"),
|
| 98 |
-
gr.File(label="Scarica report PDF")
|
| 99 |
-
],
|
| 100 |
-
title="💎 Image Trust Checker 2026 (Stable Version)",
|
| 101 |
-
description=(
|
| 102 |
-
"Analizza un'immagine per determinare quanto è affidabile.\n"
|
| 103 |
-
"Basato su euristiche open-source, heatmap e PDF compatibili con HF Spaces."
|
| 104 |
-
),
|
| 105 |
-
)
|
| 106 |
|
| 107 |
-
|
|
|
|
| 1 |
import gradio as gr
|
| 2 |
+
from PIL import Image, ImageStat, ImageDraw, ImageFont
|
|
|
|
| 3 |
import io
|
| 4 |
|
| 5 |
+
# ===========================
|
| 6 |
# EURISTIC AI DETECTOR
|
| 7 |
+
# ===========================
|
| 8 |
def heuristic_ai_detector(image):
|
| 9 |
if image.size[0] < 10 or image.size[1] < 10:
|
| 10 |
return "Realistic", 0
|
|
|
|
| 23 |
label = "AI Generated" if score >= 50 else "Realistic"
|
| 24 |
return label, score
|
| 25 |
|
| 26 |
+
# ===========================
|
| 27 |
+
# GENERA HEATMAP
|
| 28 |
+
# ===========================
|
| 29 |
def generate_heatmap(image, score):
|
| 30 |
base = image.convert("RGBA")
|
| 31 |
overlay = Image.new("RGBA", base.size, (255, 0, 0, int(score*2.55)))
|
| 32 |
return Image.alpha_composite(base, overlay)
|
| 33 |
|
| 34 |
+
# ===========================
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
# FUNZIONE PRINCIPALE
|
| 36 |
+
# ===========================
|
| 37 |
def check_image(image):
|
| 38 |
label, score = heuristic_ai_detector(image)
|
| 39 |
+
heatmap = generate_heatmap(image, score)
|
| 40 |
+
|
| 41 |
+
# Colori output box testuale
|
| 42 |
+
if score < 40:
|
| 43 |
+
color = "#4CAF50" # verde
|
| 44 |
+
elif score < 70:
|
| 45 |
+
color = "#FFC107" # giallo
|
| 46 |
+
else:
|
| 47 |
+
color = "#F44336" # rosso
|
| 48 |
+
|
| 49 |
+
# Testo formattato HTML
|
| 50 |
if label == "AI Generated":
|
| 51 |
+
explanation = f"""
|
| 52 |
+
<div style="border-radius:10px; padding:15px; background-color:{color}; color:white;">
|
| 53 |
+
⚠️ <b>AI Generated Image</b><br>
|
| 54 |
+
Score AI stimato: {score:.1f}%<br>
|
| 55 |
+
Rumore basso / texture uniforme<br>
|
| 56 |
+
Dimensioni insolite<br>
|
| 57 |
+
Metadata EXIF assente
|
| 58 |
+
</div>
|
| 59 |
+
"""
|
| 60 |
else:
|
| 61 |
+
explanation = f"""
|
| 62 |
+
<div style="border-radius:10px; padding:15px; background-color:{color}; color:white;">
|
| 63 |
+
✅ <b>Realistic Image</b><br>
|
| 64 |
+
Score AI stimato: {score:.1f}%<br>
|
| 65 |
+
Rumore naturale<br>
|
| 66 |
+
Dimensioni coerenti<br>
|
| 67 |
+
Metadata EXIF presente
|
| 68 |
+
</div>
|
| 69 |
+
"""
|
| 70 |
|
| 71 |
+
return heatmap, explanation
|
| 72 |
+
|
| 73 |
+
# ===========================
|
| 74 |
+
# GRADIO BLOCKS MODERNO
|
| 75 |
+
# ===========================
|
| 76 |
+
with gr.Blocks(css="""
|
| 77 |
+
body { background-color: #0d1117; font-family: 'Montserrat', sans-serif; color: white; }
|
| 78 |
+
h1 { text-align: center; font-size: 40px; margin-bottom: 0px; color: #FFD700; }
|
| 79 |
+
h3 { text-align: center; font-weight: normal; color: #CCCCCC; }
|
| 80 |
+
.gr-button { background: linear-gradient(90deg, #FFD700, #FFAA00); color:black; font-weight:bold; border-radius:10px; height:50px; }
|
| 81 |
+
.gr-box { background-color: #161B22; border-radius: 15px; padding: 20px; }
|
| 82 |
+
""") as demo:
|
| 83 |
+
|
| 84 |
+
gr.HTML("<h1>💎 Image Trust Checker 2026</h1><h3>Verifica se le immagini sono generate da AI o realistiche</h3>")
|
| 85 |
+
|
| 86 |
+
with gr.Row():
|
| 87 |
+
with gr.Column(scale=1):
|
| 88 |
+
img_input = gr.Image(label="Carica immagine", type="pil")
|
| 89 |
+
analyze_btn = gr.Button("Analizza immagine")
|
| 90 |
+
with gr.Column(scale=1):
|
| 91 |
+
img_output = gr.Image(label="Heatmap sospetta", type="pil")
|
| 92 |
+
txt_output = gr.HTML(label="Risultato")
|
| 93 |
|
| 94 |
+
analyze_btn.click(fn=check_image, inputs=img_input, outputs=[img_output, txt_output])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 95 |
|
| 96 |
+
demo.launch()
|