MouseLand / cellpose

a generalist algorithm for cellular segmentation with human-in-the-loop capabilities
https://www.cellpose.org/
BSD 3-Clause "New" or "Revised" License
1.31k stars 376 forks source link

Full resolution image yields unprecise mask compared to downsized image #8

Closed adrtsc closed 4 years ago

adrtsc commented 4 years ago

Hi Cellpose team,

I am trying to segment cells in a 2048x2048 image with a red (cytoplasm) and blue (nuclei) channel. In a first attempt, I rescaled the image to 512x512 and segmentation worked fine using the following code:

from cellpose import models
import matplotlib.pyplot as plt
import mxnet as mx

device = mx.cpu()
model = models.Cellpose(device, model_type = "cyto")
# my_image is a 512*512*3 numpy array ([:,:,0] = nuclei, [:,:,1] = empty, [:,:,2] = cells)
my_image = [plt.imread("my_image_rescaled.png")] 
channels = [1,3]

# evaluate the model (rescale is 27/cell_diameter)
masks, flows, styles, diams = model.eval(my_image, channels=channels, rescale= 27./70.)

# plot

img = transforms.reshape(my_image[0], channels)
img = plot.rgb_image(img)
maski = masks[0]
flowi = flows[0][0]

fig = plt.figure(figsize=(12,3))
# can save images (set save_dir=None if not)
plot.show_segmentation(fig, img, maski, flowi)
plt.tight_layout()
plt.show()

Looks great! Then I tried the same thing with the original-size image. The average cell diameter is then around 280px:

from cellpose import models
import matplotlib.pyplot as plt
import mxnet as mx

device = mx.cpu()
model = models.Cellpose(device, model_type = "cyto")
# my_image is a 2048*2048*3 numpy array ([:,:,0] = nuclei, [:,:,1] = empty, [:,:,2] = cells)
my_image = [plt.imread("my_image.png")] 
channels = [1,3]

# evaluate the model (rescale is 27/cell_diameter)
masks, flows, styles, diams = model.eval(my_image, channels=channels, rescale= 27./280.)

# plot

img = transforms.reshape(my_image[0], channels)
img = plot.rgb_image(img)
maski = masks[0]
flowi = flows[0][0]

fig = plt.figure(figsize=(12,3))
# can save images (set save_dir=None if not)
plot.show_segmentation(fig, img, maski, flowi)
plt.tight_layout()
plt.show()

Now the masks are not very accurate anymore. However, the cellpose prediction still looks good. I've tried playing with the threshold parameter, but it seems to have no effect:

Threshold = 0.9

Threshold = 0.1

I have also tried to turn off tiling, which also did not have an effect. Do you have an idea what could be going wrong here?

Thanks

marius10p commented 4 years ago

The max number of iterations for assembling pixels into masks (fig 1e) is hard coded to 100 or 200. @carsen-stringer can you please change this to be a function of diameter? .

carsen-stringer commented 4 years ago

the dynamics iterations are now scaled by the diameter. please try it out (github version updated, not pip)

adrtsc commented 4 years ago

This seems to have fixed the problem and the masks for the full-size image now have the correct size. Thanks!

from cellpose import models
import matplotlib.pyplot as plt
import mxnet as mx

device = mx.cpu()
model = models.Cellpose(device, model_type = "cyto")
# my_image is a 2048*2048*3 numpy array ([:,:,0] = nuclei, [:,:,1] = empty, [:,:,2] = cells)
my_image = [plt.imread("my_image.png")] 
channels = [1,3]

# evaluate the model (rescale is 27/cell_diameter)
masks, flows, styles, diams = model.eval(my_image, channels=channels, rescale= 27./280.)

# plot

img = transforms.reshape(my_image[0], channels)
img = plot.rgb_image(img)
maski = masks[0]
flowi = flows[0][0]

fig = plt.figure(figsize=(12,3))
# can save images (set save_dir=None if not)
plot.show_segmentation(fig, img, maski, flowi)
plt.tight_layout()
plt.show()

Figure_1_after_fix