Kalpokoch commited on
Commit
7ebedec
Β·
1 Parent(s): 792af26

perf: major build optimizations - remove matplotlib, fix duplicate endpoint, optimize dependencies

Browse files
Files changed (3) hide show
  1. app.py +8 -12
  2. inference.py +11 -2
  3. requirements.txt +1 -4
app.py CHANGED
@@ -32,18 +32,6 @@ DEVICE = os.getenv("DEVICE", "cpu")
32
  # This prevents timeout on HuggingFace free tier during container startup
33
  _model_loaded = False
34
 
35
- @app.get("/health")
36
- def health():
37
- global _model_loaded
38
- if not _model_loaded:
39
- try:
40
- load_model(WEIGHTS_PATH, DEVICE, meta_path=META_PATH)
41
- _model_loaded = True
42
- print("Model loaded and cached on first request.")
43
- except Exception as e:
44
- return {"status": "error", "device": DEVICE, "model": "DenseNet121-CBAM", "error": str(e)}
45
- return {"status": "ok", "device": DEVICE, "model": "DenseNet121-CBAM"}
46
-
47
 
48
  # ─── Routes ───────────────────────────────────────────────────────────────────
49
  from fastapi.responses import HTMLResponse
@@ -63,6 +51,14 @@ def root():
63
 
64
  @app.get("/health")
65
  def health():
 
 
 
 
 
 
 
 
66
  return {"status": "ok", "device": DEVICE, "model": "DenseNet121-CBAM"}
67
 
68
 
 
32
  # This prevents timeout on HuggingFace free tier during container startup
33
  _model_loaded = False
34
 
 
 
 
 
 
 
 
 
 
 
 
 
35
 
36
  # ─── Routes ───────────────────────────────────────────────────────────────────
37
  from fastapi.responses import HTMLResponse
 
51
 
52
  @app.get("/health")
53
  def health():
54
+ global _model_loaded
55
+ if not _model_loaded:
56
+ try:
57
+ load_model(WEIGHTS_PATH, DEVICE, meta_path=META_PATH)
58
+ _model_loaded = True
59
+ print("Model loaded and cached on first request.")
60
+ except Exception as e:
61
+ return {"status": "error", "device": DEVICE, "model": "DenseNet121-CBAM", "error": str(e)}
62
  return {"status": "ok", "device": DEVICE, "model": "DenseNet121-CBAM"}
63
 
64
 
inference.py CHANGED
@@ -156,6 +156,15 @@ class GradCAMPlusPlus:
156
 
157
  # ─── Preprocessing ─────────────────────────────────────────────────────────────
158
 
 
 
 
 
 
 
 
 
 
159
  def get_transform(image_size=512):
160
  return A.Compose([
161
  A.CLAHE(clip_limit=2.0, tile_grid_size=(8, 8), p=1.0),
@@ -257,8 +266,8 @@ def run_inference(image_path: str, weights_path: str, device: str = "cpu",
257
  orig_rgb = cv2.cvtColor(orig, cv2.COLOR_GRAY2RGB)
258
  cam_resized = cv2.resize(cam_map, (orig_rgb.shape[1], orig_rgb.shape[0]))
259
 
260
- import matplotlib.cm as mpl_cm
261
- heatmap = (mpl_cm.jet(cam_resized)[:, :, :3] * 255).astype(np.uint8)
262
  overlay = cv2.addWeighted(orig_rgb, 0.6, heatmap, 0.4, 0)
263
  result["gradcam_overlay"] = overlay # numpy array, encode downstream
264
  finally:
 
156
 
157
  # ─── Preprocessing ─────────────────────────────────────────────────────────────
158
 
159
+ def apply_jet_colormap(gray_img):
160
+ """Apply jet colormap manually without matplotlib (0=blue, 1=red)."""
161
+ gray_img = np.clip(gray_img, 0, 1)
162
+ r = np.clip(1.5 - np.abs(gray_img * 2 - 3), 0, 1)
163
+ g = np.clip(1.5 - np.abs(gray_img * 2 - 2), 0, 1)
164
+ b = np.clip(1.5 - np.abs(gray_img * 2 - 1), 0, 1)
165
+ return (np.stack([r, g, b], axis=-1) * 255).astype(np.uint8)
166
+
167
+
168
  def get_transform(image_size=512):
169
  return A.Compose([
170
  A.CLAHE(clip_limit=2.0, tile_grid_size=(8, 8), p=1.0),
 
266
  orig_rgb = cv2.cvtColor(orig, cv2.COLOR_GRAY2RGB)
267
  cam_resized = cv2.resize(cam_map, (orig_rgb.shape[1], orig_rgb.shape[0]))
268
 
269
+ # Manual jet colormap (replaces matplotlib.cm.jet) - saves ~100MB in build
270
+ heatmap = apply_jet_colormap(cam_resized)
271
  overlay = cv2.addWeighted(orig_rgb, 0.6, heatmap, 0.4, 0)
272
  result["gradcam_overlay"] = overlay # numpy array, encode downstream
273
  finally:
requirements.txt CHANGED
@@ -7,9 +7,6 @@ fastapi==0.111.0
7
  uvicorn[standard]==0.29.0
8
  python-multipart==0.0.9
9
  opencv-python-headless==4.9.0.80
 
10
  numpy==1.26.4
11
  Pillow==10.3.0
12
-
13
- # Optional: Remove these if not used in inference
14
- # albumentations==1.4.2
15
- # matplotlib==3.8.4
 
7
  uvicorn[standard]==0.29.0
8
  python-multipart==0.0.9
9
  opencv-python-headless==4.9.0.80
10
+ albumentations==1.4.2
11
  numpy==1.26.4
12
  Pillow==10.3.0