Arunmass commited on
Commit
bbf2bef
Β·
verified Β·
1 Parent(s): 5a4d29c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +29 -16
app.py CHANGED
@@ -9,6 +9,7 @@ warnings.filterwarnings("ignore")
9
 
10
  import gc
11
  import numpy as np
 
12
  import torch
13
  import torch.nn as nn
14
  import torch.nn.functional as F
@@ -200,14 +201,32 @@ model = HybridAIDetector(
200
  num_features=NUM_FEATURES, feat_embed_dim=128, num_classes=2,
201
  )
202
 
203
- # Load trained hybrid head weights
204
- ckpt = torch.load(HYBRID_HEAD_PATH, map_location="cpu")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
205
  model.feat_mlp.load_state_dict(ckpt["feat_mlp"])
206
  model.head.load_state_dict(ckpt["head"])
207
 
208
  # Load scaler params
209
- SCALER_MEAN = ckpt["scaler_mean"].astype(np.float32)
210
- SCALER_STD = ckpt["scaler_std"].astype(np.float32)
211
 
212
  model.to(DEVICE)
213
  model.eval()
@@ -264,9 +283,9 @@ def get_tta_tensors(img: Image.Image) -> list:
264
  flipped = transforms.functional.hflip(img)
265
  hf_img = high_freq_residual(img)
266
  return [
267
- ("original", base_transforms(img).unsqueeze(0).to(DEVICE)),
268
- ("hflip", base_transforms(flipped).unsqueeze(0).to(DEVICE)),
269
- ("hf_residual",base_transforms(hf_img).unsqueeze(0).to(DEVICE)),
270
  ]
271
 
272
 
@@ -475,9 +494,9 @@ def predict(image: Image.Image) -> dict:
475
  final_probs = sum(w * p for w, p in zip(weights, all_probs))
476
 
477
  return {
478
- "ai_prob": float(final_probs[0]),
479
- "real_prob": float(final_probs[1]),
480
- "raw_scores": raw_scores,
481
  "tta_weights": weights.tolist(),
482
  }
483
 
@@ -572,7 +591,6 @@ custom_css = """
572
  --shadow: 0 4px 6px -1px rgba(0,0,0,.10), 0 2px 4px -1px rgba(0,0,0,.06);
573
  }
574
  .gradio-container { max-width: 1400px !important; margin: 0 auto !important; padding: 1.5rem !important; }
575
-
576
  #header-banner {
577
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
578
  border-radius: 14px; padding: 2rem 2.5rem; text-align: center;
@@ -580,9 +598,7 @@ custom_css = """
580
  }
581
  #header-banner h1 { font-size: 2.2rem; font-weight: 700; margin: 0 0 .5rem; color: white; }
582
  #header-banner p { font-size: 1rem; opacity: .92; margin: 0 auto; max-width: 760px; color: white; }
583
-
584
  #main-row { gap: 1.25rem !important; align-items: stretch !important; }
585
-
586
  #input-panel, #output-panel {
587
  background: var(--c-bg) !important; border: 1px solid var(--c-border) !important;
588
  border-radius: 14px !important; padding: 1.5rem !important;
@@ -598,7 +614,6 @@ custom_css = """
598
  transition: border-color .25s ease !important;
599
  }
600
  #image-upload:hover { border-color: var(--c-primary) !important; }
601
-
602
  #btn-analyze {
603
  background: linear-gradient(135deg, var(--c-primary) 0%, var(--c-primary-d) 100%) !important;
604
  color: white !important; border: none !important; border-radius: 8px !important;
@@ -614,7 +629,6 @@ custom_css = """
614
  transition: border-color .2s ease, color .2s ease !important;
615
  }
616
  #btn-clear:hover { border-color: var(--c-danger) !important; color: var(--c-danger) !important; }
617
-
618
  #output-md .markdown { overflow-y: auto !important; max-height: 680px !important; padding-right: .5rem !important; }
619
  #output-md h2 { font-size: 1.2rem !important; font-weight: 700 !important; color: #1d4ed8 !important;
620
  margin: 1.1rem 0 .5rem !important; padding-bottom: .3rem !important; border-bottom: 1px solid var(--c-border) !important; }
@@ -630,7 +644,6 @@ custom_css = """
630
  #output-md hr { border: none !important; border-top: 1.5px solid var(--c-border) !important; margin: .9rem 0 !important; }
631
  #output-md blockquote { border-left: 3px solid var(--c-primary) !important; margin: .6rem 0 !important;
632
  padding: .3rem .7rem !important; background: #eff6ff !important; border-radius: 0 6px 6px 0 !important; }
633
-
634
  #footer { text-align: center; margin-top: 1.5rem; padding: 1.25rem; background: var(--c-bg);
635
  border-radius: 12px; border: 1px solid var(--c-border); color: var(--c-text-muted); font-size: .875rem; }
636
  """
 
9
 
10
  import gc
11
  import numpy as np
12
+ import numpy.core.multiarray # explicit import for safe_globals
13
  import torch
14
  import torch.nn as nn
15
  import torch.nn.functional as F
 
201
  num_features=NUM_FEATURES, feat_embed_dim=128, num_classes=2,
202
  )
203
 
204
+ # ── FIX: PyTorch 2.6 changed weights_only default to True.
205
+ # Our checkpoint stores numpy arrays (scaler_mean / scaler_std), so we must
206
+ # either allowlist the numpy globals or load with weights_only=False.
207
+ # We use the safe-globals approach (preferred over weights_only=False).
208
+ # ─────────────────────────────────────────────────────────────────────────────
209
+ _numpy_safe_globals = [
210
+ numpy.core.multiarray._reconstruct,
211
+ np.ndarray,
212
+ np.dtype,
213
+ ]
214
+ # numpy 2.x moved internals to numpy._core; allowlist both spellings defensively
215
+ try:
216
+ import numpy._core.multiarray as _nca
217
+ _numpy_safe_globals.append(_nca._reconstruct)
218
+ except Exception:
219
+ pass
220
+
221
+ with torch.serialization.safe_globals(_numpy_safe_globals):
222
+ ckpt = torch.load(HYBRID_HEAD_PATH, map_location="cpu", weights_only=True)
223
+
224
  model.feat_mlp.load_state_dict(ckpt["feat_mlp"])
225
  model.head.load_state_dict(ckpt["head"])
226
 
227
  # Load scaler params
228
+ SCALER_MEAN = np.array(ckpt["scaler_mean"], dtype=np.float32)
229
+ SCALER_STD = np.array(ckpt["scaler_std"], dtype=np.float32)
230
 
231
  model.to(DEVICE)
232
  model.eval()
 
283
  flipped = transforms.functional.hflip(img)
284
  hf_img = high_freq_residual(img)
285
  return [
286
+ ("original", base_transforms(img).unsqueeze(0).to(DEVICE)),
287
+ ("hflip", base_transforms(flipped).unsqueeze(0).to(DEVICE)),
288
+ ("hf_residual", base_transforms(hf_img).unsqueeze(0).to(DEVICE)),
289
  ]
290
 
291
 
 
494
  final_probs = sum(w * p for w, p in zip(weights, all_probs))
495
 
496
  return {
497
+ "ai_prob": float(final_probs[0]),
498
+ "real_prob": float(final_probs[1]),
499
+ "raw_scores": raw_scores,
500
  "tta_weights": weights.tolist(),
501
  }
502
 
 
591
  --shadow: 0 4px 6px -1px rgba(0,0,0,.10), 0 2px 4px -1px rgba(0,0,0,.06);
592
  }
593
  .gradio-container { max-width: 1400px !important; margin: 0 auto !important; padding: 1.5rem !important; }
 
594
  #header-banner {
595
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
596
  border-radius: 14px; padding: 2rem 2.5rem; text-align: center;
 
598
  }
599
  #header-banner h1 { font-size: 2.2rem; font-weight: 700; margin: 0 0 .5rem; color: white; }
600
  #header-banner p { font-size: 1rem; opacity: .92; margin: 0 auto; max-width: 760px; color: white; }
 
601
  #main-row { gap: 1.25rem !important; align-items: stretch !important; }
 
602
  #input-panel, #output-panel {
603
  background: var(--c-bg) !important; border: 1px solid var(--c-border) !important;
604
  border-radius: 14px !important; padding: 1.5rem !important;
 
614
  transition: border-color .25s ease !important;
615
  }
616
  #image-upload:hover { border-color: var(--c-primary) !important; }
 
617
  #btn-analyze {
618
  background: linear-gradient(135deg, var(--c-primary) 0%, var(--c-primary-d) 100%) !important;
619
  color: white !important; border: none !important; border-radius: 8px !important;
 
629
  transition: border-color .2s ease, color .2s ease !important;
630
  }
631
  #btn-clear:hover { border-color: var(--c-danger) !important; color: var(--c-danger) !important; }
 
632
  #output-md .markdown { overflow-y: auto !important; max-height: 680px !important; padding-right: .5rem !important; }
633
  #output-md h2 { font-size: 1.2rem !important; font-weight: 700 !important; color: #1d4ed8 !important;
634
  margin: 1.1rem 0 .5rem !important; padding-bottom: .3rem !important; border-bottom: 1px solid var(--c-border) !important; }
 
644
  #output-md hr { border: none !important; border-top: 1.5px solid var(--c-border) !important; margin: .9rem 0 !important; }
645
  #output-md blockquote { border-left: 3px solid var(--c-primary) !important; margin: .6rem 0 !important;
646
  padding: .3rem .7rem !important; background: #eff6ff !important; border-radius: 0 6px 6px 0 !important; }
 
647
  #footer { text-align: center; margin-top: 1.5rem; padding: 1.25rem; background: var(--c-bg);
648
  border-radius: 12px; border: 1px solid var(--c-border); color: var(--c-text-muted); font-size: .875rem; }
649
  """