def set_color_normalization_target(self, ref_image_path, color_normalization_method='macenko_pca' ): """Set color normalization values to use from target image. Arguments ref_image_path, str > path to target (reference) image color_normalization_method, str > color normalization method to use. Currently, only > reinhard and macenko_pca are accepted. """ # read input image ref_im = np.array(imread(ref_image_path, pilmode='RGB')) # assign target values color_normalization_method = color_normalization_method.lower() if color_normalization_method == 'reinhard': mu, sigma = lab_mean_std(ref_im) self.target_stats_reinhard['mu'] = mu self.target_stats_reinhard['sigma'] = sigma elif color_normalization_method == 'macenko_pca': self.target_W_macenko = _reorder_stains( rgb_separate_stains_macenko_pca(ref_im, I_0=None), stains=['hematoxylin', 'eosin']) else: raise ValueError("Unknown color_normalization_method: %s" % (color_normalization_method)) self.color_normalization_method = color_normalization_method
def reinhard_stats(slide_path, sample_fraction, magnification=None): """Samples a whole-slide-image to determine colorspace statistics (mean, variance) needed to perform global Reinhard color normalization. Normalizing individual tiles independently creates a significant bias in the results of segmentation and feature extraction, as the color statistics of each tile in a whole-slide image can vary significantly. To remedy this, we sample a subset of pixels from the entire whole-slide image in order to estimate the global mean and standard deviation of each channel in the Lab color space that are needed for reinhard color normalization. Parameters ---------- slide_path : str path and filename of slide. sample_fraction : double Fraction of pixels to sample (range (0, 1]). magnification : scalar Desired magnification for sampling. Defaults to native scan magnification. Returns ------- Mu : array_like A 3-element array containing the means of the target image channels in sample_pix_lab color space. Sigma : array_like A 3-element list containing the standard deviations of the target image channels in sample_pix_lab color space. Notes ----- Returns a namedtuple. See Also -------- histomicstk.preprocessing.color_conversion.lab_mean_std histomicstk.preprocessing.color_normalization.reinhard """ # generate a sampling of sample_pixels_rgb pixels from whole-slide image sample_pixels_rgb = sample_pixels(slide_path, sample_fraction, magnification) # reshape the Nx3 pixel array into a 1 x N x 3 image for lab_mean_std sample_pixels_rgb = np.reshape(sample_pixels_rgb, (1, sample_pixels_rgb.shape[0], 3)) # compute mean and stddev of sample pixels in Lab space Mu, Sigma = color_conversion.lab_mean_std(sample_pixels_rgb) # build named tuple for output ReinhardStats = collections.namedtuple('ReinhardStats', ['Mu', 'Sigma']) stats = ReinhardStats(Mu, Sigma) return stats
def reinhard_stats(slide_path, magnification, sample_percent): """Samples a whole-slide-image to determine colorspace statistics (mean, variance) needed to perform global Reinhard color normalization. Normalizing individual tiles independently creates a significant bias in the results of segmentation and feature extraction, as the color statistics of each tile in a whole-slide image can vary significantly. To remedy this, we sample a subset of pixels from the entire whole-slide image in order to estimate the global mean and standard deviation of each channel in the Lab color space that are needed for reinhard color normalization. Parameters ---------- slide_path : str path and filename of slide. magnification : scalar Desired magnification for sampling. Defaults to native scan magnification. sample_percent : double Percentage of pixels to sample (range (0, 1]). Returns ------- Mu : array_like A 3-element array containing the means of the target image channels in sample_pix_lab color space. Sigma : array_like A 3-element list containing the standard deviations of the target image channels in sample_pix_lab color space. Notes ----- Returns a namedtuple. See Also -------- histomicstk.preprocessing.color_conversion.lab_mean_std histomicstk.preprocessing.color_normalization.reinhard """ # generate a sampling of sample_pixels_rgb pixels from whole-slide image sample_pixels_rgb = sample_pixels(slide_path, magnification, sample_percent) # reshape the Nx3 pixel array into a 1 x N x 3 image for lab_mean_std sample_pixels_rgb = np.reshape(sample_pixels_rgb, (1, sample_pixels_rgb.shape[0], 3)) # compute mean and stddev of sample pixels in Lab space Mu, Sigma = color_conversion.lab_mean_std(sample_pixels_rgb) # build named tuple for output ReinhardStats = collections.namedtuple('ReinhardStats', ['Mu', 'Sigma']) stats = ReinhardStats(Mu, Sigma) return stats
def set_color_normalization_values( self, mu=None, sigma=None, ref_image_path=None, what='main'): """Set color normalization values for thumbnail or main image.""" assert ( all([j is not None for j in (mu, sigma)]) or ref_image_path is not None), \ "You must provide mu & sigma values or ref. image to get them." assert what in ('thumbnail', 'main') if ref_image_path is not None: ref_im = np.array(imread(ref_image_path, pilmode='RGB')) mu, sigma = lab_mean_std(ref_im) self.cnorm_params[what] = {'mu': mu, 'sigma': sigma}
def test_normalization(self): input_image_file = os.path.join(TEST_DATA_DIR, 'L1.png') ref_image_file = os.path.join(TEST_DATA_DIR, 'Easy1.png') # read input image im_input = skimage.io.imread(input_image_file)[:, :, :3] # read reference image im_reference = skimage.io.imread(ref_image_file)[:, :, :3] # get mean and stddev of reference image in lab space mean_ref, std_ref = htk_cvt.lab_mean_std(im_reference) # perform color normalization im_nmzd = htk_cn.reinhard(im_input, mean_ref, std_ref) # transform normalized image to LAB color space mean_nmzd, std_nmzd = htk_cvt.lab_mean_std(im_nmzd) # check if mean and stddev of normalized and reference images are equal np.testing.assert_allclose(mean_nmzd, mean_ref, atol=1e-1) np.testing.assert_allclose(std_nmzd, std_ref, atol=1e-1)
def test_reinhard(self): """Test reinhard.""" # # SANITY CHECK! normalize to LAB mean and std from SAME slide # mean_lab, std_lab = lab_mean_std(tissue_rgb) # tissue_rgb_normalized = reinhard( # tissue_rgb, target_mu=mean_lab, target_sigma=std_lab) # # we expect the images to be (almost) exactly the same # assert np.mean(tissue_rgb - tissue_rgb_normalized) < 1 # color norm. standard (from TCGA-A2-A3XS-DX1, Amgad et al, 2019) cnorm = { 'mu': np.array([8.74108109, -0.12440419, 0.0444982]), 'sigma': np.array([0.6135447, 0.10989545, 0.0286032]), } # Normalize to pre-set color standard (unmasked) tissue_rgb_normalized = reinhard(cfg.tissue_rgb, target_mu=cnorm['mu'], target_sigma=cnorm['sigma']) # check that it matches mean_lab, std_lab = lab_mean_std(tissue_rgb_normalized) assert all(np.abs(mean_lab - cnorm['mu']) < [0.1, 0.1, 0.1]) assert all(np.abs(std_lab - cnorm['sigma']) < [0.1, 0.1, 0.1]) # Do MASKED normalization to preset standard tissue_rgb_normalized = reinhard(cfg.tissue_rgb, target_mu=cnorm['mu'], target_sigma=cnorm['sigma'], mask_out=cfg.mask_out) # check that it matches mean_lab, std_lab = lab_mean_std(tissue_rgb_normalized, mask_out=cfg.mask_out) assert all(np.abs(mean_lab - cnorm['mu']) < [0.1, 0.1, 0.1]) assert all(np.abs(std_lab - cnorm['sigma']) < [0.1, 0.1, 0.1])
def test_segment_nuclei_kofahi(self): input_image_file = datastore.fetch('Easy1.png') ref_image_file = datastore.fetch('L1.png') # read input image im_input = skimage.io.imread(input_image_file)[:, :, :3] # read reference image im_reference = skimage.io.imread(ref_image_file)[:, :, :3] # get mean and stddev of reference image in lab space mean_ref, std_ref = htk_cvt.lab_mean_std(im_reference) # perform color normalization im_nmzd = htk_cnorm.reinhard(im_input, mean_ref, std_ref) # perform color decovolution stain_color_map = { 'hematoxylin': [0.65, 0.70, 0.29], 'eosin': [0.07, 0.99, 0.11], 'dab': [0.27, 0.57, 0.78], 'null': [0.0, 0.0, 0.0] } w = htk_cdeconv.rgb_separate_stains_macenko_pca(im_nmzd, im_nmzd.max()) im_stains = htk_cdeconv.color_deconvolution(im_nmzd, w).Stains nuclei_channel = htk_cdeconv.find_stain_index( stain_color_map['hematoxylin'], w) im_nuclei_stain = im_stains[:, :, nuclei_channel].astype(np.float) # segment nuclei im_nuclei_seg_mask = htk_seg.nuclear.detect_nuclei_kofahi( im_nuclei_stain, im_nuclei_stain < 60, min_radius=20, max_radius=30, min_nucleus_area=80, local_max_search_radius=10) num_nuclei = len(np.unique(im_nuclei_seg_mask)) - 1 # check if segmentation mask matches ground truth gtruth_mask_file = os.path.join( datastore.fetch('Easy1_nuclei_seg_kofahi.npy')) im_gtruth_mask = np.load(gtruth_mask_file) num_nuclei_gtruth = len(np.unique(im_gtruth_mask)) - 1 assert num_nuclei == num_nuclei_gtruth np.testing.assert_allclose(im_nuclei_seg_mask, im_gtruth_mask) # check no nuclei case im_nuclei_seg_mask = htk_seg.nuclear.detect_nuclei_kofahi( 255 * np.ones_like(im_nuclei_stain), np.ones_like(im_nuclei_stain), min_radius=20, max_radius=30, min_nucleus_area=80, local_max_search_radius=10) num_nuclei = len(np.unique(im_nuclei_seg_mask)) - 1 assert num_nuclei == 0
def main(args): # # Read Input Image # print('>> Reading input image') imInput = skimage.io.imread(args.inputImageFile)[:, :, :3] # # Perform color normalization # print('>> Performing color normalization') # compute mean and stddev of input in LAB color space Mu, Sigma = htk_color_conversion.lab_mean_std(imInput) # perform reinhard normalization imNmzd = htk_color_normalization.reinhard(imInput, Mu, Sigma) # # Perform color deconvolution # print('>> Performing color deconvolution') stainColor_1 = stainColorMap[args.stain_1] stainColor_2 = stainColorMap[args.stain_2] stainColor_3 = stainColorMap[args.stain_3] W = np.array([stainColor_1, stainColor_2, stainColor_3]).T imDeconvolved = htk_color_deconvolution.ColorDeconvolution(imNmzd, W) imNucleiStain = imDeconvolved.Stains[:, :, 0].astype(np.float) # # Perform nuclei segmentation # print('>> Performing nuclei segmentation') # segment foreground imFgndMask = sp.ndimage.morphology.binary_fill_holes( imNucleiStain < args.foreground_threshold) # run adaptive multi-scale LoG filter imLog = htk_shape_filters.clog(imNucleiStain, imFgndMask, sigma_min=args.min_radius * np.sqrt(2), sigma_max=args.max_radius * np.sqrt(2)) imNucleiSegMask, Seeds, Max = htk_seg.nuclear.max_clustering( imLog, imFgndMask, args.local_max_search_radius) # filter out small objects imNucleiSegMask = htk_seg.label.area_open( imNucleiSegMask, args.min_nucleus_area).astype(np.int) # # Generate annotations # objProps = skimage.measure.regionprops(imNucleiSegMask) print 'Number of nuclei = ', len(objProps) # create basic schema annotation = { "name": "Nuclei", "description": "Nuclei bounding boxes from a segmentation algorithm", "attributes": { "algorithm": { "color_normalization": "reinhard", "color_deconvolution": "ColorDeconvolution", "nuclei_segmentation": ["cLOG", "MaxClustering", "FilterLabel"] } }, "elements": [] } # add each nucleus as an element into the annotation schema for i in range(len(objProps)): c = [objProps[i].centroid[1], objProps[i].centroid[0], 0] width = objProps[i].bbox[3] - objProps[i].bbox[1] + 1 height = objProps[i].bbox[2] - objProps[i].bbox[0] + 1 cur_bbox = { "type": "rectangle", "center": c, "width": width, "height": height, "rotation": 0, "fillColor": "rgba(255, 255, 255, 0)", "lineWidth": 2, "lineColor": "rgb(34, 139, 34)" } annotation["elements"].append(cur_bbox) # # Save output segmentation mask # print('>> Outputting nuclei segmentation mask') skimage.io.imsave(args.outputNucleiMaskFile, imNucleiSegMask) # # Save output annotation # print('>> Outputting nuclei annotation') with open(args.outputNucleiAnnotationFile, 'w') as annotationFile: json.dump(annotation, annotationFile, indent=2, sort_keys=False)
def main(args): # # Read Input Image # print('>> Reading input image') im_input = skimage.io.imread(args.inputImageFile)[:, :, :3] # # Perform color normalization # print('>> Performing color normalization') # compute mean and stddev of input in LAB color space mu, sigma = htk_ccvt.lab_mean_std(im_input) # perform reinhard normalization im_nmzd = htk_cnorm.reinhard(im_input, mu, sigma) # # Perform color deconvolution # print('>> Performing color deconvolution') stain_color_1 = stain_color_map[args.stain_1] stain_color_2 = stain_color_map[args.stain_2] stain_color_3 = stain_color_map[args.stain_3] w = np.array([stain_color_1, stain_color_2, stain_color_3]).T im_stains = htk_cdeconv.color_deconvolution(im_nmzd, w).Stains im_nuclei_stain = im_stains[:, :, 0].astype(np.float) # # Perform nuclei segmentation # print('>> Performing nuclei segmentation') # segment foreground im_fgnd_mask = sp.ndimage.morphology.binary_fill_holes( im_nuclei_stain < args.foreground_threshold) # run adaptive multi-scale LoG filter im_log = htk_shape_filters.clog(im_nuclei_stain, im_fgnd_mask, sigma_min=args.min_radius * np.sqrt(2), sigma_max=args.max_radius * np.sqrt(2)) im_nuclei_seg_mask, seeds, max = htk_seg.nuclear.max_clustering( im_log, im_fgnd_mask, args.local_max_search_radius) # filter out small objects im_nuclei_seg_mask = htk_seg.label.area_open( im_nuclei_seg_mask, args.min_nucleus_area).astype(np.int) # # Generate annotations # obj_props = skimage.measure.regionprops(im_nuclei_seg_mask) print 'Number of nuclei = ', len(obj_props) # create basic schema annotation = { "name": "Nuclei", "description": "Nuclei bounding boxes from a segmentation algorithm", "attributes": { "algorithm": { "color_normalization": "reinhard", "color_deconvolution": "ColorDeconvolution", "nuclei_segmentation": ["cLOG", "MaxClustering", "FilterLabel"] } }, "elements": [] } # add each nucleus as an element into the annotation schema for i in range(len(obj_props)): c = [obj_props[i].centroid[1], obj_props[i].centroid[0], 0] width = obj_props[i].bbox[3] - obj_props[i].bbox[1] + 1 height = obj_props[i].bbox[2] - obj_props[i].bbox[0] + 1 cur_bbox = { "type": "rectangle", "center": c, "width": width, "height": height, "rotation": 0, "fillColor": "rgba(255, 255, 255, 0)", "lineWidth": 2, "lineColor": "rgb(34, 139, 34)" } annotation["elements"].append(cur_bbox) # # Save output segmentation mask # print('>> Outputting nuclei segmentation mask') skimage.io.imsave(args.outputNucleiMaskFile, im_nuclei_seg_mask) # # Save output annotation # print('>> Outputting nuclei annotation') with open(args.outputNucleiAnnotationFile, 'w') as annotation_file: json.dump(annotation, annotation_file, indent=2, sort_keys=False)
def test_reinhard(self): """Test reinhard.""" # get RGB image at a small magnification slide_info = gc.get('item/%s/tiles' % SAMPLE_SLIDE_ID) getStr = "/item/%s/tiles/region?left=%d&right=%d&top=%d&bottom=%d" % ( SAMPLE_SLIDE_ID, 0, slide_info['sizeX'], 0, slide_info['sizeY'] ) + "&magnification=%.2f" % MAG tissue_rgb = get_image_from_htk_response( gc.get(getStr, jsonResp=False)) # # SANITY CHECK! normalize to LAB mean and std from SAME slide # mean_lab, std_lab = lab_mean_std(tissue_rgb) # tissue_rgb_normalized = reinhard( # tissue_rgb, target_mu=mean_lab, target_sigma=std_lab) # # # we expect the images to be (almost) exactly the same # assert np.mean(tissue_rgb - tissue_rgb_normalized) < 1 # Normalize to pre-set color standard tissue_rgb_normalized = reinhard( tissue_rgb, target_mu=cnorm['mu'], target_sigma=cnorm['sigma']) # check that it matches mean_lab, std_lab = lab_mean_std(tissue_rgb_normalized) self.assertTrue(all( np.abs(mean_lab - cnorm['mu']) < [0.1, 0.1, 0.1])) self.assertTrue(all( np.abs(std_lab - cnorm['sigma']) < [0.1, 0.1, 0.1])) # get tissue mask thumbnail_rgb = get_slide_thumbnail(gc, SAMPLE_SLIDE_ID) labeled, mask = get_tissue_mask( thumbnail_rgb, deconvolve_first=True, n_thresholding_steps=1, sigma=1.5, min_size=30) # # visualize result # vals = np.random.rand(256, 3) # vals[0, ...] = [0.9, 0.9, 0.9] # cMap = ListedColormap(1 - vals) # # f, ax = plt.subplots(1, 3, figsize=(20, 20)) # ax[0].imshow(thumbnail_rgb) # ax[1].imshow(labeled, cmap=cMap) # ax[2].imshow(mask, cmap=cMap) # plt.show() # Do MASKED normalization to preset standard mask_out = resize( labeled == 0, output_shape=tissue_rgb.shape[:2], order=0, preserve_range=True) == 1 tissue_rgb_normalized = reinhard( tissue_rgb, target_mu=cnorm['mu'], target_sigma=cnorm['sigma'], mask_out=mask_out) # check that it matches mean_lab, std_lab = lab_mean_std( tissue_rgb_normalized, mask_out=mask_out) self.assertTrue(all( np.abs(mean_lab - cnorm['mu']) < [0.1, 0.1, 0.1])) self.assertTrue(all( np.abs(std_lab - cnorm['sigma']) < [0.1, 0.1, 0.1]))
def test_segment_nuclei_kofahi(self): input_image_file = os.path.join(TEST_DATA_DIR, 'Easy1.png') ref_image_file = os.path.join(TEST_DATA_DIR, 'L1.png') # read input image im_input = skimage.io.imread(input_image_file)[:, :, :3] # read reference image im_reference = skimage.io.imread(ref_image_file)[:, :, :3] # get mean and stddev of reference image in lab space mean_ref, std_ref = htk_cvt.lab_mean_std(im_reference) # perform color normalization im_nmzd = htk_cnorm.reinhard(im_input, mean_ref, std_ref) # perform color decovolution stain_color_map = { 'hematoxylin': [0.65, 0.70, 0.29], 'eosin': [0.07, 0.99, 0.11], 'dab': [0.27, 0.57, 0.78], 'null': [0.0, 0.0, 0.0] } w = htk_cdeconv.rgb_separate_stains_macenko_pca(im_nmzd, im_nmzd.max()) im_stains = htk_cdeconv.color_deconvolution(im_nmzd, w).Stains nuclei_channel = htk_cdeconv.find_stain_index(stain_color_map['hematoxylin'], w) im_nuclei_stain = im_stains[:, :, nuclei_channel].astype(np.float) # segment foreground (assumes nuclei are darker on a bright background) im_nuclei_fgnd_mask = sp.ndimage.morphology.binary_fill_holes( im_nuclei_stain < 60) # run adaptive multi-scale LoG filter im_log, im_sigma_max = htk_shape_filters.clog( im_nuclei_stain, im_nuclei_fgnd_mask, sigma_min=20 / np.sqrt(2), sigma_max=30 / np.sqrt(2)) # apply local maximum clustering im_nuclei_seg_mask, seeds, maxima = htk_seg.nuclear.max_clustering( im_log, im_nuclei_fgnd_mask, 10) # filter out small objects im_nuclei_seg_mask = htk_seg.label.area_open( im_nuclei_seg_mask, 80).astype(np.uint8) # perform connected component analysis obj_props = skimage.measure.regionprops(im_nuclei_seg_mask) num_nuclei = len(obj_props) # check if segmentation mask matches ground truth gtruth_mask_file = os.path.join(TEST_DATA_DIR, 'Easy1_nuclei_seg_kofahi_adaptive.npy') im_gtruth_mask = np.load(gtruth_mask_file) obj_props_gtruth = skimage.measure.regionprops(im_gtruth_mask) num_nuclei_gtruth = len(obj_props_gtruth) assert(num_nuclei == num_nuclei_gtruth) np.testing.assert_allclose(im_nuclei_seg_mask, im_gtruth_mask)
def main(args): # # Read Input Image # print('>> Reading input image') imInput = skimage.io.imread(args.inputImageFile)[:, :, :3] # # Perform color normalization # print('>> Performing color normalization') # compute mean and stddev of input in LAB color space Mu, Sigma = htk_color_conversion.lab_mean_std(imInput) # perform reinhard normalization imNmzd = htk_color_normalization.reinhard(imInput, Mu, Sigma) # # Perform color deconvolution # print('>> Performing color deconvolution') stainColor_1 = stainColorMap[args.stain_1] stainColor_2 = stainColorMap[args.stain_2] stainColor_3 = stainColorMap[args.stain_3] W = np.array([stainColor_1, stainColor_2, stainColor_3]).T imDeconvolved = htk_color_deconvolution.ColorDeconvolution(imNmzd, W) imNucleiStain = imDeconvolved.Stains[::2, ::2, 0].astype(np.float) # # Perform nuclei segmentation # print('>> Performing nuclei segmentation') # segment foreground imFgndMask = sp.ndimage.morphology.binary_fill_holes( imNucleiStain < args.foreground_threshold) # run adaptive multi-scale LoG filter imLog = htk_shape_filters.clog(imNucleiStain, imFgndMask, sigma_min=args.min_radius * np.sqrt(2), sigma_max=args.max_radius * np.sqrt(2)) imNucleiSegMask, Seeds, Max = htk_seg.nuclear.max_clustering( imLog, imFgndMask, args.local_max_search_radius) # filter out small objects imNucleiSegMask = htk_seg.label.area_open( imNucleiSegMask, args.min_nucleus_area).astype(np.int) # # Perform feature extraction # print('>> Performing feature extraction') im_nuclei = imDeconvolved.Stains[::2, ::2, 0] if args.cytoplasm_features: im_cytoplasm = imDeconvolved.Stains[::2, ::2, 1] else: im_cytoplasm = None df = htk_features.ComputeNucleiFeatures( imNucleiSegMask, im_nuclei, im_cytoplasm, 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, ) # # Create HDF5 file # print('>> Writing HDF5 file') hdf = pd.HDFStore(args.outputFile) hdf.put('d1', df, format='table', data_columns=True) print '--- Object x Features = ', hdf['d1'].shape
def main(args): # # Read Input Image # print('>> Reading input image') im_input = skimage.io.imread(args.inputImageFile)[:, :, :3] # # Perform color normalization # print('>> Performing color normalization') # compute mean and stddev of input in LAB color space mu, sigma = htk_ccvt.lab_mean_std(im_input) # perform reinhard normalization im_nmzd = htk_cnorm.reinhard(im_input, mu, sigma) # # Perform color deconvolution # print('>> Performing color deconvolution') stain_color_1 = stain_color_map[args.stain_1] stain_color_2 = stain_color_map[args.stain_2] stain_color_3 = stain_color_map[args.stain_3] w = np.array([stain_color_1, stain_color_2, stain_color_3]).T im_stains = htk_cdeconv.color_deconvolution(im_nmzd, w).Stains im_nuclei_stain = im_stains[:, :, 0].astype(np.float) # # Perform nuclei segmentation # print('>> Performing nuclei segmentation') # segment foreground im_fgnd_mask = sp.ndimage.morphology.binary_fill_holes( im_nuclei_stain < args.foreground_threshold) # run adaptive multi-scale LoG filter im_log = htk_shape_filters.clog(im_nuclei_stain, im_fgnd_mask, sigma_min=args.min_radius * np.sqrt(2), sigma_max=args.max_radius * np.sqrt(2)) im_nuclei_seg_mask, seeds, max = htk_seg.nuclear.max_clustering( im_log, im_fgnd_mask, args.local_max_search_radius) # filter out small objects im_nuclei_seg_mask = htk_seg.label.area_open( im_nuclei_seg_mask, args.min_nucleus_area).astype(np.int) # # Perform feature extraction # print('>> Performing feature extraction') im_nuclei = im_stains[:, :, 0] if args.cytoplasm_features: im_cytoplasm = im_stains[:, :, 1] else: im_cytoplasm = None df = htk_features.ComputeNucleiFeatures( im_nuclei_seg_mask, im_nuclei, im_cytoplasm, 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, ) # # Create HDF5 file # print('>> Writing HDF5 file') hdf = pd.HDFStore(args.outputFile) hdf.put('d1', df, format='table', data_columns=True) print '--- Object x Features = ', hdf['d1'].shape