Noursine's picture
Update app.py
93b9840 verified
import os
import requests
import cv2
import numpy as np
import torch
import base64
from fastapi import FastAPI, UploadFile, File
from fastapi.responses import JSONResponse
from detectron2.config import get_cfg
from detectron2.engine import DefaultPredictor
from detectron2 import model_zoo
from PIL import Image
import io
app = FastAPI(title="Roof Segmentation API")
@app.get("/")
def home():
return {"status": "running"}
MODEL_PATH = "model_final (4).pth"
# -----------------------------
# 2. Configure Detectron2
# -----------------------------
cfg = get_cfg()
cfg.merge_from_file(model_zoo.get_config_file("COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml"))
cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.5
cfg.MODEL.ROI_HEADS.NUM_CLASSES = 1
cfg.MODEL.WEIGHTS = MODEL_PATH
cfg.MODEL.DEVICE = "cpu" # Hugging Face Spaces default (no GPU)
predictor = DefaultPredictor(cfg)
# -----------------------------
# 3. Helper: Encode mask to Base64
# -----------------------------
def encode_mask(mask: np.ndarray) -> str:
"""Convert mask numpy array to base64 PNG string."""
mask_img = Image.fromarray(mask.astype(np.uint8))
buf = io.BytesIO()
mask_img.save(buf, format="PNG")
return base64.b64encode(buf.getvalue()).decode("utf-8")
# -----------------------------
# 4. API Endpoint
# -----------------------------
@app.post("/predict")
async def predict(file: UploadFile = File(...)):
# Read image
contents = await file.read()
image = Image.open(io.BytesIO(contents)).convert("RGB")
image = np.array(image)[:, :, ::-1] # to BGR for OpenCV/Detectron2
# Run inference
outputs = predictor(image)
instances = outputs["instances"].to("cpu")
results = []
mask_b64 = None
if instances.has("pred_masks"):
masks = instances.pred_masks.numpy()
boxes = instances.pred_boxes.tensor.numpy()
scores = instances.scores.numpy()
# Combine masks into one
combined_mask = np.any(masks, axis=0).astype(np.uint8) * 255
mask_b64 = encode_mask(combined_mask)
for i in range(len(masks)):
results.append({
"box": boxes[i].tolist(),
"score": float(scores[i])
})
return JSONResponse({
"predictions": results,
"mask": mask_b64 # base64 string (PNG)
})