def test_clog(self): im_nuclei_stain = np.load( os.path.join(TEST_DATA_DIR, 'Easy1_nuclei_stain.npy')) im_nuclei_fgnd_mask = np.load( os.path.join(TEST_DATA_DIR, 'Easy1_nuclei_fgnd_mask.npy')) sigma_min = 10.0 / np.sqrt(2.0) sigma_max = 40.0 / np.sqrt(2.0) im_log_max, im_sigma_max = clog(im_nuclei_stain, im_nuclei_fgnd_mask, sigma_min, sigma_max) im_log_max_gtruth = np.load( os.path.join(TEST_DATA_DIR, 'Easy1_clog_max.npy')) np.testing.assert_array_almost_equal(im_log_max.astype('float16'), im_log_max_gtruth, decimal=4) im_sigma_max_gtruth = np.load( os.path.join(TEST_DATA_DIR, 'Easy1_clog_sigma_max.npy')) np.testing.assert_array_almost_equal(im_sigma_max.astype(np.float16), im_sigma_max_gtruth, decimal=4)
def test_clog(self): im_nuclei_stain_data = np.load( os.path.join(TEST_DATA_DIR, 'Easy1_nuclei_stain.npz')) im_nuclei_stain = im_nuclei_stain_data['Easy1_nuclei_stain'] im_nuclei_fgnd_mask_data = np.load( os.path.join(TEST_DATA_DIR, 'Easy1_nuclei_fgnd_mask.npz')) im_nuclei_fgnd_mask = im_nuclei_fgnd_mask_data[ 'Easy1_nuclei_fgnd_mask'] sigma_min = 10.0 / np.sqrt(2.0) sigma_max = 40.0 / np.sqrt(2.0) im_log_max, im_sigma_max = clog(im_nuclei_stain, im_nuclei_fgnd_mask, sigma_min, sigma_max) im_log_max_gtruth_data = np.load( os.path.join(TEST_DATA_DIR, 'Easy1_clog_max.npz')) im_log_max_gtruth = im_log_max_gtruth_data['Easy1_clog_max'] assert_array_almost_equal_neighborhood_lines(im_log_max, im_log_max_gtruth, decimal=4) compare_maxima(im_log_max, im_log_max_gtruth) im_sigma_max_gtruth_data = np.load( os.path.join(TEST_DATA_DIR, 'Easy1_clog_sigma_max.npz')) im_sigma_max_gtruth = im_sigma_max_gtruth_data['Easy1_clog_sigma_max'] assert_array_almost_equal_neighborhood_lines(im_sigma_max, im_sigma_max_gtruth, decimal=4)
def test_clog(self): im_nuclei_stain_data = np.load( utilities.externaldata('data/Easy1_nuclei_stain.npz.sha512')) im_nuclei_stain = im_nuclei_stain_data['Easy1_nuclei_stain'] im_nuclei_fgnd_mask_data = np.load( utilities.externaldata('data/Easy1_nuclei_fgnd_mask.npz.sha512')) im_nuclei_fgnd_mask = im_nuclei_fgnd_mask_data['Easy1_nuclei_fgnd_mask'] sigma_min = 10.0 / np.sqrt(2.0) sigma_max = 40.0 / np.sqrt(2.0) im_log_max, im_sigma_max = clog( im_input=im_nuclei_stain, im_mask=im_nuclei_fgnd_mask, sigma_min=sigma_min, sigma_max=sigma_max) im_log_max_gtruth_data = np.load(os.path.join(utilities.externaldata( 'data/Easy1_clog_max.npz.sha512'))) im_log_max_gtruth = im_log_max_gtruth_data['Easy1_clog_max'] assert_array_almost_equal_neighborhood_lines(im_log_max, im_log_max_gtruth, decimal=4) compare_maxima(im_log_max, im_log_max_gtruth) im_sigma_max_gtruth_data = np.load(os.path.join(utilities.externaldata( 'data/Easy1_clog_sigma_max.npz.sha512'))) im_sigma_max_gtruth = im_sigma_max_gtruth_data['Easy1_clog_sigma_max'] assert_array_almost_equal_neighborhood_lines(im_sigma_max, im_sigma_max_gtruth, decimal=4)
def detect_nuclei_kofahi(im_input, args): # perform color normalization im_nmzd = htk_cnorm.reinhard(im_input, args.reference_mu_lab, args.reference_std_lab) # perform color decovolution w = np.array([ stain_color_map[args.stain_1], stain_color_map[args.stain_2], stain_color_map[args.stain_3] ]).T im_stains = htk_cdeconv.color_deconvolution(im_nmzd, w).Stains im_nuclei_stain = im_stains[:, :, 0].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 < args.foreground_threshold) # run adaptive multi-scale LoG filter im_log = htk_shape_filters.clog(im_nuclei_stain, im_nuclei_fgnd_mask, sigma_min=args.min_radius * np.sqrt(2), sigma_max=args.max_radius * np.sqrt(2)) # apply local maximum clustering im_nuclei_seg_mask, seeds, max = htk_seg.nuclear.max_clustering( im_log, im_nuclei_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) return im_nuclei_seg_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[:, :, 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_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