Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| from transformers import pipeline | |
| from PIL import Image, ExifTags | |
| import numpy as np | |
| import cv2 | |
| # Model utama AI-detector | |
| detector = pipeline("image-classification", model="umm-maybe/AI-image-detector") | |
| # Model backup (general classifier) | |
| general = pipeline("image-classification", model="google/vit-base-patch16-224") | |
| def analyze_image(img_pil): | |
| img = np.array(img_pil) | |
| # Blur detection (variance of Laplacian) | |
| gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) | |
| blur_score = cv2.Laplacian(gray, cv2.CV_64F).var() | |
| # Noise estimation (std deviation) | |
| noise_score = np.std(gray) | |
| # Edge consistency | |
| edges = cv2.Canny(gray, 100, 200) | |
| edge_score = np.std(edges) | |
| # JPEG artifacts (kasar: std dev dari DCT block) | |
| dct = cv2.dct(np.float32(gray) / 255.0) | |
| jpeg_artifact = np.std(dct) | |
| # Metadata kamera | |
| metadata = "Tidak Ada" | |
| try: | |
| exif_data = img_pil._getexif() | |
| if exif_data: | |
| metadata = "Ada" | |
| except: | |
| pass | |
| return blur_score, noise_score, edge_score, jpeg_artifact, metadata | |
| def detect_image(img): | |
| try: | |
| # Prediksi AI-detector | |
| result1 = detector(img) | |
| label1 = result1[0]['label'] | |
| conf1 = round(result1[0]['score'] * 100, 2) | |
| # Prediksi model general | |
| result2 = general(img) | |
| label2 = result2[0]['label'] | |
| conf2 = round(result2[0]['score'] * 100, 2) | |
| # Analisis teknis | |
| blur, noise, edge, jpeg_art, metadata = analyze_image(img) | |
| # --- Voting System --- | |
| ai_score = 0 | |
| real_score = 0 | |
| # Dari model AI-detector | |
| if "fake" in label1.lower() or "artificial" in label1.lower(): | |
| ai_score += conf1 | |
| elif "real" in label1.lower() or "human" in label1.lower(): | |
| real_score += conf1 | |
| # Dari metadata | |
| if metadata == "Ada": | |
| real_score += 30 # bobot ekstra untuk foto asli | |
| else: | |
| ai_score += 20 | |
| # Dari noise & blur | |
| if noise > 20 and blur > 50: | |
| real_score += 20 | |
| else: | |
| ai_score += 10 | |
| # Hasil akhir | |
| total = ai_score + real_score + 1e-6 | |
| ai_pct = round((ai_score / total) * 100, 2) | |
| real_pct = round((real_score / total) * 100, 2) | |
| if ai_pct > real_pct: | |
| final = f"⚠️ Kemungkinan Besar AI Generated ({ai_pct}%)" | |
| else: | |
| final = f"✅ Kemungkinan Besar Foto Asli ({real_pct}%)" | |
| output = f""" | |
| ### Hasil Deteksi: | |
| {final} | |
| **Persentase AI:** {ai_pct}% | |
| **Persentase Asli:** {real_pct}% | |
| **Model AI-detector:** {label1} ({conf1}%) | |
| **Model General (ViT):** {label2} ({conf2}%) | |
| **Analisis Kamera & Teknis:** | |
| - Blur Score: {round(blur,2)} | |
| - Noise Score: {round(noise,2)} | |
| - Edge Consistency (STD): {round(edge,2)} | |
| - JPEG Artifact Level: {round(jpeg_art,2)} | |
| - Metadata Kamera: {metadata} | |
| """ | |
| return output | |
| except Exception as e: | |
| return f"Terjadi error: {str(e)}" | |
| # UI Gradio | |
| iface = gr.Interface( | |
| fn=detect_image, | |
| inputs=gr.Image(type="pil"), | |
| outputs="markdown", | |
| title="AI vs Real Image Detector (Hybrid)", | |
| description="Deteksi AI vs Foto Asli dengan kombinasi model + analisis teknis (blur, noise, edge, metadata)." | |
| ) | |
| if __name__ == "__main__": | |
| iface.launch() | |