supunnadeera commited on
Commit
432df51
·
1 Parent(s): c206895
Files changed (4) hide show
  1. Dockerfile +28 -0
  2. app.py +67 -0
  3. download_model.py +10 -0
  4. requirements.txt +9 -0
Dockerfile ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Use python 3.10
2
+ FROM python:3.10
3
+
4
+ # Set working directory
5
+ WORKDIR /app
6
+
7
+ # Install system dependencies for OpenCV (required even for headless version)
8
+ RUN apt-get update && apt-get install -y libgl1-mesa-glx libglib2.0-0
9
+
10
+ # Create a folder for models so we have permission to write to it
11
+ RUN mkdir -p /app/models && chmod 777 /app/models
12
+
13
+ # Copy requirements and install
14
+ COPY requirements.txt .
15
+ RUN pip install --no-cache-dir -r requirements.txt
16
+
17
+ # Copy the downloader script
18
+ COPY download_model.py .
19
+
20
+ # --- BUILD STEP: DOWNLOAD MODEL ---
21
+ # This runs during the build process. The large file becomes part of the Docker image.
22
+ RUN python download_model.py
23
+
24
+ # Copy the rest of the application
25
+ COPY . .
26
+
27
+ # Start the server
28
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
app.py ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, UploadFile, File, Response
2
+ from cellpose import models, io
3
+ import numpy as np
4
+ import cv2
5
+ import io as sys_io
6
+ import os
7
+ import tifffile
8
+
9
+ # 1. Point Cellpose to the folder where we downloaded the model in the Dockerfile
10
+ os.environ["CELLPOSE_LOCAL_MODELS_PATH"] = "/app/models"
11
+
12
+ app = FastAPI()
13
+
14
+ # 2. Load the model globally (once) on startup
15
+ # It will find the file in /app/models, so it won't download again.
16
+ print("Loading Cellpose-SAM...")
17
+ model = models.CellposeModel(model_type='cpsam', gpu=False)
18
+ print("Cellpose-SAM Ready!")
19
+
20
+ @app.post("/segment")
21
+ async def segment(
22
+ image: UploadFile = File(...),
23
+ diameter: float = 0.0,
24
+ flow_threshold: float = 0.4,
25
+ cellprob_threshold: float = 0.0,
26
+ channels: str = "0,0" # Expecting "0,0" or "2,3" string
27
+ ):
28
+ try:
29
+ # --- PARSE INPUT ---
30
+ print(f"Received image: {image.filename}")
31
+
32
+ # Parse channels string "2,1" -> [2, 1]
33
+ chan_list = [int(c) for c in channels.split(',')]
34
+
35
+ # Read image bytes
36
+ contents = await image.read()
37
+ nparr = np.frombuffer(contents, np.uint8)
38
+ img = cv2.imdecode(nparr, cv2.IMREAD_UNCHANGED)
39
+
40
+ # Handle different image depths/formats if necessary
41
+ if img is None:
42
+ return Response(content="Could not decode image", status_code=400)
43
+
44
+ # --- INFERENCE ---
45
+ # diameter=0 runs auto-estimation
46
+ masks, flows, styles = model.eval(
47
+ img,
48
+ diameter=diameter if diameter > 0 else None,
49
+ channels=chan_list,
50
+ flow_threshold=flow_threshold,
51
+ cellprob_threshold=cellprob_threshold
52
+ )
53
+
54
+ # --- FORMAT OUTPUT ---
55
+ # We return the MASKS as a TIFF file (16-bit to support >255 cells)
56
+ masks = masks.astype(np.uint16)
57
+
58
+ # Write to memory buffer
59
+ with sys_io.BytesIO() as buf:
60
+ tifffile.imwrite(buf, masks)
61
+ response_bytes = buf.getvalue()
62
+
63
+ return Response(content=response_bytes, media_type="image/tiff")
64
+
65
+ except Exception as e:
66
+ print(f"Error: {str(e)}")
67
+ return Response(content=str(e), status_code=500)
download_model.py ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ from cellpose import models
2
+ import os
3
+
4
+ # Set the cache path to a fixed location inside the container
5
+ os.environ["CELLPOSE_LOCAL_MODELS_PATH"] = "/app/models"
6
+
7
+ print("⏳ Downloading Cellpose-SAM model (1.2GB)... this may take a few minutes...")
8
+ # Initializing the model triggers the download
9
+ models.CellposeModel(model_type='cpsam', gpu=False)
10
+ print("✅ Model downloaded and cached to /app/models!")
requirements.txt ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ fastapi
2
+ uvicorn
3
+ python-multipart
4
+ numpy
5
+ cellpose
6
+ torch
7
+ opencv-python-headless
8
+ imagecodecs
9
+ tifffile