Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| from transformers import pipeline | |
| from PIL import Image, ExifTags | |
| import cv2 | |
| import numpy as np | |
| # ===== 1. Load 3 Public Models ===== | |
| model_ids = [ | |
| "umm-maybe/AI-image-detector", # Detektor umum | |
| "vikhyatk/moondream2", # Model multimodal | |
| "microsoft/resnet-50" # Baseline visual classifier | |
| ] | |
| detectors = [pipeline("image-classification", model=m) for m in model_ids] | |
| # ===== 2. Fungsi Forensik Manual ===== | |
| def forensic_analysis(img: Image.Image): | |
| img_cv = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR) | |
| # Blur (Laplacian variance) | |
| blur_var = cv2.Laplacian(img_cv, cv2.CV_64F).var() | |
| # Noise (High-pass filter std) | |
| gray = cv2.cvtColor(img_cv, cv2.COLOR_BGR2GRAY) | |
| noise = cv2.Laplacian(gray, cv2.CV_64F).std() | |
| # High-frequency ratio (FFT) | |
| f = np.fft.fft2(gray) | |
| fshift = np.fft.fftshift(f) | |
| magnitude_spectrum = np.abs(fshift) | |
| high_freq_ratio = np.sum(magnitude_spectrum > 50) / magnitude_spectrum.size | |
| # Metadata kamera | |
| exif_data = img.getexif() | |
| has_exif = len(exif_data) > 0 | |
| forensic_score = 0 | |
| if blur_var > 500: forensic_score += 20 | |
| if noise > 10: forensic_score += 20 | |
| if high_freq_ratio > 0.3: forensic_score += 20 | |
| if has_exif: forensic_score += 40 | |
| return { | |
| "blur": round(blur_var, 2), | |
| "noise": round(noise, 2), | |
| "high_freq_ratio": round(high_freq_ratio, 3), | |
| "has_exif": has_exif, | |
| "forensic_score": forensic_score | |
| } | |
| # ===== 3. Fungsi Prediksi Gabungan ===== | |
| def detect_ai(image): | |
| votes = [] | |
| scores = [] | |
| # Jalankan semua model | |
| for det in detectors: | |
| preds = det(image) | |
| label = preds[0]['label'].lower() | |
| score = preds[0]['score'] | |
| if "ai" in label or "fake" in label or "artificial" in label: | |
| votes.append("AI") | |
| else: | |
| votes.append("Real") | |
| scores.append(score) | |
| # Analisis forensik | |
| forensic = forensic_analysis(image) | |
| # Voting | |
| ai_votes = votes.count("AI") | |
| real_votes = votes.count("Real") | |
| if ai_votes > real_votes: | |
| final = "AI" | |
| elif real_votes > ai_votes: | |
| final = "Real" | |
| else: | |
| # Gunakan forensic sebagai tie-breaker | |
| final = "Real" if forensic["forensic_score"] > 50 else "AI" | |
| return { | |
| "Hasil Deteksi": final, | |
| "Voting Model": votes, | |
| "Confidence Scores": scores, | |
| "Forensik": forensic | |
| } | |
| # ===== 4. Gradio UI ===== | |
| demo = gr.Interface( | |
| fn=detect_ai, | |
| inputs=gr.Image(type="pil"), | |
| outputs="json", | |
| title="AI vs Real Image Detector (Ensemble + Forensic)", | |
| description="Menggunakan 3 model publik + analisis forensik (blur, noise, frekuensi, metadata)." | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch() | |