From 9d2ee82ded6c190a07a418cde1e7cbfc0d9ce944 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Oct 2024 18:21:44 -0400 Subject: [PATCH 01/10] adding option for legacy models in API (#1025) --- cellpose/models.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cellpose/models.py b/cellpose/models.py index 3ba71bcd..75b70700 100644 --- a/cellpose/models.py +++ b/cellpose/models.py @@ -29,7 +29,8 @@ "cyto3", "nuclei", "cyto2_cp3", "tissuenet_cp3", "livecell_cp3", "yeast_PhC_cp3", "yeast_BF_cp3", "bact_phase_cp3", "bact_fluor_cp3", "deepbacs_cp3", "cyto2", "cyto", "CPx", "transformer_cp3", "neurips_cellpose_default", "neurips_cellpose_transformer", - "neurips_grayscale_cyto2" + "neurips_grayscale_cyto2", + "CP", "CPx", "TN1", "TN2", "TN3", "LC1", "LC2", "LC3", "LC4" ] MODEL_LIST_PATH = os.fspath(MODEL_DIR.joinpath("gui_models.txt")) From 384157563233f2f3bd1b90ca3d8913dc630e9c52 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Oct 2024 18:28:16 -0400 Subject: [PATCH 02/10] bug in demo_images url (#1021) --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4bd2be3a..b7c6c14a 100644 --- a/README.md +++ b/README.md @@ -185,7 +185,7 @@ python -m cellpose The first time cellpose runs it downloads the latest available trained model weights from the website. -You can now **drag and drop** any images (*.tif, *.png, *.jpg, *.gif) into the GUI and run Cellpose, and/or manually segment them. When the GUI is processing, you will see the progress bar fill up and during this time you cannot click on anything in the GUI. For more information about what the GUI is doing you can look at the terminal/prompt you opened the GUI with. For example data, see [website](http://www.cellpose.org) or this [zip file](https://www.cellpose.org/static/images/demo_images.zip). For best accuracy and runtime performance, resize images so cells are less than 100 pixels across. +You can now **drag and drop** any images (*.tif, *.png, *.jpg, *.gif) into the GUI and run Cellpose, and/or manually segment them. When the GUI is processing, you will see the progress bar fill up and during this time you cannot click on anything in the GUI. For more information about what the GUI is doing you can look at the terminal/prompt you opened the GUI with. For example data, see [website](https://www.cellpose.org) or this [zip file](https://www.cellpose.org/static/images/demo_images.zip). For best accuracy and runtime performance, resize images so cells are less than 100 pixels across. For 3D data, with multi-Z, please use the 3D version of the GUI with: ~~~~ @@ -195,7 +195,7 @@ python -m cellpose --Zstack ## Step-by-step demo -1. Download this [folder](http://cellpose.org/static/images/demo_images.zip) of images and unzip it. These are a subset of the test images from the paper. +1. Download this [zip file](https://www.cellpose.org/static/images/demo_images.zip) of images and unzip it. These are a subset of the test images from the paper. 2. Start the GUI with `python -m cellpose`. 3. Drag an image from the folder into the GUI. 4. Set the model (in demo all are `cyto`) and the channel you want to segment (in demo all are `green`). Optionally set the second channel if you are segmenting `cyto` and have an available nucleus channel. From 0339f6e822ef197821542e4a671b812760348e0e Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Oct 2024 18:33:53 -0400 Subject: [PATCH 03/10] adding info about image lists (#1028) --- docs/inputs.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/inputs.rst b/docs/inputs.rst index 9ce3b1e3..2b2b9093 100644 --- a/docs/inputs.rst +++ b/docs/inputs.rst @@ -9,6 +9,11 @@ each channel so that 0 = 1st percentile of image values and 1 = 99th percentile. If you want to run multiple images in a directory, use the command line or a jupyter notebook to run cellpose. +If you have multiple images of the same size, it can be faster to input them into the +Cellpose `model.eval` function as an array rather than a list, and running with a large +batch size. This is because the model can process tiles from multiple images in single batches +on the GPU if the images are fed in as an array. + 3D segmentation ~~~~~~~~~~~~~~~~~~~~~~~~~~ From 166abf117da7bd395e1539822bd79f2c13985336 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Oct 2024 18:41:19 -0400 Subject: [PATCH 04/10] no longer remapping when reloading masks (#1029) --- cellpose/gui/io.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cellpose/gui/io.py b/cellpose/gui/io.py index 2faadd6e..47576551 100644 --- a/cellpose/gui/io.py +++ b/cellpose/gui/io.py @@ -478,7 +478,8 @@ def _masks_to_gui(parent, masks, outlines=None, colors=None): # get unique values shape = masks.shape masks = masks.flatten() - fastremap.renumber(masks, in_place=True) + if len(fastremap.unique(masks)) != masks.max() + 1: + fastremap.renumber(masks, in_place=True) masks = masks.reshape(shape) masks = masks.astype(np.uint16) if masks.max() < 2**16 - 1 else masks.astype( np.uint32) From 6fb288f98f351b84c214c79ad8c0fc0b64d86bf8 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Oct 2024 18:48:26 -0400 Subject: [PATCH 05/10] z-axis=0 in GUI (#1020) --- cellpose/gui/gui.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cellpose/gui/gui.py b/cellpose/gui/gui.py index ec1c6c86..492818d1 100644 --- a/cellpose/gui/gui.py +++ b/cellpose/gui/gui.py @@ -2431,7 +2431,7 @@ def compute_segmentation(self, custom=False, model_name=None, load_model=True): cellprob_threshold=cellprob_threshold, flow_threshold=flow_threshold, do_3D=do_3D, niter=niter, normalize=normalize_params, stitch_threshold=stitch_threshold, - progress=self.progress)[:2] + progress=self.progress, z_axis=0 if self.NZ > 1 else None)[:2] except Exception as e: print("NET ERROR: %s" % e) self.progress.setValue(0) From b74038d9a617598bc41893ee56481047f668e845 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Oct 2024 18:59:30 -0400 Subject: [PATCH 06/10] bug with size model location (#1015) --- cellpose/models.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/cellpose/models.py b/cellpose/models.py index 75b70700..11d29a98 100644 --- a/cellpose/models.py +++ b/cellpose/models.py @@ -58,16 +58,20 @@ def model_path(model_type, model_index=0): def size_model_path(model_type): - if os.path.exists(model_type): - return model_type + "_size.npy" - else: - torch_str = "torch" - if model_type == "cyto" or model_type == "nuclei" or model_type == "cyto2": - basename = "size_%s%s_0.npy" % (model_type, torch_str) - else: + torch_str = "torch" + if (model_type == "cyto" or model_type == "nuclei" or + model_type == "cyto2" or model_type == "cyto3"): + if model_type == "cyto3": basename = "size_%s.npy" % model_type + else: + basename = "size_%s%s_0.npy" % (model_type, torch_str) return cache_model_path(basename) - + else: + if os.path.exists(model_type) and os.path.exists(model_type + "_size.npy"): + return model_type + "_size.npy" + else: + raise FileNotFoundError(f"size model not found ({model_type + '_size.npy'})") + def cache_model_path(basename): MODEL_DIR.mkdir(parents=True, exist_ok=True) From a2b472985b7991edc60a23877570369de6ecdc17 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 26 Oct 2024 10:50:59 -0400 Subject: [PATCH 07/10] bug with drawing masks (#961) --- cellpose/gui/gui.py | 2 +- cellpose/gui/io.py | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/cellpose/gui/gui.py b/cellpose/gui/gui.py index 492818d1..36bc07b5 100644 --- a/cellpose/gui/gui.py +++ b/cellpose/gui/gui.py @@ -1704,7 +1704,7 @@ def add_set(self): def add_mask(self, points=None, color=(100, 200, 50), dense=True): # points is list of strokes points_all = np.concatenate(points, axis=0) - + # loop over z values median = [] zdraw = np.unique(points_all[:, 0]) diff --git a/cellpose/gui/io.py b/cellpose/gui/io.py index 47576551..13ebc498 100644 --- a/cellpose/gui/io.py +++ b/cellpose/gui/io.py @@ -477,10 +477,11 @@ def _masks_to_gui(parent, masks, outlines=None, colors=None): """ masks loaded into GUI """ # get unique values shape = masks.shape - masks = masks.flatten() if len(fastremap.unique(masks)) != masks.max() + 1: + print("GUI_INFO: renumbering masks") fastremap.renumber(masks, in_place=True) - masks = masks.reshape(shape) + outlines = None + masks = masks.reshape(shape) masks = masks.astype(np.uint16) if masks.max() < 2**16 - 1 else masks.astype( np.uint32) if parent.restore and "upsample" in parent.restore: @@ -519,9 +520,6 @@ def _masks_to_gui(parent, masks, outlines=None, colors=None): parent.outpix_resize = parent.outpix.copy() else: parent.outpix = outlines - shape = parent.outpix.shape - fastremap.renumber(parent.outpix, in_place=True) - parent.outpix = np.reshape(parent.outpix, shape) if parent.restore and "upsample" in parent.restore: parent.outpix_resize = parent.outpix.copy() parent.outpix_orig = np.zeros_like(parent.cellpix_orig) From 91d4ab76a36c84421a3486848a13069e4f770df7 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 26 Oct 2024 11:45:47 -0400 Subject: [PATCH 08/10] bug with drawing (#930 and #961) --- cellpose/gui/gui.py | 21 ++++++++++++++------- cellpose/gui/io.py | 1 + 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/cellpose/gui/gui.py b/cellpose/gui/gui.py index 36bc07b5..19345e82 100644 --- a/cellpose/gui/gui.py +++ b/cellpose/gui/gui.py @@ -1502,6 +1502,7 @@ def remove_stroke(self, delete_points=True, stroke_ind=-1): stroke = np.array(self.strokes[stroke_ind]) cZ = self.currentZ inZ = stroke[0, 0] == cZ + print(inZ.sum()) if inZ: outpix = self.outpix[cZ, stroke[:, 1], stroke[:, 2]] > 0 self.layerz[stroke[~outpix, 1], stroke[~outpix, 2]] = np.array([0, 0, 0, 0]) @@ -1687,6 +1688,7 @@ def add_set(self): color = self.colormap[self.ncells, :3] median = self.add_mask(points=self.current_point_set, color=color) if median is not None: + print(median) self.removed_cell = [] self.toggle_mask_ops() self.cellcolors = np.append(self.cellcolors, color[np.newaxis, :], @@ -1696,6 +1698,8 @@ def add_set(self): if self.NZ == 1: # only save after each cell if single image io._save_sets_with_check(self) + else: + print("GUI_ERROR: cell too small, not drawn") self.current_stroke = [] self.strokes = [] self.current_point_set = [] @@ -1724,28 +1728,31 @@ def add_mask(self, points=None, color=(100, 200, 50), dense=True): ar, ac = ar + vr.min() - 2, ac + vc.min() - 2 # get dense outline contours = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) - pvc, pvr = contours[-2][0].squeeze().T + print(contours[-2][0].shape) + pvc, pvr = contours[-2][0][:,0].T vr, vc = pvr + vr.min() - 2, pvc + vc.min() - 2 # concatenate all points ar, ac = np.hstack((np.vstack((vr, vc)), np.vstack((ar, ac)))) # if these pixels are overlapping with another cell, reassign them ioverlap = self.cellpix[z][ar, ac] > 0 - if (~ioverlap).sum() < 8: - print("ERROR: cell too small without overlaps, not drawn") + if (~ioverlap).sum() < 10: + print("GUI_ERROR: cell < 10 pixels without overlaps, not drawn") return None elif ioverlap.sum() > 0: ar, ac = ar[~ioverlap], ac[~ioverlap] # compute outline of new mask - mask = np.zeros((np.ptp(ar) + 4, np.ptp(ac) + 4), np.uint8) - mask[ar - ar.min() + 2, ac - ac.min() + 2] = 1 + mask = np.zeros((np.ptp(vr) + 4, np.ptp(vc) + 4), np.uint8) + mask[ar - vr.min() + 2, ac - vc.min() + 2] = 1 contours = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) - pvc, pvr = contours[-2][0].squeeze().T - vr, vc = pvr + ar.min() - 2, pvc + ac.min() - 2 + print(contours[-2][0].shape) + pvc, pvr = contours[-2][0][:,0].T + vr, vc = pvr + vr.min() - 2, pvc + vc.min() - 2 ars = np.concatenate((ars, ar), axis=0) acs = np.concatenate((acs, ac), axis=0) vrs = np.concatenate((vrs, vr), axis=0) vcs = np.concatenate((vcs, vc), axis=0) + print("HI", ars, acs) self.draw_mask(z, ars, acs, vrs, vcs, color) median.append(np.array([np.median(ars), np.median(acs)])) diff --git a/cellpose/gui/io.py b/cellpose/gui/io.py index 13ebc498..d1d9bf87 100644 --- a/cellpose/gui/io.py +++ b/cellpose/gui/io.py @@ -482,6 +482,7 @@ def _masks_to_gui(parent, masks, outlines=None, colors=None): fastremap.renumber(masks, in_place=True) outlines = None masks = masks.reshape(shape) + outlines = None masks = masks.astype(np.uint16) if masks.max() < 2**16 - 1 else masks.astype( np.uint32) if parent.restore and "upsample" in parent.restore: From 09214042c635668d56248738ac165a5812b4a834 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 26 Oct 2024 11:48:43 -0400 Subject: [PATCH 09/10] removing print statements --- cellpose/gui/gui.py | 7 +------ cellpose/gui/io.py | 4 ++-- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/cellpose/gui/gui.py b/cellpose/gui/gui.py index 19345e82..d8d6770c 100644 --- a/cellpose/gui/gui.py +++ b/cellpose/gui/gui.py @@ -1502,7 +1502,6 @@ def remove_stroke(self, delete_points=True, stroke_ind=-1): stroke = np.array(self.strokes[stroke_ind]) cZ = self.currentZ inZ = stroke[0, 0] == cZ - print(inZ.sum()) if inZ: outpix = self.outpix[cZ, stroke[:, 1], stroke[:, 2]] > 0 self.layerz[stroke[~outpix, 1], stroke[~outpix, 2]] = np.array([0, 0, 0, 0]) @@ -1688,7 +1687,6 @@ def add_set(self): color = self.colormap[self.ncells, :3] median = self.add_mask(points=self.current_point_set, color=color) if median is not None: - print(median) self.removed_cell = [] self.toggle_mask_ops() self.cellcolors = np.append(self.cellcolors, color[np.newaxis, :], @@ -1728,7 +1726,6 @@ def add_mask(self, points=None, color=(100, 200, 50), dense=True): ar, ac = ar + vr.min() - 2, ac + vc.min() - 2 # get dense outline contours = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) - print(contours[-2][0].shape) pvc, pvr = contours[-2][0][:,0].T vr, vc = pvr + vr.min() - 2, pvc + vc.min() - 2 # concatenate all points @@ -1745,15 +1742,13 @@ def add_mask(self, points=None, color=(100, 200, 50), dense=True): mask[ar - vr.min() + 2, ac - vc.min() + 2] = 1 contours = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) - print(contours[-2][0].shape) pvc, pvr = contours[-2][0][:,0].T vr, vc = pvr + vr.min() - 2, pvc + vc.min() - 2 ars = np.concatenate((ars, ar), axis=0) acs = np.concatenate((acs, ac), axis=0) vrs = np.concatenate((vrs, vr), axis=0) vcs = np.concatenate((vcs, vc), axis=0) - print("HI", ars, acs) - + self.draw_mask(z, ars, acs, vrs, vcs, color) median.append(np.array([np.median(ars), np.median(acs)])) diff --git a/cellpose/gui/io.py b/cellpose/gui/io.py index d1d9bf87..abcb8e8a 100644 --- a/cellpose/gui/io.py +++ b/cellpose/gui/io.py @@ -482,7 +482,8 @@ def _masks_to_gui(parent, masks, outlines=None, colors=None): fastremap.renumber(masks, in_place=True) outlines = None masks = masks.reshape(shape) - outlines = None + if masks.ndim == 2: + outlines = None masks = masks.astype(np.uint16) if masks.max() < 2**16 - 1 else masks.astype( np.uint32) if parent.restore and "upsample" in parent.restore: @@ -650,7 +651,6 @@ def _save_sets(parent): "diameter": parent.diameter } - print(dat["masks"].shape) if parent.restore is not None: dat["img_restore"] = parent.stack_filtered np.save(base + "_seg.npy", dat) From 0fd761106d3f20994fb7e507af5655bcde8bcef6 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 26 Oct 2024 11:49:13 -0400 Subject: [PATCH 10/10] removing io save print --- cellpose/gui/io.py | 1 - 1 file changed, 1 deletion(-) diff --git a/cellpose/gui/io.py b/cellpose/gui/io.py index abcb8e8a..bacb10ea 100644 --- a/cellpose/gui/io.py +++ b/cellpose/gui/io.py @@ -692,7 +692,6 @@ def _save_sets(parent): "diameter": parent.diameter } - print(dat["masks"].shape) if parent.restore is not None: dat["img_restore"] = parent.stack_filtered np.save(base + "_seg.npy", dat)