File size: 2,931 Bytes
8c30b41
f034887
f658766
f23fa83
923a637
f658766
505b320
f658766
f034887
 
 
 
 
505b320
0738ed7
f034887
f23fa83
 
 
 
 
 
 
 
 
 
 
f658766
458c1f5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f23fa83
afd314f
f23fa83
269f417
f23fa83
f034887
f23fa83
458c1f5
 
afd314f
 
 
 
 
b0c31d2
0738ed7
afd314f
0738ed7
f034887
0738ed7
f034887
0738ed7
 
 
 
 
afd314f
0738ed7
 
923a637
b735378
923a637
f658766
458c1f5
f658766
b0c31d2
269f417
 
 
 
 
 
8c30b41
923a637
269f417
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
import gradio as gr
from PIL import Image, ExifTags
import numpy as np
import cv2

# ----------------------------
# ANALISIS LOKAL
# ----------------------------
def calculate_blur(image):
    gray = np.array(image.convert("L"))
    return cv2.Laplacian(gray, cv2.CV_64F).var()

def calculate_noise(image):
    gray = np.array(image.convert("L"), dtype=np.float32)
    return np.std(gray - np.mean(gray))

def has_camera_exif(image):
    try:
        exif = image._getexif()
        if exif:
            for tag, value in exif.items():
                decoded = ExifTags.TAGS.get(tag, tag)
                if decoded in ["Make", "Model"]:
                    return True
    except:
        return False
    return False

# -------- FFT ANALYSIS --------
def high_freq_artifacts(image):
    gray = np.array(image.convert("L"), dtype=np.float32)
    f = np.fft.fft2(gray)
    fshift = np.fft.fftshift(f)
    magnitude_spectrum = np.abs(fshift)
    rows, cols = gray.shape
    crow, ccol = rows // 2 , cols // 2
    r = min(crow, ccol) // 4
    mask = np.zeros((rows, cols))
    mask[crow-r:crow+r, ccol-r:ccol+r] = 1
    low_energy = np.sum(magnitude_spectrum * mask)
    total_energy = np.sum(magnitude_spectrum)
    high_ratio = (total_energy - low_energy) / total_energy * 100
    return high_ratio

# ----------------------------
# DETEKSI AI HYBRID ADAPTIF
# ----------------------------
def detect_image(image: Image.Image):
    blur_score = calculate_blur(image)
    noise_score = calculate_noise(image)
    exif_present = has_camera_exif(image)
    high_freq_score = high_freq_artifacts(image)

    # ---------- Scoring adaptif ----------
    hf_norm = min(high_freq_score / 10, 10)
    noise_norm = max(0, 12 - noise_score)
    weighted_score = 0.5 * hf_norm + 0.5 * noise_norm

    # Threshold tegas
    is_ai = False
    if not exif_present and weighted_score > 5 and blur_score < 150:
        is_ai = True

    final_result = "🤖 AI Detected" if is_ai else "✅ Foto Asli"

    output_lines = [
        f"### Hasil Deteksi:\n{final_result}",
        f"Blur Score: {blur_score:.2f}",
        f"Noise Score: {noise_score:.2f}",
        f"High-Freq Artifacts Score: {high_freq_score:.2f}",
        f"Weighted Score: {weighted_score:.2f}",
        f"Metadata Kamera: {'Ada' if exif_present else 'Tidak Ada'}"
    ]

    return "\n".join(output_lines)

# ----------------------------
# GRADIO INTERFACE
# ----------------------------
with gr.Blocks(title="Hybrid AI Realistic Detector (Jejak Digital)") as demo:
    gr.Markdown("Unggah gambar, sistem akan mendeteksi apakah gambar kemungkinan besar asli atau dihasilkan AI.")
    with gr.Row():
        img_input = gr.Image(type="pil", label="Unggah Gambar")
        output_md = gr.Markdown(label="Hasil Deteksi")
    detect_btn = gr.Button("Deteksi")
    detect_btn.click(fn=detect_image, inputs=img_input, outputs=output_md)

if __name__ == "__main__":
    demo.launch()