Source code for histomicstk.segmentation.nuclear.detect_nuclei_kofahi

import numpy as np

import histomicstk as htk
import histomicstk.filters.shape as htk_shape_filters


[docs] def detect_nuclei_kofahi(im_nuclei_stain, im_nuclei_fgnd_mask, min_radius, max_radius, min_nucleus_area, local_max_search_radius): """Performs a nuclear segmentation using kofahi's method. This method uses scale-adaptive multi-scale Laplacian-of-Gaussian filtering for blob enhancement and a local maximum clustering for segmentation. The original implementation described by Al-Kofahi et al. uses Laplacian of Gaussian but this function replaces it with Difference of Gaussian to improve speed. Parameters ---------- im_nuclei_stain : array_like A hematoxylin intensity image obtained from ColorDeconvolution. im_nuclei_fgnd_mask: array_like A binary mask of the nuclear foreground typically obtained by applying a threshold on the hematoxylin/nuclei stain image min_radius : float Minimum nuclear radius (used to set min sigma of the multiscale LoG filter) max_radius : float Maximum nuclear radius (used to set max sigma of the multiscale LoG filter) min_nucleus_area : int Minimum area that each nucleus should have local_max_search_radius : float Local max search radius used for detection seed points in nuclei Returns ------- im_nuclei_seg_mask : array_like A 2D array mask of the nuclei segmentation. References ---------- .. [#] Y. Al-Kofahi et al "Improved Automatic Detection and Segmentation of Cell Nuclei in Histopathology Images" in IEEE Transactions on Biomedical Engineering, Volume: 57, Issue: 4, doi: 10.1109/TBME.2009.2035102, April 2010. """ import scipy as sp import skimage.morphology # smooth foreground mask with closing and opening im_nuclei_fgnd_mask = skimage.morphology.closing( im_nuclei_fgnd_mask, skimage.morphology.disk(3)) im_nuclei_fgnd_mask = skimage.morphology.opening( im_nuclei_fgnd_mask, skimage.morphology.disk(3)) im_nuclei_fgnd_mask = sp.ndimage.binary_fill_holes( im_nuclei_fgnd_mask) if not np.any(im_nuclei_fgnd_mask): return im_nuclei_fgnd_mask # run adaptive multi-scale LoG filter im_log_max, im_sigma_max = htk_shape_filters.cdog( im_nuclei_stain, im_nuclei_fgnd_mask, sigma_min=min_radius / np.sqrt(2), sigma_max=max_radius / np.sqrt(2), ) # apply local maximum clustering im_nuclei_seg_mask, seeds, maxima = htk.segmentation.nuclear.max_clustering( im_log_max, im_nuclei_fgnd_mask, local_max_search_radius) if seeds is None: return im_nuclei_seg_mask # split any objects with disconnected fragments im_nuclei_seg_mask = htk.segmentation.label.split(im_nuclei_seg_mask, conn=8) # filter out small objects im_nuclei_seg_mask = htk.segmentation.label.area_open( im_nuclei_seg_mask, min_nucleus_area).astype(int) return im_nuclei_seg_mask