| import os |
| import torch |
| import torch.nn as nn |
| import torchvision.models as models |
| from torchvision import transforms |
| from PIL import Image |
|
|
| |
| classes = { |
| 0: "ANGER", |
| 1: "DISGUST", |
| 2: "FEAR", |
| 3: "HAPPINESS", |
| 4: "NEUTRAL", |
| 5: "SADNESS", |
| 6: "SURPRISE", |
| } |
|
|
| IMAGENET_MEAN = [0.485, 0.456, 0.406] |
| IMAGENET_STD = [0.229, 0.224, 0.225] |
| IMG_SIZE = 100 |
|
|
| class facExpRec(nn.Module): |
| """ |
| ResNet18 backbone with custom fc for 7 expressions. |
| Deployment-safe: weights=None, we load your checkpoint. |
| """ |
| def __init__(self, num_classes: int = 7): |
| super().__init__() |
| self.backbone = models.resnet18(weights=None) |
| in_features = self.backbone.fc.in_features |
| self.backbone.fc = nn.Linear(in_features, num_classes) |
|
|
| def forward(self, x): |
| return self.backbone(x) |
|
|
| def ensure_rgb(image: Image.Image) -> Image.Image: |
| if image.mode != "RGB": |
| image = image.convert("RGB") |
| return image |
|
|
| def get_transform(img_size: int = IMG_SIZE): |
| return transforms.Compose([ |
| transforms.Lambda(ensure_rgb), |
| transforms.Resize((img_size, img_size)), |
| transforms.ToTensor(), |
| transforms.Normalize(mean=IMAGENET_MEAN, std=IMAGENET_STD), |
| ]) |
|
|
| trnscm = get_transform(IMG_SIZE) |
|
|
| def load_model(checkpoint_path: str, device: str = "cpu", num_classes: int = 7): |
| model = facExpRec(num_classes=num_classes) |
| state = torch.load(checkpoint_path, map_location=device) |
|
|
| |
| if isinstance(state, dict) and "state_dict" in state: |
| state = state["state_dict"] |
|
|
| |
| |
| sample_key = next(iter(state.keys())) |
| if not sample_key.startswith("backbone."): |
| state = {f"backbone.{k}": v for k, v in state.items()} |
|
|
| model.load_state_dict(state, strict=True) |
| model.to(device) |
| model.eval() |
| return model |
|
|