def __init__(self, images: ImageData, **prediction_config) -> None: """ Parameters ---------- images : labelCollect.ImageData ImageData-object that contains data regarding one microscopy image that will be used for prediction prediction_config : dict Is used to update PredictObjects.default_config to change prediction settings. """ self.name = images.name self.image = images.image self.label_paths = images.label_paths config = deepcopy(PredictObjects.default_config) config.update({key: value for key, value in prediction_config.items()}) self.config = config if self.config.get( 'memory_limit') is not None and gputools_available(): mem_limit = self.config.get('memory_limit') limit_gpu_memory(mem_limit[1], allow_growth=False, total_memory=mem_limit[0]) # Create list of model/channel pairs to use if isinstance(self.config.get("sd_models"), tuple) and isinstance( self.config.get("prediction_chs"), tuple): self.model_list = [ *zip(self.config.get("sd_models"), self.config.get("prediction_chs")) ] else: self.model_list = [(self.config.get("sd_models"), self.config.get("prediction_chs"))]
def train_model(x_train, y_train, x_val, y_val, save_path, patch_size, anisotropy, n_rays=96): rays = Rays_GoldenSpiral(n_rays, anisotropy=anisotropy) # make the model config # copied from the stardist training notebook, this is a very weird line ... use_gpu = False and gputools_available() # predict on subsampled image for increased efficiency grid = tuple(1 if a > 1.5 else 2 for a in anisotropy) config = Config3D(rays=rays, grid=grid, use_gpu=use_gpu, n_channel_in=1, train_patch_size=patch_size, anisotropy=anisotropy) if use_gpu: print("Using a GPU for training") # limit gpu memory from csbdeep.utils.tf import limit_gpu_memory limit_gpu_memory(0.8) else: print("GPU not found, using the CPU for training") save_root, save_name = os.path.split(save_path) os.makedirs(save_root, exist_ok=True) model = StarDist3D(config, name=save_name, basedir=save_root) model.train(x_train, y_train, validation_data=(x_val, y_val), augmenter=augmenter) optimal_parameters = model.optimize_thresholds(x_val, y_val) return optimal_parameters
from keras.preprocessing.image import ImageDataGenerator import numpy as np import matplotlib.pyplot as plt from tifffile import imread import os from tqdm import tqdm_notebook as tqdm from csbdeep.utils.tf import limit_gpu_memory from csbdeep.utils import plot_some, plot_history from csbdeep.data import RawData, create_patches from csbdeep.io import load_training_data from nets import unet limit_gpu_memory(fraction=1 / 2) base_dir = '/mnt/AE3205C73205958D/Data/3dliver_local/pc_adult/2d_slices/imagesXY/images_full/' #train_dir = os.path.join(base_dir, 'trainingImages_512x512/') train_dir = os.path.join(base_dir, 'trainImages') #validation_dir = os.path.join(base_dir, 'trainingLabels_512x512/') label_dir = os.path.join(base_dir, 'trainLabels') #test_dir = os.path.join(base_dir, 'testImages_512x512') #print(train_dir) imgList = os.listdir(train_dir) labelList = os.listdir(label_dir) imgArray = [] for image in tqdm(imgList, 'Reading img'): imgArray.append(imread(os.path.join(train_dir, image)))
def _limit_tf_gpu_memory(): from csbdeep.utils.tf import IS_TF_1, limit_gpu_memory limit_gpu_memory(0.75, total_memory=(None if IS_TF_1 else 8000))
def main(): if not ('__file__' in locals() or '__file__' in globals()): print('running interactively, exiting.') sys.exit(0) # parse arguments parser, args = parse_args() args_dict = vars(args) # exit and show help if no arguments provided at all if len(sys.argv) == 1: parser.print_help() sys.exit(0) # check for required arguments manually (because of argparse issue) required = ('--input-dir', '--input-axes', '--norm-pmin', '--norm-pmax', '--model-basedir', '--model-name', '--output-dir') for r in required: dest = r[2:].replace('-', '_') if args_dict[dest] is None: parser.print_usage(file=sys.stderr) print("%s: error: the following arguments are required: %s" % (parser.prog, r), file=sys.stderr) sys.exit(1) # show effective arguments (including defaults) if not args.quiet: print('Arguments') print('---------') pprint(args_dict) print() sys.stdout.flush() # logging function log = (lambda *a, **k: None) if args.quiet else tqdm.write # get list of input files and exit if there are none file_list = list(Path(args.input_dir).glob(args.input_pattern)) if len(file_list) == 0: log("No files to process in '%s' with pattern '%s'." % (args.input_dir, args.input_pattern)) sys.exit(0) # delay imports after checking to all required arguments are provided from tifffile import imread, imsave from csbdeep.utils.tf import keras_import K = keras_import('backend') from csbdeep.models import CARE from csbdeep.data import PercentileNormalizer sys.stdout.flush() sys.stderr.flush() # limit gpu memory if args.gpu_memory_limit is not None: from csbdeep.utils.tf import limit_gpu_memory limit_gpu_memory(args.gpu_memory_limit) # create CARE model and load weights, create normalizer K.clear_session() model = CARE(config=None, name=args.model_name, basedir=args.model_basedir) if args.model_weights is not None: print("Loading network weights from '%s'." % args.model_weights) model.load_weights(args.model_weights) normalizer = PercentileNormalizer(pmin=args.norm_pmin, pmax=args.norm_pmax, do_after=args.norm_undo) n_tiles = args.n_tiles if n_tiles is not None and len(n_tiles) == 1: n_tiles = n_tiles[0] processed = [] # process all files for file_in in tqdm(file_list, disable=args.quiet or (n_tiles is not None and np.prod(n_tiles) > 1)): # construct output file name file_out = Path(args.output_dir) / args.output_name.format( file_path=str(file_in.relative_to(args.input_dir).parent), file_name=file_in.stem, file_ext=file_in.suffix, model_name=args.model_name, model_weights=Path(args.model_weights).stem if args.model_weights is not None else None) # checks (file_in.suffix.lower() in ('.tif', '.tiff') and file_out.suffix.lower() in ('.tif', '.tiff')) or _raise( ValueError('only tiff files supported.')) # load and predict restored image img = imread(str(file_in)) restored = model.predict(img, axes=args.input_axes, normalizer=normalizer, n_tiles=n_tiles) # restored image could be multi-channel even if input image is not axes_out = axes_check_and_normalize(args.input_axes) if restored.ndim > img.ndim: assert restored.ndim == img.ndim + 1 assert 'C' not in axes_out axes_out += 'C' # convert data type (if necessary) restored = restored.astype(np.dtype(args.output_dtype), copy=False) # save to disk if not args.dry_run: file_out.parent.mkdir(parents=True, exist_ok=True) if args.imagej_tiff: save_tiff_imagej_compatible(str(file_out), restored, axes_out) else: imsave(str(file_out), restored) processed.append((file_in, file_out)) # print summary of processed files if not args.quiet: sys.stdout.flush() sys.stderr.flush() n_processed = len(processed) len_processed = len(str(n_processed)) log('Finished processing %d %s' % (n_processed, 'files' if n_processed > 1 else 'file')) log('-' * (26 + len_processed if n_processed > 1 else 26)) for i, (file_in, file_out) in enumerate(processed): len_file = max(len(str(file_in)), len(str(file_out))) log(('{:>%d}. in : {:>%d}' % (len_processed, len_file)).format( 1 + i, str(file_in))) log(('{:>%d} out: {:>%d}' % (len_processed, len_file)).format( '', str(file_out)))
faulthandler.enable() import sys import tensorflow as tf from tensorflow import keras as ks import keras.backend as K import os import numpy as np from models import build_model from csbdeep.utils.tf import limit_gpu_memory from skimage.measure import compare_psnr from datawrapper import make_sequence, experimental_images limit_gpu_memory(fraction=0.75, allow_growth=False) #run_opts = tf.RunOptions(report_tensor_allocations_upon_oom = True) ##### architecture ######## architecture = ['time CNN'][0] image_size = [256, 256] batch_size = 8 timepoints = 11 timeinterval = [ 1 ] # can be used as an data augmentation to generate training dataset with various movements signallevel = [s for s in range(10, 100, 10)] gaussnoise = [s for s in np.linspace(0.5, 5, 10)] offset = 100
grid = args.grid conf = Config2D ( n_rays = n_rays, grid = grid, use_gpu = use_gpu, n_channel_in = n_channel, ) print(conf) vars(conf) if use_gpu: from csbdeep.utils.tf import limit_gpu_memory # adjust as necessary: limit GPU memory to be used by TensorFlow to leave some to OpenCL-based computations limit_gpu_memory(args.limit_gpu_mem) model = StarDist2D(conf, name=args.model_name, basedir=args.model_dir) median_size = calculate_extents(list(Y), np.median) fov = np.array(model._axes_tile_overlap('YX')) if any(median_size > fov): print("WARNING: median object size larger than field of view of the neural network.") augmenter = None
def run_StarDist( inputImagePath, z_count, t_count, model_selection, probThreshold, nmsThreshold, normalizationLow, normalizationHigh, output_type, resultPath): print('------------------------------------------') print(' StarDist Virtual Environment') print('------------------------------------------') print(f' inputImagePath = {inputImagePath}') print(f' z_count = {z_count}') print(f' t_count = {t_count}') print(f' model_selection = {model_selection}') print(f' probThreshold = {probThreshold}') print(f' nmsThreshold = {nmsThreshold}') print(f' normalizationLow = {normalizationLow}') print(f'normalizationHigh = {normalizationHigh}') print(f' outputType = {output_type}') print(f' resultPath = {resultPath}') # Limit GPU memory usage limit_gpu_memory(fraction=None, allow_growth=True) # Get the path of the folder that contains this python script script_folder = pathlib.Path(__file__).resolve().parent logger.info(f'Script Folder = {script_folder}') # Get the model selections model_dict = {0: '2D_demo', 1: '2D_fluor_nuc', 2: '2D_dsb2018', 3: '3D_demo'} if model_selection not in model_dict: logger.warn('Selection is not available, use 2D_demo instead') model_name = model_dict[model_selection] # Load StarDist model assuming the 3D_demo and 2D_demo folders # are both in `script_folder` if z_count > 1: # input image is 3D or 3D+T logger.warn('Input is a 3D/3D+T image, use 3D_demo model') # Use 3D model for 3D image model = StarDist3D(None, name='3D_demo', basedir=script_folder) # Set 3D block size tile_shape = (50, 256, 256) # Check if input is a time-lapse image if t_count > 1: axes = 'YXZT' else: axes = 'YXZ' elif z_count == 1: # Use 2D model for 2D image model = StarDist2D(None, name=model_name, basedir=script_folder) # Set 2D tile size tile_shape = (512, 512) # Check if input is a time-lapse image if t_count > 1: axes = 'TYX' else: axes = 'YX' else: raise ValueError('Z count must be positive') # Load input image image = tifffile.imread(inputImagePath) dtype = image.dtype # Current limitation: input and output should have the same depth if dtype == np.uint8: logger.warn('Label image will be saved in 8bit') # Not a time-lapse if t_count == 1: image = image[np.newaxis] # Create output labeled image labels = np.empty_like(image, dtype=dtype) n_tiles = [i // t + 1 for t, i in zip(tile_shape, image[0].shape)] # Get thresholds prob_thresh = np.clip(probThreshold, 0.0, 1.0) nms_thresh = np.clip(nmsThreshold, 0.0, 1.0) # Use default thresholds optimized for the StarDist model when both # thresholds are set as 0 if prob_thresh == 0.0 and nms_thresh == 0.0: logger.warn( 'Use default thresholds of the StarDist model when both ' 'thresholds are set as 0.') prob_thresh = nms_thresh = None logger.info(f'probThreshold = {prob_thresh}, nmsThreshold = {nms_thresh}') # Get Normalization Percentile p_min = np.clip(normalizationLow, 0.0, 100.0) p_max = np.clip(normalizationHigh, 0.0, 100.0) # Use default normalization for the StarDist model when p_min >= p_max if p_min >= p_max: logger.warn( 'Use default normalization of the StarDist model ' 'when p_min >= p_max.') p_min, p_max = 2, 99.9 logger.info(f'normalizationLow = {p_min}, normalizationHigh = {p_max}') # Apply StarDist model for t in range(t_count): labels[t] = model.predict_instances( normalize(image[t], p_min=p_min, p_max=p_max), prob_thresh=prob_thresh, nms_thresh=nms_thresh, n_tiles=n_tiles, show_tile_progress=False)[0].astype(dtype) # Convert labeled mask to binary mask if (output_type == 1): # Add two pixel gap between neighboring masks if (z_count > 1): addOnePixelGap_3D(labels[t]) else: addOnePixelGap_2D(labels[t]) # Convert to binary mask val = 255 if (labels[t].dtype.type == np.uint16): val = 65535 labels[t] = (labels[t] > 0) * val # Not a time-lapse if t_count == 1: labels = labels[0] # Save the labeled image tifffile.imwrite(resultPath, labels, photometric='minisblack', metadata={'axes': axes})