Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] H&E image nucleus segmentation works with v2 but not with v3 #1056

Open
gdurif opened this issue Nov 20, 2024 · 4 comments
Open

[BUG] H&E image nucleus segmentation works with v2 but not with v3 #1056

gdurif opened this issue Nov 20, 2024 · 4 comments
Labels
bug Something isn't working

Comments

@gdurif
Copy link

gdurif commented Nov 20, 2024

Bug description

Running nuclei segmentation on H&E stained images used to work with cellpose v2 (tested with v2.2.3 and v2.3.2) but does not work anymore with cellpose v3 (tested with v3.0 and v3.1.0), c.f. example below.

Python version: Python 3.12.7
OS: 6.11.7-arch1-1 x86_64 GNU/Linux

To Reproduce

Steps to reproduce the behavior:

  1. Install requirements inside a dedicated environment (replace XXXX by requested cellpose version):
python -m venv ./venv
source ./venv/bin/activate
pip install matplotlib
pip install cellpose==XXX
  1. We will use the following TCGA-E2-A14V-01Z-00-DX1.png image (a crop from an image from the MoNuSeg dataset available under CC BY-NC-SA 4.0 license):

TCGA-E2-A14V-01Z-00-DX1

Note: I usually use tif image for segmentation but it is not possible to attach tif file on github so I converted it to png.

  1. Run the following minimum example to reproduce the issue:
from cellpose.io import imread, logger_setup
from cellpose import models, version
logger = logger_setup()

import matplotlib.pyplot as plt

# cellpose version
print(f"cellpose version = {version}")

# image
image_name = "TCGA-E2-A14V-01Z-00-DX1"
ext = "png"  # "tif""
image_path = f"{image_name}.{ext}"

# load image
image = imread(image_path)

# methods
cellpose_model = models.Cellpose(
    model_type="nuclei", gpu=False
)

# run
res, _, _, _ = cellpose_model.eval(
    image,
    channels=[0, 0],
    diameter=None,
    min_size=15,
    invert=True,
    flow_threshold=0.4,
)


# graphics
fig, axs = plt.subplots(nrows=1, ncols=2, figsize=(8,4))
fig.tight_layout()
axs[0].imshow(image)
axs[0].title.set_text("original image")
axs[1].imshow(res)
axs[1].title.set_text(f"cellpose")

fig.savefig("cellpose.png")

Results

Here is what we get with cellpose v2.3.2 (it works!):

cellpose_v2 3 2

Here is what we get with cellpose v3.1.0 (we get nothing!):

cellpose_v3 1 0

Logs

  • Here are the logs for cellpose v2.3.2:
2024-11-20 17:14:36,434 [INFO] WRITING LOG OUTPUT TO /XXXX/.cellpose/run.log
2024-11-20 17:14:36,434 [INFO] 
cellpose version:       2.3.2 
platform:               linux 
python version:         3.12.7 
torch version:          2.5.1+cu124
cellpose version = 2.3.2
2024-11-20 17:14:36,437 [INFO] >>>> using CPU
2024-11-20 17:14:36,438 [INFO] >> nuclei << model set to be used
/XXXX/lib/python3.12/site-packages/cellpose/resnet_torch.py:235: FutureWarning: You are using `torch.load` with `weights_only=False` (the current default value), which uses the default pickle module implicitly. It is possible to construct malicious pickle data which will execute arbitrary code during unpickling (See https://github.com/pytorch/pytorch/blob/main/SECURITY.md#untrusted-models for more details). In a future release, the default value for `weights_only` will be flipped to `True`. This limits the functions that could be executed during unpickling. Arbitrary objects will no longer be allowed to be loaded via this mode unless they are explicitly allowlisted by the user via `torch.serialization.add_safe_globals`. We recommend you start setting `weights_only=True` for any use case where you don't have full control of the loaded file. Please open an issue on GitHub for any issues related to this experimental feature.
  state_dict = torch.load(filename, map_location=torch.device('cpu'))
2024-11-20 17:14:36,531 [INFO] >>>> model diam_mean =  17.000 (ROIs rescaled to this size during training)
2024-11-20 17:14:36,531 [INFO] ~~~ ESTIMATING CELL DIAMETER(S) ~~~
2024-11-20 17:14:37,059 [INFO] estimated cell diameter(s) in 0.53 sec
2024-11-20 17:14:37,059 [INFO] >>> diameter(s) = 
2024-11-20 17:14:37,059 [INFO] [ 18.05 ]
2024-11-20 17:14:37,059 [INFO] ~~~ FINDING MASKS ~~~
2024-11-20 17:14:37,359 [INFO] >>>> TOTAL TIME 0.83 sec
  • Here are the logs for cellpose v3.1.0:
2024-11-20 17:16:51,603 [INFO] WRITING LOG OUTPUT TO /XXXX/.cellpose/run.log
2024-11-20 17:16:51,603 [INFO] 
cellpose version:       3.1.0 
platform:               linux 
python version:         3.12.7 
torch version:          2.5.1+cu124
cellpose version = 3.1.0
2024-11-20 17:16:51,606 [INFO] >>>> using CPU
2024-11-20 17:16:51,606 [INFO] >>>> using CPU
2024-11-20 17:16:51,606 [INFO] >> nuclei << model set to be used
2024-11-20 17:16:51,641 [INFO] >>>> loading model /XXXX/.cellpose/models/nucleitorch_0
/XXXX/lib/python3.12/site-packages/cellpose/resnet_torch.py:275: FutureWarning: You are using `torch.load` with `weights_only=False` (the current default value), which uses the default pickle module implicitly. It is possible to construct malicious pickle data which will execute arbitrary code during unpickling (See https://github.com/pytorch/pytorch/blob/main/SECURITY.md#untrusted-models for more details). In a future release, the default value for `weights_only` will be flipped to `True`. This limits the functions that could be executed during unpickling. Arbitrary objects will no longer be allowed to be loaded via this mode unless they are explicitly allowlisted by the user via `torch.serialization.add_safe_globals`. We recommend you start setting `weights_only=True` for any use case where you don't have full control of the loaded file. Please open an issue on GitHub for any issues related to this experimental feature.
  state_dict = torch.load(filename, map_location=torch.device("cpu"))
2024-11-20 17:16:51,694 [INFO] >>>> model diam_mean =  17.000 (ROIs rescaled to this size during training)
2024-11-20 17:16:51,695 [INFO] channels set to [0, 0]
2024-11-20 17:16:51,695 [INFO] ~~~ ESTIMATING CELL DIAMETER(S) ~~~
/XXXX/lib/python3.12/site-packages/numpy/core/fromnumeric.py:3504: RuntimeWarning: Mean of empty slice.
  return _methods._mean(a, axis=axis, dtype=dtype,
/XXXX/lib/python3.12/site-packages/numpy/core/_methods.py:129: RuntimeWarning: invalid value encountered in scalar divide
  ret = ret.dtype.type(ret / rcount)
2024-11-20 17:16:53,751 [INFO] estimated cell diameter(s) in 2.06 sec
2024-11-20 17:16:53,751 [INFO] >>> diameter(s) = 
2024-11-20 17:16:53,751 [INFO] [ 17.00 ]
2024-11-20 17:16:53,751 [INFO] ~~~ FINDING MASKS ~~~
2024-11-20 17:16:53,874 [INFO] >>>> TOTAL TIME 2.18 sec
@gdurif gdurif added the bug Something isn't working label Nov 20, 2024
@ashishUthama
Copy link

Would you mind re-trying specifying a diameter of 18?

(Just a guess to see what happens, since in the logs, the diameter estimation appears to have an issue in 3.1)

@gdurif
Copy link
Author

gdurif commented Nov 21, 2024

So I used:

res, _, _, _ = cellpose_model.eval(
    image,
    channels=[0, 0],
    diameter=18,
    min_size=15,
    invert=True,
    flow_threshold=0.4,
)

And the result is similar, I have nothing in output.

Here are the logs:

2024-11-21 09:12:05,864 [INFO] WRITING LOG OUTPUT TO /XXXX/.cellpose/run.log
2024-11-21 09:12:05,865 [INFO] 
cellpose version: 	3.1.0 
platform:       	linux 
python version: 	3.12.7 
torch version:  	2.5.1+cu124
cellpose version = 3.1.0
2024-11-21 09:12:05,869 [INFO] >>>> using CPU
2024-11-21 09:12:05,869 [INFO] >>>> using CPU
2024-11-21 09:12:05,869 [INFO] >> nuclei << model set to be used
2024-11-21 09:12:05,917 [INFO] >>>> loading model /XXXX/.cellpose/models/nucleitorch_0
/XXXX/lib/python3.12/site-packages/cellpose/resnet_torch.py:275: FutureWarning: You are using `torch.load` with `weights_only=False` (the current default value), which uses the default pickle module implicitly. It is possible to construct malicious pickle data which will execute arbitrary code during unpickling (See https://github.com/pytorch/pytorch/blob/main/SECURITY.md#untrusted-models for more details). In a future release, the default value for `weights_only` will be flipped to `True`. This limits the functions that could be executed during unpickling. Arbitrary objects will no longer be allowed to be loaded via this mode unless they are explicitly allowlisted by the user via `torch.serialization.add_safe_globals`. We recommend you start setting `weights_only=True` for any use case where you don't have full control of the loaded file. Please open an issue on GitHub for any issues related to this experimental feature.
  state_dict = torch.load(filename, map_location=torch.device("cpu"))
2024-11-21 09:12:05,984 [INFO] >>>> model diam_mean =  17.000 (ROIs rescaled to this size during training)
2024-11-21 09:12:05,984 [INFO] channels set to [0, 0]
2024-11-21 09:12:05,984 [INFO] ~~~ FINDING MASKS ~~~
2024-11-21 09:12:06,336 [INFO] >>>> TOTAL TIME 0.35 sec

@gdurif
Copy link
Author

gdurif commented Nov 21, 2024

And same with diameter=18.05 to match the estimated value from v2.3.2 run.

@gdurif
Copy link
Author

gdurif commented Dec 12, 2024

Any news regarding this issue? Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants