File size: 2,842 Bytes
64a94a9
 
 
3561a8c
f0ff41c
 
64a94a9
 
 
 
 
 
ed4c5f6
64a94a9
958932b
64a94a9
 
 
 
 
 
 
 
 
 
 
 
3561a8c
 
 
64a94a9
 
 
 
 
 
 
 
 
 
 
 
3561a8c
64a94a9
 
 
 
 
ed4c5f6
 
64a94a9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3561a8c
64a94a9
 
 
3561a8c
64a94a9
 
 
 
3561a8c
923a637
64a94a9
 
 
 
 
 
 
 
 
19e6f0c
64a94a9
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
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()