TropicalBee commited on
Commit
22ab02f
·
verified ·
1 Parent(s): 529c419

Update app.py

Browse files

i fixed the flashing problem earlier the white interface got displayed first before the text could get loaded..

Files changed (1) hide show
  1. app.py +27 -39
app.py CHANGED
@@ -5,25 +5,30 @@ from torchvision import models, transforms
5
  from safetensors.torch import load_file
6
  from PIL import Image
7
 
8
- # 1. Rebuild the blank ResNet-50 architecture
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
- # 2. Load YOUR trained weights from the safetensors file
13
- # Using map_location='cpu' ensures it works on Hugging Face's free CPU tier!
14
- state_dict = load_file("model.safetensors", device="cpu")
15
 
16
- # (Optional safety check) If you trained with DataParallel, keys might have "module." in front.
17
- # This removes it so the weights load perfectly no matter what.
18
- state_dict = {k.replace('module.', ''): v for k, v in state_dict.items()}
19
-
20
- # Inject the weights into the skeleton and set to test mode
21
- model.load_state_dict(state_dict)
22
- model.eval()
 
 
 
 
 
 
 
23
 
24
- # 3. Define the strict patch transform (No randomness!)
25
  test_transform = transforms.Compose([
26
- # transforms.Resize(256), # Standard practice to resize slightly before center cropping
27
  transforms.CenterCrop(224),
28
  transforms.ToTensor(),
29
  transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
@@ -31,11 +36,14 @@ test_transform = transforms.Compose([
31
 
32
  classes = ['FAKE', 'REAL']
33
 
34
- # 4. Create the prediction function that Gradio will call
35
  def predict_image(img):
36
  if img is None:
37
  return None
38
 
 
 
 
39
  # Ensure image is strictly RGB (drops alpha channels from PNGs)
40
  img = img.convert('RGB')
41
 
@@ -43,53 +51,33 @@ def predict_image(img):
43
  img_tensor = test_transform(img).unsqueeze(0)
44
 
45
  with torch.no_grad():
46
- # Pass through model
47
  preds = model(img_tensor)
48
- # Convert raw numbers to percentages (0.0 to 1.0)
49
  probs = torch.nn.functional.softmax(preds[0], dim=0)
50
 
51
- # Gradio expects a dictionary of { "Class Name": probability }
52
  return {classes[i]: float(probs[i]) for i in range(2)}
53
 
54
- # 5. Build and launch the Web App!
55
  description_text = """
56
-
57
  ### How it works:
58
-
59
  This model analyzes microscopic pixel noise to determine if an image is real or AI-generated.
60
 
61
-
62
-
63
  ### Limitations for best results:
64
-
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
-
67
  * **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.
68
-
69
  * **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!
70
-
71
  * **No Screenshots:** Heavy compression (like taking a screenshot or downloading from messaging apps) destroys the microscopic forensic evidence. Please upload the raw, original files.
72
-
73
  """
74
 
75
-
76
-
77
- # Inside your interface:
78
-
79
  interface = gr.Interface(
80
-
81
  fn=predict_image,
82
-
83
  inputs=gr.Image(type="pil", label="Upload an Image"),
84
-
85
  outputs=gr.Label(num_top_classes=2, label="Prediction"),
86
-
87
  title="PixelSleuth: AI Image Detector",
88
-
89
  description=description_text,
90
-
91
  flagging_mode="never"
92
-
93
  )
94
 
95
- interface.launch()
 
 
 
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])
 
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
 
 
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()