File size: 3,401 Bytes
f9a0579
dbd0345
f9a0579
dbd0345
f9a0579
dbd0345
f9a0579
dbd0345
f9a0579
dbd0345
f9a0579
 
dbd0345
 
 
 
f9a0579
dbd0345
f9a0579
 
 
 
dbd0345
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f9a0579
dbd0345
 
 
f9a0579
dbd0345
f9a0579
dbd0345
f9a0579
dbd0345
f9a0579
 
dbd0345
 
f9a0579
 
dbd0345
 
 
 
f9a0579
dbd0345
f9a0579
dbd0345
f9a0579
dbd0345
f9a0579
dbd0345
f9a0579
dbd0345
f9a0579
dbd0345
f9a0579
dbd0345
f9a0579
dbd0345
f9a0579
dbd0345
f9a0579
dbd0345
f9a0579
dbd0345
 
 
f9a0579
dbd0345
 
 
f9a0579
dbd0345
f9a0579
dbd0345
 
 
f9a0579
 
dbd0345
 
 
 
9bde0e3
dbd0345
 
 
529c419
dbd0345
 
 
71d8b26
9bde0e3
dbd0345
 
 
 
 
 
9bde0e3
dbd0345
 
 
529c419
dbd0345
 
 
529c419
dbd0345
 
 
529c419
dbd0345
 
 
529c419
dbd0345
 
 
9bde0e3
 
dbd0345
 
 
 
 
 
 
 
 
 
f9a0579
dbd0345
 
 
f9a0579
dbd0345
 
 
f9a0579
dbd0345
 
 
f9a0579
dbd0345
 
 
289c0f6
dbd0345
 
 
9bde0e3
dbd0345
 
 
54ed55d
dbd0345
 
 
f9a0579
 
dbd0345
 
 
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
import gradio as gr

import torch

import torch.nn as nn

from torchvision import models, transforms

from safetensors.torch import load_file

from PIL import Image



# 1. Rebuild the blank ResNet-50 architecture

model = models.resnet50(weights=None)

model.fc = nn.Linear(model.fc.in_features, 2) # 2 classes: Fake (0) and Real (1)



# 2. Load YOUR trained weights from the safetensors file

# Using map_location='cpu' ensures it works on Hugging Face's free CPU tier!

state_dict = load_file("model.safetensors", device="cpu")



# (Optional safety check) If you trained with DataParallel, keys might have "module." in front.

# This removes it so the weights load perfectly no matter what.

state_dict = {k.replace('module.', ''): v for k, v in state_dict.items()}



# Inject the weights into the skeleton and set to test mode

model.load_state_dict(state_dict)

model.eval()



# 3. Define the strict patch transform (No randomness!)

test_transform = transforms.Compose([

    # transforms.Resize(256), # Standard practice to resize slightly before center cropping

    transforms.CenterCrop(224), 

    transforms.ToTensor(),

    transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])

])



classes = ['FAKE', 'REAL']



# 4. Create the prediction function that Gradio will call

def predict_image(img):

    if img is None:

        return None

        

    # Ensure image is strictly RGB (drops alpha channels from PNGs)

    img = img.convert('RGB')

    

    # Apply transforms and add the batch dimension

    img_tensor = test_transform(img).unsqueeze(0) 

    

    with torch.no_grad():

        # Pass through model

        preds = model(img_tensor)

        # Convert raw numbers to percentages (0.0 to 1.0)

        probs = torch.nn.functional.softmax(preds[0], dim=0)

        

    # Gradio expects a dictionary of { "Class Name": probability }

    return {classes[i]: float(probs[i]) for i in range(2)}



# 5. Build and launch the Web App!

description_text = """



###  How it works:



This model analyzes patches of an image to determine if an image is real or AI-generated. 







###  Limitations for best results:



* **Resolution Sweet Spot:** Works flawlessly on standard AI resolutions and mid-sized images (from **512x512 up to around 1000x1500 pixels**, like 640x832 or 880x1320). 



* **The 4K Danger Zone:** Ultra-high-resolution (like **3840x2160 / 4K**) images will cause the model to fail. Because the model's 'magnifying glass' is strictly fixed to a 224x224 pixel crop, it ends up looking through a pinhole at less than 0.6% of a 4K image, causing it to lose context and guess randomly.



* **Centered Subjects:** The model strictly scans the dead-center of the image. If the AI artifacts or mistakes (like extra fingers or warped backgrounds) are on the far edges, the model won't see them!



* **No Screenshots:** Heavy compression (like taking a screenshot or downloading from messaging apps) destroys the microscopic forensic evidence. Please upload the raw, original files.



"""







# Inside your interface:



interface = gr.Interface(



    fn=predict_image,



    inputs=gr.Image(type="pil", label="Upload an Image"),



    outputs=gr.Label(num_top_classes=2, label="Prediction"),



    title="FakeOut: AI Image Detector",



    description=description_text, 



    flagging_mode="never"



)



interface.launch()