Noursine commited on
Commit
44faaa6
·
verified ·
1 Parent(s): 7575573

Create app3.py

Browse files
Files changed (1) hide show
  1. app3.py +90 -0
app3.py ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import io
3
+ import base64
4
+ import cv2
5
+ import torch
6
+ import numpy as np
7
+ from PIL import Image
8
+ from fastapi import FastAPI, UploadFile, File, Form
9
+ from fastapi.responses import JSONResponse
10
+ from detectron2.config import get_cfg
11
+ from detectron2.engine import DefaultPredictor
12
+ from detectron2 import model_zoo
13
+ from detectron2.utils.visualizer import Visualizer
14
+ from detectron2.data import MetadataCatalog
15
+
16
+ app = FastAPI(title="Roof Segmentation API")
17
+
18
+ @app.get("/")
19
+ def home():
20
+ return {"status": "running"}
21
+
22
+ MODEL_PATH = "model_final (4).pth"
23
+
24
+ # ----------------------------- Detectron2 Config -----------------------------
25
+ cfg = get_cfg()
26
+ cfg.merge_from_file(model_zoo.get_config_file("COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml"))
27
+ cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.5
28
+ cfg.MODEL.ROI_HEADS.NUM_CLASSES = 1
29
+ cfg.MODEL.WEIGHTS = MODEL_PATH
30
+ cfg.MODEL.DEVICE = "cpu" # or "cuda" if GPU available
31
+
32
+ predictor = DefaultPredictor(cfg)
33
+ kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
34
+
35
+ # ----------------------------- Helper -----------------------------
36
+ def encode_image(img: np.ndarray) -> str:
37
+ """Convert BGR image to base64 PNG string."""
38
+ img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
39
+ pil_img = Image.fromarray(img_rgb)
40
+ buf = io.BytesIO()
41
+ pil_img.save(buf, format="PNG")
42
+ return base64.b64encode(buf.getvalue()).decode("utf-8")
43
+
44
+ # ----------------------------- API Endpoint -----------------------------
45
+ @app.post("/predict")
46
+ async def predict(
47
+ file: UploadFile = File(...),
48
+ output_type: str = Form("both") # 'predicted_output', 'polygon_overlay', or 'both'
49
+ ):
50
+ contents = await file.read()
51
+ image = np.array(Image.open(io.BytesIO(contents)).convert("RGB"))[:, :, ::-1] # BGR
52
+
53
+ outputs = predictor(image)
54
+ instances = outputs["instances"].to("cpu")
55
+
56
+ # --- Polygon overlay ---
57
+ polygon_overlay = image.copy()
58
+ if instances.has("pred_masks"):
59
+ masks = instances.pred_masks
60
+ combined_mask = torch.any(masks, dim=0).numpy().astype("uint8") * 255
61
+ clean_mask = cv2.morphologyEx(combined_mask, cv2.MORPH_OPEN, kernel)
62
+ clean_mask = cv2.morphologyEx(clean_mask, cv2.MORPH_CLOSE, kernel)
63
+ smooth_mask = cv2.GaussianBlur(clean_mask, (5, 5), 0)
64
+ _, smooth_mask = cv2.threshold(smooth_mask, 127, 255, cv2.THRESH_BINARY)
65
+ contours, _ = cv2.findContours(smooth_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
66
+ if contours:
67
+ largest_contour = max(contours, key=cv2.contourArea)
68
+ polygon = cv2.approxPolyDP(largest_contour, epsilon=10, closed=True)
69
+ cv2.polylines(polygon_overlay, [polygon], isClosed=True, color=(0, 255, 0), thickness=2)
70
+
71
+ # --- Detectron2 predicted output ---
72
+ v = Visualizer(image[:, :, ::-1], MetadataCatalog.get("toproof_train"), scale=1.2)
73
+ out = v.draw_instance_predictions(instances)
74
+ predicted_output = out.get_image()[:, :, ::-1] # BGR
75
+
76
+ # Encode images
77
+ predicted_b64 = encode_image(predicted_output)
78
+ polygon_b64 = encode_image(polygon_overlay)
79
+
80
+ # Build response based on output_type
81
+ result = {}
82
+ if output_type == "predicted_output":
83
+ result["predicted_output"] = predicted_b64
84
+ elif output_type == "polygon_overlay":
85
+ result["polygon_overlay"] = polygon_b64
86
+ else: # both
87
+ result["predicted_output"] = predicted_b64
88
+ result["polygon_overlay"] = polygon_b64
89
+
90
+ return JSONResponse(result)