def main():
    # parse cmd arguments
    parser = getParser()
    parser.parse_args()
    args = getArguments(parser)
    
    # prepare logger
    logger = Logger.getInstance()
    if args.debug: logger.setLevel(logging.DEBUG)
    elif args.verbose: logger.setLevel(logging.INFO)
    
    # iterate over input images
    for image in args.images:
        
        # load image as float using ITK
        logger.info('Loading image {} as float using ITK...'.format(image))
        image_type = itk.Image[itk.F, 3]  # causes PyDev to complain -> ignore error warning
        reader = itk.ImageFileReader[image_type].New()
        reader.SetFileName(image)
        reader.Update()
            
        
        logger.debug(itku.getInformation(reader.GetOutput()))
        
        # build output image name
        image_watershed_name = args.folder + '/' + image.split('/')[-1][:-4] + '_watershed' + image.split('/')[-1][-4:]
        
        # check if output image exists
        if not args.force:
            if os.path.exists(image_watershed_name):
                logger.warning('The output image {} already exists. Skipping this input image.'.format(image_watershed_name))
                continue
                
        # prepare watershed
        # assign to watershed_source the image to be passed to the watershed
        watershed_source = reader.GetOutput()
        # extract data from original image to scipy
        itk_py_converter_orig = itk.PyBuffer[image_type]  # causes PyDev to complain -> ignore error warning
        original_image_array = itk_py_converter_orig.GetArrayFromImage(reader.GetOutput())        
        # recover input image dimensions
        rs = original_image_array.shape
        # create empty final label image array
        image_label_final_array = scipy.zeros(rs[0] * rs[1] * rs[2], dtype=scipy.int32).reshape(rs) #!TODO: Is 32bit enough?
        # create an empty watershed result array
        watershed_result_array = scipy.zeros_like(image_label_final_array)
        # create initial label mask covering the whole image space
        label_mask = scipy.zeros(rs[0] * rs[1] * rs[2], dtype=scipy.bool_).reshape(rs)
        label_mask.fill(True)
        # set threhold to use
        threshold = __INITIAL_THRESHOLD
        # set the point to the largest region to process
        region_pointer = -1

        
        # apply the watershed
        logger.info('Applying watershed...')
        
        while True:
            # initialize the watershed filter object
            logger.info('Watershedding with settings: thr={} / level={}...'.format(threshold, 0.0))
            image_watershed = itk.WatershedImageFilter[image_type].New()
            image_watershed.SetInput(watershed_source)
            image_watershed.SetThreshold(threshold)
            image_watershed.SetLevel(0.0)
            
            try:
                image_watershed.Update()
                
                logger.debug(itku.getInformation(image_watershed.GetOutput()))
            
                logger.info('Adding resulting labels to final result image...')
                # converting to scipy
                itk_py_converter_ws = itk.PyBuffer[itku.getImageType(image_watershed.GetOutput())]  # causes PyDev to complain -> ignore error warning
                watershed_result_array = itk_py_converter_ws.GetArrayFromImage(image_watershed.GetOutput())
                # recovering current offset for the new label ids
                min_label_id = image_label_final_array.max()
                # updating final label image
                image_label_final_array[label_mask] = watershed_result_array[label_mask] + min_label_id
                
                logger.info('Last watershed led to {} new labels, {} in total now...'.format(len(scipy.unique(watershed_result_array)) - 1, len(scipy.unique(image_label_final_array))))
                
    #            # lower the threshold if no new labels were created, or skip label if a threshold of 0 did not help
                if 100 >= len(scipy.unique(watershed_result_array)) - 1:
                    if 0 == threshold:
                        region_pointer -= 1
                        logger.info('Skipping this region as threshold lowering did not lead to the production of more than 100 labels...')
                    else:
                        threshold = threshold / 2.
                        if threshold < 0.001: threshold = 0.0
                        logger.info('Lowering threshold for next region to {} ...'.format(threshold))
                else:
                    threshold = __INITIAL_THRESHOLD
                    logger.info('Resetting threshold to original value of {} ...'.format(__INITIAL_THRESHOLD))
                    
            except RuntimeError as error:
                if 0 == threshold:
                    region_pointer -= 1
                    logger.warning('Watershed processing terminated with error {}. Skipping this region as threshold lowering did not succeed.'.format(error))
                else:
                    threshold = threshold / 2
                    if threshold < 0.001: threshold = 0.0
                    logger.warning('Watershed processing terminated with error {}. Lowering threshold to {}.'.format(error, threshold))
            
                        
            logger.info('Computing statistics / checking stop condition...')
            statistics = LabelImageStatistics(image_label_final_array, original_image_array)
            
            # check medium region size and if stop condition reached, break
            sizes = sorted(statistics.get_sizes().iteritems(), key=lambda x: x[1]) # get sizes sorted (biggest region last)
            if __IDEAL_REGION_SIZE >= sizes[region_pointer][1]:
                logger.info('Stopping condition {} with a maximum region size of {} reached: Stopping processing...'.format(__IDEAL_REGION_SIZE, sizes[region_pointer][1]))
                break
#            if __IDEAL_REGION_SIZE >= sum(map(lambda x: x[1], sizes)) / float(len(sizes)):
#                logger.info('Stopping condition {} with a medium region size of {} reached: Stopping processing...'.format(__IDEAL_REGION_SIZE, sum(map(lambda x: x[1], sizes)) / float(len(sizes))))
#                break
                
            logger.info('Stopping condition {} with a maximum region size of {} not reached: Preparing next run...'.format(__IDEAL_REGION_SIZE, sizes[region_pointer][1]))
#            logger.info('Stopping condition {} with a medium region size of {} not reached: Preparing next run...'.format(__IDEAL_REGION_SIZE, sum(map(lambda x: x[1], sizes)) / float(len(sizes))))
            
            logger.info('Biggest region scheduled for breaking up: {} with {} voxels and intensity distribution score of {}...'.format(sizes[region_pointer][0], sizes[region_pointer][1], statistics.get_intensity_distributions()[sizes[region_pointer][0]]))
            # update label mask to cover the biggest label
            label_mask = (sizes[region_pointer][0] == image_label_final_array)
                
            # create the new input for the watershed algorithm
            watershed_source_array = scipy.zeros_like(original_image_array)
            watershed_source_array[label_mask] = original_image_array[label_mask]
            #watershed_source_array[scipy.invert(label_mask)] = watershed_source_array[label_mask].max() + 1 #!TODO: Not sure if this works, as I have the gradient image! High value = high gradient!?
            
            # cast to ITK image to apply watershed in the next step            
            watershed_source = itk_py_converter_orig.GetImageFromArray(watershed_source_array.tolist())

            logger.debug(itku.getInformation(watershed_source))
            
        # cast to ITK image to save (uses the watershed converter)
        image_label_final = itk_py_converter_ws.GetImageFromArray(image_label_final_array.tolist())

        logger.debug(itku.getInformation(image_label_final))

        logger.info('Overall skipped regions: {}...'.format(-1 * region_pointer - 1))

        # save file
        logger.info('Saving watershed image as {}...'.format(image_watershed_name))
        watershed_image_type = itku.getImageType(image_watershed.GetOutput())
        writer = itk.ImageFileWriter[watershed_image_type].New()
        writer.SetFileName(image_watershed_name)
        writer.SetInput(image_label_final)
        writer.Update()
    
    logger.info('Successfully terminated.')
Beispiel #2
0
def main():
    # parse cmd arguments
    parser = getParser()
    parser.parse_args()
    args = getArguments(parser)
    
    # prepare logger
    logger = Logger.getInstance()
    if args.debug: logger.setLevel(logging.DEBUG)
    elif args.verbose: logger.setLevel(logging.INFO)
    
    # iterate over input images
    for image in args.images:
        
        # load image as float using ITK
        logger.info('Loading image {} as float using ITK...'.format(image))
        image_type = itk.Image[itk.F, 3]
        reader = itk.ImageFileReader[image_type].New()
        reader.SetFileName(image)
        reader.Update()
        
        logger.debug(itku.getInformation(reader.GetOutput()))
        
        # compute ideal parameters
        rs = reader.GetOutput().GetLargestPossibleRegion().GetSize()
        threshold = underfit(rs.GetElement(0) * rs.GetElement(1) * rs.GetElement(2))
        level = 0
        logger.debug('{}, {}, {}'.format(rs.GetElement(0), rs.GetElement(1), rs.GetElement(2)))
        logger.debug('The image contains {} voxels, the resulting threshold is {}.'.format(rs.GetElement(0) * rs.GetElement(1) * rs.GetElement(2), threshold))
        
        # build output image name
        image_watershed_name = args.folder + '/' + image.split('/')[-1][:-4] + '_watershed'
        image_watershed_name += '_thr{}_lvl{}'.format(threshold, level)
        image_watershed_name += image.split('/')[-1][-4:]
        
        # check if output image exists
        if not args.force:
            if os.path.exists(image_watershed_name):
                logger.warning('The output image {} already exists. Skipping this step.'.format(image_watershed_name))
                continue
        
        # initialize the watershed filter object
        image_watershed = itk.WatershedImageFilter[image_type].New()
        image_watershed.SetInput(reader.GetOutput())
        image_watershed.SetThreshold(threshold)
        image_watershed.SetLevel(level)
        
        logger.info('Watershedding with settings: thr={} / level={}...'.format(threshold, level))
        image_watershed.Update()
        
        logger.debug(itku.getInformation(image_watershed.GetOutput()))
        
        # save file
        logger.info('Saving watershed image as {}...'.format(image_watershed_name))
        watershed_image_type = itku.getImageType(image_watershed.GetOutput())
        writer = itk.ImageFileWriter[watershed_image_type].New()
        writer.SetFileName(image_watershed_name)
        writer.SetInput(image_watershed.GetOutput())
        writer.Update()
                
    logger.info('Successfully terminated.')
def main():
    # parse cmd arguments
    parser = getParser()
    parser.parse_args()
    args = getArguments(parser)
    
    # prepare logger
    logger = Logger.getInstance()
    if args.debug: logger.setLevel(logging.DEBUG)
    elif args.verbose: logger.setLevel(logging.INFO)
    
    # iterate over input images
    for image in args.images:
        
        # load image as float using ITK
        logger.info('Loading image {} as float using ITK...'.format(image))
        image_type = itk.Image[itk.F, 3]
        reader = itk.ImageFileReader[image_type].New()
        reader.SetFileName(image)
        reader.Update()
        
        logger.debug(itku.getInformation(reader.GetOutput()))
        
        # compute ideal parameters
        rs = reader.GetOutput().GetLargestPossibleRegion().GetSize()
        threshold = underfit(rs.GetElement(0) * rs.GetElement(1) * rs.GetElement(2))
        level = 0
        logger.debug('{}, {}, {}'.format(rs.GetElement(0), rs.GetElement(1), rs.GetElement(2)))
        logger.debug('The image contains {} voxels, the resulting threshold is {}.'.format(rs.GetElement(0) * rs.GetElement(1) * rs.GetElement(2), threshold))
        
        # build output image name
        image_watershed_name = args.folder + '/' + image.split('/')[-1][:-4] + '_watershed'
        image_watershed_name += '_thr{}_lvl{}'.format(threshold, level)
        image_watershed_name += image.split('/')[-1][-4:]
        
        # check if output image exists
        if not args.force:
            if os.path.exists(image_watershed_name):
                logger.warning('The output image {} already exists. Skipping this step.'.format(image_watershed_name))
                continue
        
        # initialize the watershed filter object
        image_watershed = itk.WatershedImageFilter[image_type].New()
        image_watershed.SetInput(reader.GetOutput())
        image_watershed.SetThreshold(threshold)
        image_watershed.SetLevel(level)
        
        logger.info('Watershedding with settings: thr={} / level={}...'.format(threshold, level))
        image_watershed.Update()
        
        logger.debug(itku.getInformation(image_watershed.GetOutput()))
        
        # save file
        logger.info('Saving watershed image as {}...'.format(image_watershed_name))
        watershed_image_type = itku.getImageType(image_watershed.GetOutput())
        writer = itk.ImageFileWriter[watershed_image_type].New()
        writer.SetFileName(image_watershed_name)
        writer.SetInput(image_watershed.GetOutput())
        writer.Update()
                
    logger.info('Successfully terminated.')