Spaces:
Sleeping
Sleeping
| import torch | |
| import cv2 | |
| import numpy as np | |
| from pathlib import Path | |
| from fastapi import FastAPI, UploadFile, File, HTTPException | |
| from fastapi.middleware.cors import CORSMiddleware | |
| import tempfile | |
| import os | |
| import json | |
| from models.unet import HierarchicalUNet | |
| from src.inference.analyzer import SegmentationAnalyzer | |
| app = FastAPI(title="OCT Segmentation API") | |
| # Setup CORS to allow requests from the frontend | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') | |
| checkpoint_path = Path(__file__).parent / "unet_hierarchical_best.pth" | |
| model = None | |
| def load_model(): | |
| global model | |
| if checkpoint_path.exists(): | |
| print(f"Loading model from {checkpoint_path}...") | |
| model = HierarchicalUNet(n_channels=1, n_coarse_classes=3, n_granular_classes=15) | |
| checkpoint = torch.load(checkpoint_path, map_location=device, weights_only=True) | |
| model.load_state_dict(checkpoint['model_state_dict']) | |
| model.to(device) | |
| model.eval() | |
| else: | |
| print(f"Warning: Checkpoint {checkpoint_path} not found.") | |
| async def predict_endpoint(file: UploadFile = File(...)): | |
| if model is None: | |
| raise HTTPException(status_code=500, detail="Model not loaded") | |
| suffix = Path(file.filename or "").suffix.lower() | |
| with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as tmp: | |
| content = await file.read() | |
| tmp.write(content) | |
| tmp_path = tmp.name | |
| try: | |
| img = cv2.imread(tmp_path, cv2.IMREAD_GRAYSCALE) | |
| if img is None: | |
| raise HTTPException(status_code=400, detail="Invalid image file") | |
| img_resized = cv2.resize(img, (512, 512)) | |
| img_normalized = img_resized.astype(np.float32) / 255.0 | |
| img_tensor = torch.from_numpy(img_normalized).unsqueeze(0).unsqueeze(0).to(device) | |
| with torch.no_grad(): | |
| coarse_logits, granular_logits = model(img_tensor) | |
| granular_preds = torch.argmax(granular_logits, dim=1).squeeze(0).cpu().numpy() | |
| analyzer = SegmentationAnalyzer() | |
| analysis = analyzer.analyze(granular_preds) | |
| # Convert to dictionary matching the JSON structure | |
| return json.loads(analysis.to_json()) | |
| except Exception as e: | |
| raise HTTPException(status_code=500, detail=str(e)) | |
| finally: | |
| if os.path.exists(tmp_path): | |
| os.remove(tmp_path) | |