Noursine's picture
Update meaw.py
caa19ba verified
import os
import io
import base64
import cv2
import torch
import numpy as np
from PIL import Image
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 detectron2.utils.visualizer import Visualizer
from detectron2.data import MetadataCatalog
app = FastAPI(title="Roof Segmentation API")
@app.get("/")
def home():
return {"status": "running"}
MODEL_PATH = "model_final (4).pth"
# -----------------------------
# 1. 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" # Use "cuda" if you have GPU
predictor = DefaultPredictor(cfg)
# Morphology kernel for polygon smoothing
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
# -----------------------------
# Helper: Encode image to Base64
# -----------------------------
def encode_image(img: np.ndarray) -> str:
"""Convert BGR image to base64 PNG string."""
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
pil_img = Image.fromarray(img_rgb)
buf = io.BytesIO()
pil_img.save(buf, format="PNG")
return base64.b64encode(buf.getvalue()).decode("utf-8")
# -----------------------------
# API Endpoint
# -----------------------------
@app.post("/predict")
async def predict(file: UploadFile = File(...)):
contents = await file.read()
image = np.array(Image.open(io.BytesIO(contents)).convert("RGB"))[:, :, ::-1] # BGR
outputs = predictor(image)
instances = outputs["instances"].to("cpu")
# --- Polygon overlay ---
polygon_overlay = image.copy()
if instances.has("pred_masks"):
masks = instances.pred_masks
combined_mask = torch.any(masks, dim=0).numpy().astype("uint8") * 255
clean_mask = cv2.morphologyEx(combined_mask, cv2.MORPH_OPEN, kernel)
clean_mask = cv2.morphologyEx(clean_mask, cv2.MORPH_CLOSE, kernel)
smooth_mask = cv2.GaussianBlur(clean_mask, (5, 5), 0)
_, smooth_mask = cv2.threshold(smooth_mask, 127, 255, cv2.THRESH_BINARY)
contours, _ = cv2.findContours(smooth_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
largest_contour = max(contours, key=cv2.contourArea)
polygon = cv2.approxPolyDP(largest_contour, epsilon=10, closed=True)
cv2.polylines(polygon_overlay, [polygon], isClosed=True, color=(0, 255, 0), thickness=2)
# --- Detectron2 predicted output ---
v = Visualizer(image[:, :, ::-1], MetadataCatalog.get("toproof_train"), scale=1.2)
out = v.draw_instance_predictions(instances)
predicted_output = out.get_image()[:, :, ::-1] # back to BGR
# Encode both images as Base64
predicted_b64 = encode_image(predicted_output)
polygon_b64 = encode_image(polygon_overlay)
return JSONResponse({
"predicted_output": predicted_b64,
"polygon_overlay": polygon_b64
})