| import numpy as np |
| from skimage import exposure |
|
|
| from .params import AnalysisParameters |
|
|
|
|
| class CellposeSegmenter: |
| def __init__(self, params: AnalysisParameters): |
| self.params = params |
| self.model = self._load_model() |
|
|
| def _load_model(self): |
| from cellpose import models |
| return models.CellposeModel( |
| pretrained_model=self.params.pretrained_model, |
| gpu=self.params.gpu, |
| ) |
|
|
| def segment(self, image: np.ndarray) -> np.ndarray: |
| if image.ndim == 2: |
| img = np.stack([image, image, image], axis=0) |
| elif image.ndim == 3: |
| if image.shape[-1] in (3, 4): |
| img = np.transpose(image[:, :, :3], (2, 0, 1)) |
| elif image.shape[0] in (3, 4): |
| img = image[:3] |
| else: |
| raise ValueError(f"Unexpected image shape: {image.shape}") |
| else: |
| raise ValueError(f"Unexpected image ndim: {image.ndim}") |
|
|
| |
| for c in range(img.shape[0]): |
| p2, p98 = np.percentile(img[c], (2, 98)) |
| img[c] = exposure.rescale_intensity(img[c], in_range=(p2, p98)) |
|
|
| |
| img_inv = 255 - img if img.max() > 1 else 1 - img |
|
|
| masks, _, _ = self.model.eval( |
| img_inv, |
| diameter=self.params.diameter, |
| flow_threshold=self.params.flow_threshold, |
| cellprob_threshold=self.params.cellprob_threshold, |
| ) |
| return masks |
|
|