Source code for histomicstk.segmentation.nuclear.detect_tile_nuclei

import numpy as np

import histomicstk.features as htk_features
import histomicstk.preprocessing.color_deconvolution as htk_cdeconv
import histomicstk.preprocessing.color_normalization as htk_cnorm
import histomicstk.segmentation.label as htk_seg_label
import histomicstk.segmentation.nuclear as htk_nuclear
from histomicstk.cli import utils as cli_utils


[docs] def detect_tile_nuclei(tile_info, args, src_mu_lab=None, src_sigma_lab=None, invert_image=False, default_img_inversion=False, return_fdata=False): """ Detect nuclei within a tile image and generate annotations. Args: ---- tile_info (dict): Information about the tile image. args: Arguments from the cli. src_mu_lab: Source mean in LAB color space. src_sigma_lab: Source standard deviation in LAB color space. invert_image (bool): Invert the image. default_img_inversion (bool): Apply default image inversion. return_fdata (bool): Return computed features. Returns: ------- nuclei_annot_list (list): List of nuclei annotations. fdata: Computed nuclei features. """ # Flags single_channel = False # get tile image & check number of channels single_channel = len(tile_info['tile'].shape) <= 2 or tile_info['tile'].shape[2] == 1 if single_channel: im_tile = np.dstack((tile_info['tile'], tile_info['tile'], tile_info['tile'])) if default_img_inversion: invert_image = True else: im_tile = tile_info['tile'][:, :, :3] # perform image inversion if invert_image: im_tile = (np.iinfo(im_tile.dtype).max if im_tile.dtype.kind == 'u' else np.max(im_tile)) - im_tile # perform color normalization im_nmzd = htk_cnorm.reinhard(im_tile, args.reference_mu_lab, args.reference_std_lab, src_mu=src_mu_lab, src_sigma=src_sigma_lab) # perform color decovolution w = cli_utils.get_stain_matrix(args) # perform deconvolution im_stains = htk_cdeconv.color_deconvolution(im_nmzd, w).Stains im_nuclei_stain = im_stains[:, :, 0].astype(float) # segment nuclear foreground im_nuclei_fgnd_mask = im_nuclei_stain < args.foreground_threshold # segment nuclei im_nuclei_seg_mask = htk_nuclear.detect_nuclei_kofahi( im_nuclei_stain, im_nuclei_fgnd_mask, args.min_radius, args.max_radius, args.min_nucleus_area, args.local_max_search_radius, ) # Delete border nuclei if args.ignore_border_nuclei is True: im_nuclei_seg_mask = htk_seg_label.delete_border(im_nuclei_seg_mask) # Delete overlapping border nuclei if any(tile_info['tile_overlap'].values()) > 0: im_nuclei_seg_mask = htk_seg_label.delete_overlap( im_nuclei_seg_mask, overlap_info=tile_info['tile_overlap']) # generate nuclei annotations nuclei_annot_list = [] flag_nuclei_found = np.any(im_nuclei_seg_mask) # compute nuclei features and nuclei_annot_list fdata = None if flag_nuclei_found: if args.nuclei_annotation_format: format = args.nuclei_annotation_format if args.nuclei_annotation_format == 'bbox' and - \ args.remove_overlapping_nuclei_segmentation: format = 'boundary' if return_fdata: if args.cytoplasm_features: im_cytoplasm_stain = im_stains[:, :, 1].astype(float) else: im_cytoplasm_stain = None # Generate features and nuclei annotation simultaneously fdata, nuclei_annot_list = htk_features.compute_nuclei_features( im_nuclei_seg_mask, im_nuclei_stain.astype(np.uint8), im_cytoplasm_stain.astype(np.uint8), fsd_bnd_pts=args.fsd_bnd_pts, fsd_freq_bins=args.fsd_freq_bins, cyto_width=args.cyto_width, num_glcm_levels=args.num_glcm_levels, morphometry_features_flag=args.morphometry_features, fsd_features_flag=args.fsd_features, intensity_features_flag=args.intensity_features, gradient_features_flag=args.gradient_features, tile_info=tile_info, im_nuclei_seg_mask=im_nuclei_seg_mask, format=format, return_nuclei_annotation=True, ) fdata.columns = ['Feature.' + col for col in fdata.columns] else: nuclei_annot_list = cli_utils.create_tile_nuclei_annotations( im_nuclei_seg_mask, tile_info, format) if return_fdata: return nuclei_annot_list, fdata return nuclei_annot_list