LiangLabUMB commited on
Commit
a001e15
·
verified ·
1 Parent(s): b97a37a

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +122 -130
app.py CHANGED
@@ -6,57 +6,77 @@ from cellpose import models
6
  from matplotlib.colors import hsv_to_rgb
7
  import matplotlib.pyplot as plt
8
  import os, io, base64
9
- from PIL import Image
10
  from cellpose.io import imread, imsave
11
- import glob
12
 
13
  from huggingface_hub import hf_hub_download
14
 
15
  img = np.zeros((96, 128), dtype = np.uint8)
16
  fp0 = Image.fromarray(img)
17
- #fp0 = "0.png"
18
- #imsave(fp0, img)
19
 
20
- # data retrieval
21
- def download_weights():
 
 
 
 
 
 
22
  return hf_hub_download(repo_id="mouseland/cellpose-sam", filename="cpsam")
23
-
24
- #os.system("wget -q https://huggingface.co/mouseland/cellpose-sam/resolve/main/cpsam")
25
-
26
- def download_weights_old():
27
- import os, requests
28
-
29
- fname = ['cpsam_v2']
30
-
31
- url = ["https://osf.io/d7c8e/download"]
32
-
33
- for j in range(len(url)):
34
- if not os.path.isfile(fname[j]):
35
- ntries = 0
36
- while ntries<10:
37
- try:
38
- r = requests.get(url[j])
39
- except:
40
- print("!!! Failed to download data !!!")
41
- ntries += 1
42
- print(ntries)
43
-
44
- if r.status_code != requests.codes.ok:
45
- print("!!! Failed to download data !!!")
46
- else:
47
- with open(fname[j], "wb") as fid:
48
- fid.write(r.content)
 
 
 
 
 
49
 
50
  try:
51
- fpath = download_weights()
52
- model = models.CellposeModel(gpu=True, pretrained_model = fpath)
53
  except Exception as e:
54
- print(f"Error loading model: {e}")
 
 
 
55
  exit(1)
56
 
 
 
 
57
 
 
 
 
 
58
 
59
-
 
 
60
  def plot_flows(y):
61
  Y = (np.clip(normalize99(y[0][0]),0,1) - 0.5) * 2
62
  X = (np.clip(normalize99(y[1][0]),0,1) - 0.5) * 2
@@ -78,7 +98,7 @@ def plot_outlines(img, masks):
78
  peri = cv2.arcLength(contours[c], True)
79
  approx = cv2.approxPolyDP(contours[c], 0.001, True)[:,0,:]
80
  outpix.append(approx)
81
-
82
  figsize = (6,6)
83
  if img.shape[0]>img.shape[1]:
84
  figsize = (6*img.shape[1]/img.shape[0], 6)
@@ -93,17 +113,6 @@ def plot_outlines(img, masks):
93
  for o in outpix:
94
  ax.plot(o[:,0], img.shape[0]-o[:,1], color=[1,0,0], lw=1)
95
  ax.axis('off')
96
-
97
- #bytes_image = io.BytesIO()
98
- #plt.savefig(bytes_image, format='png', facecolor=fig.get_facecolor(), edgecolor='none')
99
- #bytes_image.seek(0)
100
- #img_arr = np.frombuffer(bytes_image.getvalue(), dtype=np.uint8)
101
- #bytes_image.close()
102
- #img = cv2.imdecode(img_arr, 1)
103
- #img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
104
- #del bytes_image
105
- #fig.clf()
106
- #plt.close(fig)
107
 
108
  buf = io.BytesIO()
109
  fig.savefig(buf, bbox_inches='tight')
@@ -119,9 +128,8 @@ def plot_overlay(img, masks):
119
  img_gray = img.astype(np.float32).mean(axis=-1)
120
  else:
121
  img_gray = img.astype(np.float32)
122
-
123
  img = normalize99(img_gray)
124
- #img = np.clip(img, 0, 1)
125
  HSV = np.zeros((img.shape[0], img.shape[1], 3), np.float32)
126
  HSV[:,:,2] = np.clip(img*1.5, 0, 1.0)
127
  for n in range(int(masks.max())):
@@ -150,98 +158,88 @@ def image_resize(img, resize=400):
150
  img = img.astype(np.uint8)
151
  return img
152
 
153
-
 
 
154
  @spaces.GPU(duration=10)
155
- def run_model_gpu(img, max_iter, flow_threshold, cellprob_threshold):
 
156
  masks, flows, _ = model.eval(img, niter = max_iter, flow_threshold = flow_threshold, cellprob_threshold = cellprob_threshold)
157
  return masks, flows
158
 
159
  @spaces.GPU(duration=60)
160
- def run_model_gpu60(img, max_iter, flow_threshold, cellprob_threshold):
 
161
  masks, flows, _ = model.eval(img, niter = max_iter, flow_threshold = flow_threshold, cellprob_threshold = cellprob_threshold)
162
  return masks, flows
163
 
164
  @spaces.GPU(duration=240)
165
- def run_model_gpu240(img, max_iter, flow_threshold, cellprob_threshold):
 
166
  masks, flows, _ = model.eval(img, niter = max_iter, flow_threshold = flow_threshold, cellprob_threshold = cellprob_threshold)
167
  return masks, flows
168
 
169
  import datetime
170
  from zipfile import ZipFile
171
- def cellpose_segment(filepath, resize = 1000,max_iter = 250, flow_threshold= 0.4, cellprob_threshold = 0):
 
 
 
172
 
173
  zip_path = os.path.splitext(filepath[-1])[0]+"_masks.zip"
174
- #zip_path = 'masks.zip'
175
  with ZipFile(zip_path, 'w') as myzip:
176
  for j in range((len(filepath))):
177
  now = datetime.datetime.now()
178
- formatted_now = now.strftime("%Y-%m-%d %H:%M:%S")
179
-
180
  img_input = imread(filepath[j])
181
- #img_input = np.array(img_pil)
182
  img = image_resize(img_input, resize = resize)
183
-
184
  maxsize = np.max(img.shape)
185
  if maxsize<=1000:
186
- masks, flows = run_model_gpu(img, max_iter, flow_threshold, cellprob_threshold)
187
  elif maxsize < 5000:
188
- masks, flows = run_model_gpu60(img, max_iter, flow_threshold, cellprob_threshold)
189
  elif maxsize < 20000:
190
- masks, flows = run_model_gpu240(img, max_iter, flow_threshold, cellprob_threshold)
191
  else:
192
  raise ValueError("Image size must be less than 20,000")
193
 
194
- print(formatted_now, j, masks.max(), os.path.split(filepath[j])[-1])
195
-
196
  target_size = (img_input.shape[1], img_input.shape[0])
197
  if (target_size[0]!=img.shape[1] or target_size[1]!=img.shape[0]):
198
- # scale it back to keep the orignal size
199
  masks_rsz = cv2.resize(masks.astype('uint16'), target_size, interpolation=cv2.INTER_NEAREST).astype('uint16')
200
  else:
201
  masks_rsz = masks.copy()
202
-
203
  fname_masks = os.path.splitext(filepath[j])[0]+"_masks.tif"
204
  imsave(fname_masks, masks_rsz)
205
-
206
  myzip.write(fname_masks, arcname = os.path.split(fname_masks)[-1])
207
-
208
-
209
- #masks, flows, _ = model.eval(img, channels=[0,0])
210
  flows = flows[0]
211
- # masks = np.zeros(img.shape[:2])
212
- # flows = np.zeros_like(img)
213
 
214
  outpix = plot_outlines(img, masks)
215
- #overlay = plot_overlay(img, masks)
216
-
217
-
218
-
219
- #crand = .2 + .8 * np.random.rand(np.max(masks.flatten()).astype('int')+1,).astype('float32')
220
- #crand[0] = 0
221
-
222
- #overlay = Image.fromarray(overlay)
223
  flows = Image.fromarray(flows)
224
 
225
  Ly, Lx = img.shape[:2]
226
  outpix = outpix.resize((Lx, Ly), resample = Image.BICUBIC)
227
- #overlay = overlay.resize((Lx, Ly), resample = Image.BICUBIC)
228
  flows = flows.resize((Lx, Ly), resample = Image.BICUBIC)
229
 
230
  fname_out = os.path.splitext(filepath[-1])[0]+"_outlines.png"
231
- outpix.save(fname_out) #"outlines.png")
232
-
233
- #fname_flows = os.path.splitext(filepath[-1])[0]+"_flows.png"
234
- #flows.save(fname_flows) #"outlines.png")
235
 
236
  if len(filepath)>1:
237
  b1 = gr.DownloadButton(visible=True, value = zip_path)
238
  else:
239
  b1 = gr.DownloadButton(visible=True, value = fname_masks)
240
- b2 = gr.DownloadButton(visible=True, value = fname_out) #"outlines.png")
241
-
242
  return outpix, flows, b1, b2
243
 
244
- def download_function():
245
  b1 = gr.DownloadButton("Download masks as TIFF", visible=False)
246
  b2 = gr.DownloadButton("Download outline image as PNG", visible=False)
247
  return b1, b2
@@ -263,8 +261,7 @@ def tif_view(filepath):
263
  imgi = np.zeros((Ly, Lx, 3))
264
  nn = np.minimum(3, img.shape[-1])
265
  imgi[:,:,:nn] = img[:,:,:nn]
266
-
267
- #filepath = fpath+'.png'
268
  imsave(filepath, imgi)
269
  return filepath
270
 
@@ -276,10 +273,9 @@ def norm_path(filepath):
276
  filepath = fpath +'.png'
277
  pil_image = Image.fromarray((255. * img).astype(np.uint8))
278
  pil_image.save(filepath)
279
- #imsave(filepath, pil_image)
280
- return filepath
281
-
282
- def update_image(filepath):
283
  for f in filepath:
284
  f = tif_view(f)
285
  filepath_show = norm_path(filepath[-1])
@@ -289,65 +285,61 @@ def update_button(filepath):
289
  filepath = tif_view(filepath)
290
  filepath_show = norm_path(filepath)
291
  return filepath_show, [filepath], fp0, fp0
292
-
293
- with gr.Blocks(title = "Hello",
 
 
 
294
  css=".gradio-container {background:purple;}") as demo:
295
 
296
- #filepath = ""
297
  with gr.Row():
298
  with gr.Column(scale=2):
299
- gr.HTML("""<div style="font-family:'Times New Roman', 'Serif'; font-size:20pt; font-weight:bold; text-align:center; color:white;">CellposeSAM for cellular
300
- segmentation <a style="color:#cfe7fe; font-size:14pt;" href="https://www.biorxiv.org/content/10.1101/2025.04.28.651001v1" target="_blank">[paper]</a>
301
  <a style="color:white; font-size:14pt;" href="https://github.com/MouseLand/cellpose" target="_blank">[github]</a>
302
- <a style="color:white; font-size:14pt;" href="https://www.youtube.com/watch?v=KIdYXgQemcI" target="_blank">[talk]</a>
303
  </div>""")
304
- gr.HTML("""<h4 style="color:white;">You may need to login/refresh for 5 minutes of free GPU compute per day (enough to process hundreds of images). The model is now 'cpsam_v2' (updated June 2026). </h4>""")
305
-
306
  input_image = gr.Image(label = "Input", type = "filepath")
307
 
308
  with gr.Row():
309
- with gr.Column(scale=1):
 
 
310
  with gr.Row():
311
  resize = gr.Number(label = 'max resize', value = 1000)
312
  max_iter = gr.Number(label = 'max iterations', value = 250)
313
  flow_threshold = gr.Number(label = 'flow threshold', value = 0.4)
314
  cellprob_threshold = gr.Number(label = 'cellprob threshold', value = 0)
315
-
316
- up_btn = gr.UploadButton("Multi-file upload (png, jpg, tif etc)", visible=True, file_count = "multiple")
317
-
318
- #gr.HTML("""<h4 style="color:white;"> Note2: Only the first image of a tif will display the segmentations, but you can download segmentations for all planes. </h4>""")
319
-
320
  with gr.Column(scale=1):
321
  send_btn = gr.Button("Run CellposeSAM")
322
- down_btn = gr.DownloadButton("Download masks (TIF)", visible=False)
323
- down_btn2 = gr.DownloadButton("Download outlines (PNG)", visible=False)
324
-
325
- with gr.Column(scale=2):
326
- outlines = gr.Image(label = "Outlines", type = "pil", format = 'png', value = fp0) #, width = "50vw", height = "20vw")
327
- #img_overlay = gr.Image(label = "Overlay", type = "pil", format = 'png') #, width = "50vw", height = "20vw")
328
- flows = gr.Image(label = "Cellpose flows", type = "pil", format = 'png', value = fp0) #, width = "50vw", height = "20vw")
329
-
330
-
331
-
332
  sample_list = glob.glob("samples/*.png")
333
- #sample_list = []
334
- #for j in range(23):
335
- # sample_list.append("samples/img%0.2d.png"%j)
336
-
337
  gr.Examples(sample_list, fn = update_button, inputs=input_image, outputs = [input_image, up_btn, outlines, flows], examples_per_page=50, label = "Click on an example to try it")
338
  input_image.upload(update_button, input_image, [input_image, up_btn, outlines, flows])
339
  up_btn.upload(update_image, up_btn, [input_image, up_btn, outlines, flows])
340
-
341
- send_btn.click(cellpose_segment, [up_btn, resize, max_iter, flow_threshold, cellprob_threshold], [outlines, flows, down_btn, down_btn2])
342
 
343
- #down_btn.click(download_function, None, [down_btn, down_btn2])
344
-
345
- gr.HTML("""<h4 style="color:white;"> Notes:<br>
 
 
346
  <li>you can load and process 2D, multi-channel tifs.
347
  <li>the smallest dimension of a tif --> channels
348
  <li>you can upload multiple files and download a zip of the segmentations
349
  <li>install Cellpose-SAM locally for full functionality.
350
  </h4>""")
351
-
352
-
353
  demo.launch()
 
6
  from matplotlib.colors import hsv_to_rgb
7
  import matplotlib.pyplot as plt
8
  import os, io, base64
9
+ from PIL import Image
10
  from cellpose.io import imread, imsave
11
+ import glob
12
 
13
  from huggingface_hub import hf_hub_download
14
 
15
  img = np.zeros((96, 128), dtype = np.uint8)
16
  fp0 = Image.fromarray(img)
 
 
17
 
18
+ # ---------------------------------------------------------------------------
19
+ # Model weights
20
+ # ---------------------------------------------------------------------------
21
+ MODEL_V1 = "cpsam (v1)"
22
+ MODEL_V2 = "cpsam_v2"
23
+ DEFAULT_MODEL = MODEL_V2
24
+
25
+ def download_weights_v1():
26
  return hf_hub_download(repo_id="mouseland/cellpose-sam", filename="cpsam")
27
+
28
+ def download_weights_v2():
29
+ # try Hugging Face first, then fall back to OSF
30
+ try:
31
+ return hf_hub_download(repo_id="mouseland/cellpose-sam", filename="cpsam_v2")
32
+ except Exception as e:
33
+ print(f"cpsam_v2 not found on Hugging Face ({e}), trying OSF")
34
+
35
+ import requests
36
+ fname = "cpsam_v2"
37
+ url = "https://osf.io/d7c8e/download"
38
+ if os.path.isfile(fname):
39
+ return fname
40
+ for ntries in range(10):
41
+ try:
42
+ r = requests.get(url, timeout=300)
43
+ if r.status_code == requests.codes.ok:
44
+ with open(fname, "wb") as fid:
45
+ fid.write(r.content)
46
+ return fname
47
+ print(f"!!! Failed to download cpsam_v2 (status {r.status_code}), try {ntries+1} !!!")
48
+ except Exception as e:
49
+ print(f"!!! Failed to download cpsam_v2 ({e}), try {ntries+1} !!!")
50
+ raise RuntimeError("Could not download cpsam_v2 weights")
51
+
52
+ MODELS = {}
53
+
54
+ try:
55
+ MODELS[MODEL_V1] = models.CellposeModel(gpu=True, pretrained_model=download_weights_v1())
56
+ except Exception as e:
57
+ print(f"Error loading {MODEL_V1}: {e}")
58
 
59
  try:
60
+ MODELS[MODEL_V2] = models.CellposeModel(gpu=True, pretrained_model=download_weights_v2())
 
61
  except Exception as e:
62
+ print(f"Error loading {MODEL_V2}: {e}")
63
+
64
+ if len(MODELS) == 0:
65
+ print("No models could be loaded, exiting")
66
  exit(1)
67
 
68
+ MODEL_CHOICES = list(MODELS.keys())
69
+ if DEFAULT_MODEL not in MODELS:
70
+ DEFAULT_MODEL = MODEL_CHOICES[0]
71
 
72
+ def get_model(model_name):
73
+ if model_name not in MODELS:
74
+ raise gr.Error(f"Model '{model_name}' is not available. Choose one of: {', '.join(MODEL_CHOICES)}")
75
+ return MODELS[model_name]
76
 
77
+ # ---------------------------------------------------------------------------
78
+ # Plotting helpers
79
+ # ---------------------------------------------------------------------------
80
  def plot_flows(y):
81
  Y = (np.clip(normalize99(y[0][0]),0,1) - 0.5) * 2
82
  X = (np.clip(normalize99(y[1][0]),0,1) - 0.5) * 2
 
98
  peri = cv2.arcLength(contours[c], True)
99
  approx = cv2.approxPolyDP(contours[c], 0.001, True)[:,0,:]
100
  outpix.append(approx)
101
+
102
  figsize = (6,6)
103
  if img.shape[0]>img.shape[1]:
104
  figsize = (6*img.shape[1]/img.shape[0], 6)
 
113
  for o in outpix:
114
  ax.plot(o[:,0], img.shape[0]-o[:,1], color=[1,0,0], lw=1)
115
  ax.axis('off')
 
 
 
 
 
 
 
 
 
 
 
116
 
117
  buf = io.BytesIO()
118
  fig.savefig(buf, bbox_inches='tight')
 
128
  img_gray = img.astype(np.float32).mean(axis=-1)
129
  else:
130
  img_gray = img.astype(np.float32)
131
+
132
  img = normalize99(img_gray)
 
133
  HSV = np.zeros((img.shape[0], img.shape[1], 3), np.float32)
134
  HSV[:,:,2] = np.clip(img*1.5, 0, 1.0)
135
  for n in range(int(masks.max())):
 
158
  img = img.astype(np.uint8)
159
  return img
160
 
161
+ # ---------------------------------------------------------------------------
162
+ # GPU inference
163
+ # ---------------------------------------------------------------------------
164
  @spaces.GPU(duration=10)
165
+ def run_model_gpu(img, max_iter, flow_threshold, cellprob_threshold, model_name):
166
+ model = get_model(model_name)
167
  masks, flows, _ = model.eval(img, niter = max_iter, flow_threshold = flow_threshold, cellprob_threshold = cellprob_threshold)
168
  return masks, flows
169
 
170
  @spaces.GPU(duration=60)
171
+ def run_model_gpu60(img, max_iter, flow_threshold, cellprob_threshold, model_name):
172
+ model = get_model(model_name)
173
  masks, flows, _ = model.eval(img, niter = max_iter, flow_threshold = flow_threshold, cellprob_threshold = cellprob_threshold)
174
  return masks, flows
175
 
176
  @spaces.GPU(duration=240)
177
+ def run_model_gpu240(img, max_iter, flow_threshold, cellprob_threshold, model_name):
178
+ model = get_model(model_name)
179
  masks, flows, _ = model.eval(img, niter = max_iter, flow_threshold = flow_threshold, cellprob_threshold = cellprob_threshold)
180
  return masks, flows
181
 
182
  import datetime
183
  from zipfile import ZipFile
184
+ def cellpose_segment(filepath, resize = 1000, max_iter = 250, flow_threshold= 0.4, cellprob_threshold = 0, model_name = DEFAULT_MODEL):
185
+
186
+ if not filepath:
187
+ raise gr.Error("Please upload an image first.")
188
 
189
  zip_path = os.path.splitext(filepath[-1])[0]+"_masks.zip"
 
190
  with ZipFile(zip_path, 'w') as myzip:
191
  for j in range((len(filepath))):
192
  now = datetime.datetime.now()
193
+ formatted_now = now.strftime("%Y-%m-%d %H:%M:%S")
194
+
195
  img_input = imread(filepath[j])
 
196
  img = image_resize(img_input, resize = resize)
197
+
198
  maxsize = np.max(img.shape)
199
  if maxsize<=1000:
200
+ masks, flows = run_model_gpu(img, max_iter, flow_threshold, cellprob_threshold, model_name)
201
  elif maxsize < 5000:
202
+ masks, flows = run_model_gpu60(img, max_iter, flow_threshold, cellprob_threshold, model_name)
203
  elif maxsize < 20000:
204
+ masks, flows = run_model_gpu240(img, max_iter, flow_threshold, cellprob_threshold, model_name)
205
  else:
206
  raise ValueError("Image size must be less than 20,000")
207
 
208
+ print(formatted_now, model_name, j, masks.max(), os.path.split(filepath[j])[-1])
209
+
210
  target_size = (img_input.shape[1], img_input.shape[0])
211
  if (target_size[0]!=img.shape[1] or target_size[1]!=img.shape[0]):
212
+ # scale it back to keep the original size
213
  masks_rsz = cv2.resize(masks.astype('uint16'), target_size, interpolation=cv2.INTER_NEAREST).astype('uint16')
214
  else:
215
  masks_rsz = masks.copy()
216
+
217
  fname_masks = os.path.splitext(filepath[j])[0]+"_masks.tif"
218
  imsave(fname_masks, masks_rsz)
219
+
220
  myzip.write(fname_masks, arcname = os.path.split(fname_masks)[-1])
221
+
 
 
222
  flows = flows[0]
 
 
223
 
224
  outpix = plot_outlines(img, masks)
 
 
 
 
 
 
 
 
225
  flows = Image.fromarray(flows)
226
 
227
  Ly, Lx = img.shape[:2]
228
  outpix = outpix.resize((Lx, Ly), resample = Image.BICUBIC)
 
229
  flows = flows.resize((Lx, Ly), resample = Image.BICUBIC)
230
 
231
  fname_out = os.path.splitext(filepath[-1])[0]+"_outlines.png"
232
+ outpix.save(fname_out)
 
 
 
233
 
234
  if len(filepath)>1:
235
  b1 = gr.DownloadButton(visible=True, value = zip_path)
236
  else:
237
  b1 = gr.DownloadButton(visible=True, value = fname_masks)
238
+ b2 = gr.DownloadButton(visible=True, value = fname_out)
239
+
240
  return outpix, flows, b1, b2
241
 
242
+ def download_function():
243
  b1 = gr.DownloadButton("Download masks as TIFF", visible=False)
244
  b2 = gr.DownloadButton("Download outline image as PNG", visible=False)
245
  return b1, b2
 
261
  imgi = np.zeros((Ly, Lx, 3))
262
  nn = np.minimum(3, img.shape[-1])
263
  imgi[:,:,:nn] = img[:,:,:nn]
264
+
 
265
  imsave(filepath, imgi)
266
  return filepath
267
 
 
273
  filepath = fpath +'.png'
274
  pil_image = Image.fromarray((255. * img).astype(np.uint8))
275
  pil_image.save(filepath)
276
+ return filepath
277
+
278
+ def update_image(filepath):
 
279
  for f in filepath:
280
  f = tif_view(f)
281
  filepath_show = norm_path(filepath[-1])
 
285
  filepath = tif_view(filepath)
286
  filepath_show = norm_path(filepath)
287
  return filepath_show, [filepath], fp0, fp0
288
+
289
+ # ---------------------------------------------------------------------------
290
+ # UI
291
+ # ---------------------------------------------------------------------------
292
+ with gr.Blocks(title = "Hello",
293
  css=".gradio-container {background:purple;}") as demo:
294
 
 
295
  with gr.Row():
296
  with gr.Column(scale=2):
297
+ gr.HTML("""<div style="font-family:'Times New Roman', 'Serif'; font-size:20pt; font-weight:bold; text-align:center; color:white;">CellposeSAM for cellular
298
+ segmentation <a style="color:#cfe7fe; font-size:14pt;" href="https://www.biorxiv.org/content/10.1101/2025.04.28.651001v1" target="_blank">[paper]</a>
299
  <a style="color:white; font-size:14pt;" href="https://github.com/MouseLand/cellpose" target="_blank">[github]</a>
300
+ <a style="color:white; font-size:14pt;" href="https://www.youtube.com/watch?v=KIdYXgQemcI" target="_blank">[talk]</a>
301
  </div>""")
302
+ gr.HTML("""<h4 style="color:white;">You may need to login/refresh for 5 minutes of free GPU compute per day (enough to process hundreds of images). Choose between the original 'cpsam' (v1) and 'cpsam_v2' (updated June 2026) in the model dropdown. </h4>""")
303
+
304
  input_image = gr.Image(label = "Input", type = "filepath")
305
 
306
  with gr.Row():
307
+ with gr.Column(scale=1):
308
+ model_choice = gr.Dropdown(choices = MODEL_CHOICES, value = DEFAULT_MODEL,
309
+ label = "Model", interactive = True)
310
  with gr.Row():
311
  resize = gr.Number(label = 'max resize', value = 1000)
312
  max_iter = gr.Number(label = 'max iterations', value = 250)
313
  flow_threshold = gr.Number(label = 'flow threshold', value = 0.4)
314
  cellprob_threshold = gr.Number(label = 'cellprob threshold', value = 0)
315
+
316
+ up_btn = gr.UploadButton("Multi-file upload (png, jpg, tif etc)", visible=True, file_count = "multiple")
317
+
 
 
318
  with gr.Column(scale=1):
319
  send_btn = gr.Button("Run CellposeSAM")
320
+ down_btn = gr.DownloadButton("Download masks (TIF)", visible=False)
321
+ down_btn2 = gr.DownloadButton("Download outlines (PNG)", visible=False)
322
+
323
+ with gr.Column(scale=2):
324
+ outlines = gr.Image(label = "Outlines", type = "pil", format = 'png', value = fp0)
325
+ flows = gr.Image(label = "Cellpose flows", type = "pil", format = 'png', value = fp0)
326
+
 
 
 
327
  sample_list = glob.glob("samples/*.png")
328
+
 
 
 
329
  gr.Examples(sample_list, fn = update_button, inputs=input_image, outputs = [input_image, up_btn, outlines, flows], examples_per_page=50, label = "Click on an example to try it")
330
  input_image.upload(update_button, input_image, [input_image, up_btn, outlines, flows])
331
  up_btn.upload(update_image, up_btn, [input_image, up_btn, outlines, flows])
 
 
332
 
333
+ send_btn.click(cellpose_segment,
334
+ [up_btn, resize, max_iter, flow_threshold, cellprob_threshold, model_choice],
335
+ [outlines, flows, down_btn, down_btn2])
336
+
337
+ gr.HTML("""<h4 style="color:white;"> Notes:<br>
338
  <li>you can load and process 2D, multi-channel tifs.
339
  <li>the smallest dimension of a tif --> channels
340
  <li>you can upload multiple files and download a zip of the segmentations
341
  <li>install Cellpose-SAM locally for full functionality.
342
  </h4>""")
343
+
344
+
345
  demo.launch()