TropicalBee commited on
Commit
dbd0345
·
verified ·
1 Parent(s): dda8a6e

Update app.py

Browse files

reverted back to my previous version

Files changed (1) hide show
  1. app.py +133 -27
app.py CHANGED
@@ -1,83 +1,189 @@
1
  import gradio as gr
 
2
  import torch
 
3
  import torch.nn as nn
 
4
  from torchvision import models, transforms
 
5
  from safetensors.torch import load_file
 
6
  from PIL import Image
7
 
8
- # 1. Rebuild the skeleton structure globally (Instant execution)
 
 
 
9
  model = models.resnet50(weights=None)
 
10
  model.fc = nn.Linear(model.fc.in_features, 2) # 2 classes: Fake (0) and Real (1)
11
 
12
- # Flag to trace if weights have loaded yet
13
- weights_loaded = False
14
 
15
- def load_model_weights():
16
- global weights_loaded, model
17
- if not weights_loaded:
18
- print(" Loading model weights into memory...")
19
- # Load weights from the safetensors file on CPU
20
- state_dict = load_file("model.safetensors", device="cpu")
21
-
22
- # Clean DataParallel prefix strings if they exist
23
- state_dict = {k.replace('module.', ''): v for k, v in state_dict.items()}
24
-
25
- model.load_state_dict(state_dict)
26
- model.eval()
27
- weights_loaded = True
28
- print(" Weights loaded successfully!")
29
 
30
- # 2. Define the strict patch transform (No randomness!)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  test_transform = transforms.Compose([
 
 
 
32
  transforms.CenterCrop(224),
 
33
  transforms.ToTensor(),
 
34
  transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
 
35
  ])
36
 
 
 
37
  classes = ['FAKE', 'REAL']
38
 
39
- # 3. Create the prediction function that Gradio will call
 
 
 
40
  def predict_image(img):
 
41
  if img is None:
 
42
  return None
 
43
 
44
- # Lazy-load weights on the first click to prevent UI setup blocking
45
- load_model_weights()
46
-
47
  # Ensure image is strictly RGB (drops alpha channels from PNGs)
 
48
  img = img.convert('RGB')
 
49
 
 
50
  # Apply transforms and add the batch dimension
 
51
  img_tensor = test_transform(img).unsqueeze(0)
 
52
 
 
53
  with torch.no_grad():
 
 
 
54
  preds = model(img_tensor)
 
 
 
55
  probs = torch.nn.functional.softmax(preds[0], dim=0)
 
56
 
 
 
 
57
  return {classes[i]: float(probs[i]) for i in range(2)}
58
 
59
- # 4. App Copywriting
 
 
 
60
  description_text = """
 
 
 
61
  ### How it works:
 
 
 
62
  This model analyzes microscopic pixel noise to determine if an image is real or AI-generated.
63
 
 
 
 
 
 
 
64
  ### Limitations for best results:
 
 
 
65
  * **Resolution Sweet Spot:** Works flawlessly on standard AI resolutions and mid-sized images (from **512x512 up to around 1000x1500 pixels**, like 640x832 or 880x1320).
 
 
 
66
  * **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.
 
 
 
67
  * **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!
 
 
 
68
  * **No Screenshots:** Heavy compression (like taking a screenshot or downloading from messaging apps) destroys the microscopic forensic evidence. Please upload the raw, original files.
 
 
 
69
  """
70
 
71
- # 5. Build and launch the Web App!
 
 
 
 
 
 
 
 
 
72
  interface = gr.Interface(
 
 
 
73
  fn=predict_image,
 
 
 
74
  inputs=gr.Image(type="pil", label="Upload an Image"),
 
 
 
75
  outputs=gr.Label(num_top_classes=2, label="Prediction"),
 
 
 
76
  title="PixelSleuth: AI Image Detector",
 
 
 
77
  description=description_text,
 
 
 
78
  flagging_mode="never"
 
 
 
79
  )
80
 
81
- # Launching with a queue handles the connection states cleanly on Hugging Face
82
- if __name__ == "__main__":
83
- interface.queue().launch()
 
1
  import gradio as gr
2
+
3
  import torch
4
+
5
  import torch.nn as nn
6
+
7
  from torchvision import models, transforms
8
+
9
  from safetensors.torch import load_file
10
+
11
  from PIL import Image
12
 
13
+
14
+
15
+ # 1. Rebuild the blank ResNet-50 architecture
16
+
17
  model = models.resnet50(weights=None)
18
+
19
  model.fc = nn.Linear(model.fc.in_features, 2) # 2 classes: Fake (0) and Real (1)
20
 
 
 
21
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
 
23
+ # 2. Load YOUR trained weights from the safetensors file
24
+
25
+ # Using map_location='cpu' ensures it works on Hugging Face's free CPU tier!
26
+
27
+ state_dict = load_file("model.safetensors", device="cpu")
28
+
29
+
30
+
31
+ # (Optional safety check) If you trained with DataParallel, keys might have "module." in front.
32
+
33
+ # This removes it so the weights load perfectly no matter what.
34
+
35
+ state_dict = {k.replace('module.', ''): v for k, v in state_dict.items()}
36
+
37
+
38
+
39
+ # Inject the weights into the skeleton and set to test mode
40
+
41
+ model.load_state_dict(state_dict)
42
+
43
+ model.eval()
44
+
45
+
46
+
47
+ # 3. Define the strict patch transform (No randomness!)
48
+
49
  test_transform = transforms.Compose([
50
+
51
+ # transforms.Resize(256), # Standard practice to resize slightly before center cropping
52
+
53
  transforms.CenterCrop(224),
54
+
55
  transforms.ToTensor(),
56
+
57
  transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
58
+
59
  ])
60
 
61
+
62
+
63
  classes = ['FAKE', 'REAL']
64
 
65
+
66
+
67
+ # 4. Create the prediction function that Gradio will call
68
+
69
  def predict_image(img):
70
+
71
  if img is None:
72
+
73
  return None
74
+
75
 
76
+
 
 
77
  # Ensure image is strictly RGB (drops alpha channels from PNGs)
78
+
79
  img = img.convert('RGB')
80
+
81
 
82
+
83
  # Apply transforms and add the batch dimension
84
+
85
  img_tensor = test_transform(img).unsqueeze(0)
86
+
87
 
88
+
89
  with torch.no_grad():
90
+
91
+ # Pass through model
92
+
93
  preds = model(img_tensor)
94
+
95
+ # Convert raw numbers to percentages (0.0 to 1.0)
96
+
97
  probs = torch.nn.functional.softmax(preds[0], dim=0)
98
+
99
 
100
+
101
+ # Gradio expects a dictionary of { "Class Name": probability }
102
+
103
  return {classes[i]: float(probs[i]) for i in range(2)}
104
 
105
+
106
+
107
+ # 5. Build and launch the Web App!
108
+
109
  description_text = """
110
+
111
+
112
+
113
  ### How it works:
114
+
115
+
116
+
117
  This model analyzes microscopic pixel noise to determine if an image is real or AI-generated.
118
 
119
+
120
+
121
+
122
+
123
+
124
+
125
  ### Limitations for best results:
126
+
127
+
128
+
129
  * **Resolution Sweet Spot:** Works flawlessly on standard AI resolutions and mid-sized images (from **512x512 up to around 1000x1500 pixels**, like 640x832 or 880x1320).
130
+
131
+
132
+
133
  * **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.
134
+
135
+
136
+
137
  * **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!
138
+
139
+
140
+
141
  * **No Screenshots:** Heavy compression (like taking a screenshot or downloading from messaging apps) destroys the microscopic forensic evidence. Please upload the raw, original files.
142
+
143
+
144
+
145
  """
146
 
147
+
148
+
149
+
150
+
151
+
152
+
153
+ # Inside your interface:
154
+
155
+
156
+
157
  interface = gr.Interface(
158
+
159
+
160
+
161
  fn=predict_image,
162
+
163
+
164
+
165
  inputs=gr.Image(type="pil", label="Upload an Image"),
166
+
167
+
168
+
169
  outputs=gr.Label(num_top_classes=2, label="Prediction"),
170
+
171
+
172
+
173
  title="PixelSleuth: AI Image Detector",
174
+
175
+
176
+
177
  description=description_text,
178
+
179
+
180
+
181
  flagging_mode="never"
182
+
183
+
184
+
185
  )
186
 
187
+
188
+
189
+ interface.launch()