LucasClarke's picture
Upload 4 files
71f7eb2 verified
Raw
History Blame Contribute Delete
2.98 kB
import torch
import torch.nn as nn
import timm
from torchvision import transforms
from PIL import Image
from fastapi import FastAPI, UploadFile, File
import io
import numpy as np
app = FastAPI()
class SingleSwinGAPGMP(nn.Module):
def __init__(self, model_name="swin_tiny_patch4_window7_224", num_classes=3, pretrained=False, drop_path_rate=0.0):
super(SingleSwinGAPGMP, self).__init__()
self.backbone = timm.create_model(
model_name,
pretrained=pretrained,
num_classes=0,
drop_path_rate=drop_path_rate
)
self.num_features = self.backbone.num_features
self.head = nn.Linear(self.num_features * 2, num_classes)
def extract_features(self, x):
x = self.backbone.forward_features(x)
if hasattr(self.backbone, 'norm'):
x = self.backbone.norm(x)
if x.dim() == 4:
gap = x.mean(dim=[1, 2])
gmp = x.amax(dim=[1, 2])
elif x.dim() == 3:
gap = x.mean(dim=1)
gmp = x.amax(dim=1)
else:
gap = x.mean(dim=[-2, -1])
gmp = x.amax(dim=[-2, -1])
return torch.cat([gap, gmp], dim=1)
def forward(self, x):
features = self.extract_features(x)
logits = self.head(features)
return logits
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
MODEL_NAME = "swin_tiny_patch4_window7_224"
num_classes = 3
labels = ["Highly Fresh", "Fresh", "Not Fresh"]
model = SingleSwinGAPGMP(model_name=MODEL_NAME, num_classes=num_classes, pretrained=False)
model.load_state_dict(torch.load("fish_model.pth", map_location=device))
model.to(device)
model.eval()
preprocess = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
])
@app.post("/predict")
async def predict(file: UploadFile = File(...)):
img_bytes = await file.read()
image = Image.open(io.BytesIO(img_bytes)).convert('RGB')
input_tensor = preprocess(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs_orig = model(input_tensor)
outputs_hflip = model(torch.flip(input_tensor, dims=[3]))
outputs_vflip = model(torch.flip(input_tensor, dims=[2]))
outputs_hvflip = model(torch.flip(input_tensor, dims=[2, 3]))
outputs_avg = (outputs_orig + outputs_hflip + outputs_vflip + outputs_hvflip) / 4.0
probabilities = torch.nn.functional.softmax(outputs_avg[0], dim=0)
conf, idx = torch.max(probabilities, 0)
return {
"label": labels[idx.item()],
"confidence": float(conf.item()),
"all_probs": {labels[i]: float(probabilities[i]) for i in range(len(labels))}
}
@app.get("/")
def health_check():
return {"status": "ready", "model": MODEL_NAME}