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()