raidAthmaneBenlala commited on
Commit
d6cbcc6
·
1 Parent(s): 8cd65c6

✨ Upgrade backend to support ConvNeXt automatic detection and ResNet18 fallback

Browse files
Files changed (1) hide show
  1. toothmap_backend/models.py +51 -1
toothmap_backend/models.py CHANGED
@@ -4,6 +4,8 @@ from torchvision.models.detection import fasterrcnn_resnet50_fpn_v2
4
  from torchvision.models.detection.faster_rcnn import FastRCNNPredictor
5
  from torchvision.models import resnet18
6
  import segmentation_models_pytorch as smp
 
 
7
  import os
8
 
9
  DEVICE = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
@@ -33,6 +35,43 @@ def _strip_dp(state: dict) -> dict:
33
  return {k.replace("module.", "", 1): v for k, v in state.items()}
34
  return state
35
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  def _load(path: str, model):
37
  if not os.path.exists(path):
38
  print(f"⚠️ Checkpoint not found: {path}")
@@ -49,6 +88,17 @@ def _load(path: str, model):
49
  def load_models(ckpt_dir: str):
50
  print(f"📦 Loading models from: {ckpt_dir}")
51
  MODELS["frcnn"] = _load(os.path.join(ckpt_dir, "frcnn_best.pt"), build_frcnn()).to(DEVICE).eval()
52
- MODELS["cls"] = _load(os.path.join(ckpt_dir, "resnet18_cls_best.pt"), build_classifier()).to(DEVICE).eval()
 
 
 
 
 
 
 
 
 
 
 
53
  MODELS["unet"] = _load(os.path.join(ckpt_dir, "unet_resnet34_best.pt"), build_unet()).to(DEVICE).eval()
54
  print("🚀 All PyTorch models ready.")
 
4
  from torchvision.models.detection.faster_rcnn import FastRCNNPredictor
5
  from torchvision.models import resnet18
6
  import segmentation_models_pytorch as smp
7
+ import torchvision
8
+ from pathlib import Path
9
  import os
10
 
11
  DEVICE = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
 
35
  return {k.replace("module.", "", 1): v for k, v in state.items()}
36
  return state
37
 
38
+ def load_convnext_model(ckpt_path: Path, device: torch.device):
39
+ """Loads ConvNeXt-Tiny customized for 32 FDI classes (>90% Acc Setup)."""
40
+ m = torchvision.models.convnext_tiny(weights=None)
41
+ m.classifier[2] = nn.Linear(m.classifier[2].in_features, 32)
42
+
43
+ if not os.path.exists(ckpt_path):
44
+ print(f"⚠️ ConvNeXt Checkpoint not found: {ckpt_path}. Model will return random garbage until trained.")
45
+ m.to(device)
46
+ m.eval()
47
+ return m
48
+
49
+ state = torch.load(ckpt_path, map_location=device, weights_only=True)
50
+ # Strip any "module." prefix if trained with DataParallel
51
+ new_state = {}
52
+ for k, v in state.items():
53
+ name = k[7:] if k.startswith("module.") else k
54
+ new_state[name] = v
55
+
56
+ m.load_state_dict(new_state)
57
+ m.to(device)
58
+ m.eval()
59
+ return m
60
+
61
+ def load_resnet_model(ckpt_path: Path, device: torch.device):
62
+ """Loads ResNet18 customized for 32 FDI classes."""
63
+ m = torchvision.models.resnet18(weights=None)
64
+ m.fc = nn.Sequential(nn.Dropout(p=0.3), nn.Linear(m.fc.in_features, 32))
65
+ state = torch.load(ckpt_path, map_location=device, weights_only=True)
66
+ new_state = {}
67
+ for k, v in state.items():
68
+ name = k[7:] if k.startswith("module.") else k
69
+ new_state[name] = v
70
+ m.load_state_dict(new_state)
71
+ m.to(device)
72
+ m.eval()
73
+ return m
74
+
75
  def _load(path: str, model):
76
  if not os.path.exists(path):
77
  print(f"⚠️ Checkpoint not found: {path}")
 
88
  def load_models(ckpt_dir: str):
89
  print(f"📦 Loading models from: {ckpt_dir}")
90
  MODELS["frcnn"] = _load(os.path.join(ckpt_dir, "frcnn_best.pt"), build_frcnn()).to(DEVICE).eval()
91
+
92
+ convnext_path = Path(os.path.join(ckpt_dir, "convnext_best.pt"))
93
+ resnet_path = Path(os.path.join(ckpt_dir, "resnet18_cls_best.pt"))
94
+ if convnext_path.exists():
95
+ MODELS["cls"] = load_convnext_model(convnext_path, DEVICE)
96
+ print("✅ ConvNeXt loaded.")
97
+ elif resnet_path.exists():
98
+ MODELS["cls"] = load_resnet_model(resnet_path, DEVICE)
99
+ print("✅ ResNet18 loaded.")
100
+ else:
101
+ print("⚠️ No classification checkpoint found!")
102
+
103
  MODELS["unet"] = _load(os.path.join(ckpt_dir, "unet_resnet34_best.pt"), build_unet()).to(DEVICE).eval()
104
  print("🚀 All PyTorch models ready.")