def test_Intensity_1(self): """Test a case of distributed intensity values.""" # Create label image with only one region label_image = scipy.zeros(2*2*2, dtype=scipy.int8).reshape(2,2,2) # Create original image with two equally distibuted intensity value original_image = scipy.zeros(2*2*2, dtype=scipy.int8) original_image[:4] = -1 original_image[4:] = 1 original_image = original_image.reshape(2,2,2) # Initialize object statistics = LabelImageStatistics(label_image, original_image) # Computed expected result i = scipy.array([-1,-1,-1,-1,1,1,1,1]) h = scipy.histogram(i, statistics._intensity_distribution_local_histogram_width) hr = scipy.array(h[0]) / float(h[0].sum()) g = stats.norm(*stats.norm.fit(i)) r = abs(hr - g.pdf(h[1][:-1])) r *= h[1][-2] - h[1][0] r = r.sum() # Check created intensity distribution intensity_distributions = statistics.get_intensity_distributions() self.assertEqual(len(intensity_distributions), 1) self.assertEqual(intensity_distributions[0], i.std()) intensity_distribution_histogram = statistics.get_intensity_distribution_histogram() self.assertEqual(intensity_distribution_histogram[0][statistics.get_intensity_distribution_histogram_width()/2], 1) self.assertEqual(intensity_distribution_histogram[0].max(), 1) self.assertEqual(intensity_distribution_histogram[0].min(), 0) self.assertEqual(intensity_distribution_histogram[1].mean(), i.std())
def test_Homogeneous(self): """Checks the return value for a homogeneous region.""" # Create label image with only one region label_image = scipy.zeros(2 * 2 * 2, dtype=scipy.int8).reshape(2, 2, 2) # Create original image with only one intensity value original_image = scipy.zeros(2 * 2 * 2, dtype=scipy.int8).reshape(2, 2, 2) # Initialize object statistics = LabelImageStatistics(label_image, original_image) # Check created intensity distribution intensity_distributions = statistics.get_intensity_distributions() self.assertEqual(len(intensity_distributions), 1) self.assertEqual(intensity_distributions[0], 0) intensity_distribution_histogram = statistics.get_intensity_distribution_histogram( ) self.assertEqual( len(intensity_distribution_histogram[0]), statistics.get_intensity_distribution_histogram_width()) self.assertEqual( len(intensity_distribution_histogram[1]), statistics.get_intensity_distribution_histogram_width() + 1) self.assertEqual( intensity_distribution_histogram[0] [statistics.get_intensity_distribution_histogram_width() / 2], 1) self.assertEqual(intensity_distribution_histogram[0].max(), 1) self.assertEqual(intensity_distribution_histogram[0].min(), 0)
def test_Equality(self): """Checks whether equally formed histograms in different intensity regions produce the same result.""" # Create random value for testing x = scipy.random.randint(10, 10000) # Create label image with only one region label_image = scipy.zeros(2 * 2 * 2, dtype=scipy.int8).reshape(2, 2, 2) # Create original images with two equally distributed intensity values original_image1 = scipy.zeros(2 * 2 * 2).reshape(2, 2, 2) original_image2 = scipy.zeros(2 * 2 * 2).reshape(2, 2, 2) original_image1[2:, :, :] = -x original_image1[:2, :, :] = 0 original_image2[2:, :, :] = 0 original_image2[:2, :, :] = x # Initialize objects statistics1 = LabelImageStatistics(label_image, original_image1) statistics2 = LabelImageStatistics(label_image, original_image2) # Check created intensity distribution to be different intensity_distributions1 = statistics1.get_intensity_distributions() intensity_distributions2 = statistics2.get_intensity_distributions() self.assertEqual(intensity_distributions1[0], intensity_distributions2[0])
def test_Homogeneous(self): """Checks the return value for a homogeneous region.""" # Create label image with only one region label_image = scipy.zeros(2*2*2, dtype=scipy.int8).reshape(2,2,2) # Create original image with only one intensity value original_image = scipy.zeros(2*2*2, dtype=scipy.int8).reshape(2,2,2) # Initialize object statistics = LabelImageStatistics(label_image, original_image) # Check created intensity distribution intensity_distributions = statistics.get_intensity_distributions() self.assertEqual(len(intensity_distributions), 1) self.assertEqual(intensity_distributions[0], 0) intensity_distribution_histogram = statistics.get_intensity_distribution_histogram() self.assertEqual(len(intensity_distribution_histogram[0]), statistics.get_intensity_distribution_histogram_width()) self.assertEqual(len(intensity_distribution_histogram[1]), statistics.get_intensity_distribution_histogram_width() + 1) self.assertEqual(intensity_distribution_histogram[0][statistics.get_intensity_distribution_histogram_width()/2], 1) self.assertEqual(intensity_distribution_histogram[0].max(), 1) self.assertEqual(intensity_distribution_histogram[0].min(), 0)
def test_Continuity(self): """Checks if the returned values are continuous for more spaced intensity values.""" # Create random value for testing x = scipy.random.randint(10, 10000) # Create label image with only one region label_image = scipy.zeros(2*2*2, dtype=scipy.int8).reshape(2,2,2) # Create original images with two equally distributed intensity values original_image1 = scipy.zeros(2*2*2).reshape(2,2,2) original_image2 = scipy.zeros(2*2*2).reshape(2,2,2) original_image1[1:,:,:] = x original_image2[1:,:,:] = 2*x # Initialize objects statistics1 = LabelImageStatistics(label_image, original_image1) statistics2 = LabelImageStatistics(label_image, original_image2) # Check created intensity distribution to be different intensity_distributions1 = statistics1.get_intensity_distributions() intensity_distributions2 = statistics2.get_intensity_distributions() self.assertGreater(intensity_distributions2[0], intensity_distributions1[0])
def test_Intensity_1(self): """Test a case of distributed intensity values.""" # Create label image with only one region label_image = scipy.zeros(2 * 2 * 2, dtype=scipy.int8).reshape(2, 2, 2) # Create original image with two equally distibuted intensity value original_image = scipy.zeros(2 * 2 * 2, dtype=scipy.int8) original_image[:4] = -1 original_image[4:] = 1 original_image = original_image.reshape(2, 2, 2) # Initialize object statistics = LabelImageStatistics(label_image, original_image) # Computed expected result i = scipy.array([-1, -1, -1, -1, 1, 1, 1, 1]) h = scipy.histogram( i, statistics._intensity_distribution_local_histogram_width) hr = scipy.array(h[0]) / float(h[0].sum()) g = stats.norm(*stats.norm.fit(i)) r = abs(hr - g.pdf(h[1][:-1])) r *= h[1][-2] - h[1][0] r = r.sum() # Check created intensity distribution intensity_distributions = statistics.get_intensity_distributions() self.assertEqual(len(intensity_distributions), 1) self.assertEqual(intensity_distributions[0], i.std()) intensity_distribution_histogram = statistics.get_intensity_distribution_histogram( ) self.assertEqual( intensity_distribution_histogram[0] [statistics.get_intensity_distribution_histogram_width() / 2], 1) self.assertEqual(intensity_distribution_histogram[0].max(), 1) self.assertEqual(intensity_distribution_histogram[0].min(), 0) self.assertEqual(intensity_distribution_histogram[1].mean(), i.std())
def test_Equality(self): """Checks whether equally formed histograms in different intensity regions produce the same result.""" # Create random value for testing x = scipy.random.randint(10, 10000) # Create label image with only one region label_image = scipy.zeros(2*2*2, dtype=scipy.int8).reshape(2,2,2) # Create original images with two equally distributed intensity values original_image1 = scipy.zeros(2*2*2).reshape(2,2,2) original_image2 = scipy.zeros(2*2*2).reshape(2,2,2) original_image1[2:,:,:] = -x original_image1[:2,:,:] = 0 original_image2[2:,:,:] = 0 original_image2[:2,:,:] = x # Initialize objects statistics1 = LabelImageStatistics(label_image, original_image1) statistics2 = LabelImageStatistics(label_image, original_image2) # Check created intensity distribution to be different intensity_distributions1 = statistics1.get_intensity_distributions() intensity_distributions2 = statistics2.get_intensity_distributions() self.assertEqual(intensity_distributions1[0], intensity_distributions2[0])
def test_Continuity(self): """Checks if the returned values are continuous for more spaced intensity values.""" # Create random value for testing x = scipy.random.randint(10, 10000) # Create label image with only one region label_image = scipy.zeros(2 * 2 * 2, dtype=scipy.int8).reshape(2, 2, 2) # Create original images with two equally distributed intensity values original_image1 = scipy.zeros(2 * 2 * 2).reshape(2, 2, 2) original_image2 = scipy.zeros(2 * 2 * 2).reshape(2, 2, 2) original_image1[1:, :, :] = x original_image2[1:, :, :] = 2 * x # Initialize objects statistics1 = LabelImageStatistics(label_image, original_image1) statistics2 = LabelImageStatistics(label_image, original_image2) # Check created intensity distribution to be different intensity_distributions1 = statistics1.get_intensity_distributions() intensity_distributions2 = statistics2.get_intensity_distributions() self.assertGreater(intensity_distributions2[0], intensity_distributions1[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] # 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.')
def test_Basic(self): """Test the case of a region with only one intensity value and some basic return values.""" # Create label image with only one region label_image = scipy.zeros(2*2*2, dtype=scipy.int8).reshape(2,2,2) # Create original image with only one intensity value original_image = scipy.zeros(2*2*2, dtype=scipy.int8).reshape(2,2,2) # Initialize object statistics = LabelImageStatistics(label_image, original_image) # Check created intensity distribution intensity_distributions = statistics.get_intensity_distributions() self.assertEqual(len(intensity_distributions), 1) self.assertEqual(intensity_distributions[0], 0) intensity_distribution_histogram = statistics.get_intensity_distribution_histogram() self.assertEqual(len(intensity_distribution_histogram[0]), statistics.get_intensity_distribution_histogram_width()) self.assertEqual(len(intensity_distribution_histogram[1]), statistics.get_intensity_distribution_histogram_width() + 1) self.assertEqual(intensity_distribution_histogram[0][statistics.get_intensity_distribution_histogram_width()/2], 1) self.assertEqual(intensity_distribution_histogram[0].max(), 1) self.assertEqual(intensity_distribution_histogram[0].min(), 0) # Check created size distribution sizes = statistics.get_sizes() self.assertEqual(len(sizes), 1) self.assertEqual(sizes[0], 2*2*2) sizes_histogram = statistics.get_size_histogram() self.assertEqual(len(sizes_histogram[0]), statistics.get_size_histogram_width()) self.assertEqual(len(sizes_histogram[1]), statistics.get_size_histogram_width() + 1) self.assertEqual(sizes_histogram[0][statistics.get_size_histogram_width()/2], 1) self.assertEqual(sizes_histogram[0].max(), 1) self.assertEqual(sizes_histogram[0].min(), 0) # Check other statistics values self.assertTrue(statistics.labels_are_consecutive()) self.assertEqual(statistics.get_min_intensity(), 0) self.assertEqual(statistics.get_max_intensity(), 0) self.assertEqual(statistics.get_min_label(), 0) self.assertEqual(statistics.get_max_label(), 0) self.assertEqual(statistics.get_label_count(), 1)
def test_Basic(self): """Test the case of a region with only one intensity value and some basic return values.""" # Create label image with only one region label_image = scipy.zeros(2 * 2 * 2, dtype=scipy.int8).reshape(2, 2, 2) # Create original image with only one intensity value original_image = scipy.zeros(2 * 2 * 2, dtype=scipy.int8).reshape(2, 2, 2) # Initialize object statistics = LabelImageStatistics(label_image, original_image) # Check created intensity distribution intensity_distributions = statistics.get_intensity_distributions() self.assertEqual(len(intensity_distributions), 1) self.assertEqual(intensity_distributions[0], 0) intensity_distribution_histogram = statistics.get_intensity_distribution_histogram( ) self.assertEqual( len(intensity_distribution_histogram[0]), statistics.get_intensity_distribution_histogram_width()) self.assertEqual( len(intensity_distribution_histogram[1]), statistics.get_intensity_distribution_histogram_width() + 1) self.assertEqual( intensity_distribution_histogram[0] [statistics.get_intensity_distribution_histogram_width() / 2], 1) self.assertEqual(intensity_distribution_histogram[0].max(), 1) self.assertEqual(intensity_distribution_histogram[0].min(), 0) # Check created size distribution sizes = statistics.get_sizes() self.assertEqual(len(sizes), 1) self.assertEqual(sizes[0], 2 * 2 * 2) sizes_histogram = statistics.get_size_histogram() self.assertEqual(len(sizes_histogram[0]), statistics.get_size_histogram_width()) self.assertEqual(len(sizes_histogram[1]), statistics.get_size_histogram_width() + 1) self.assertEqual( sizes_histogram[0][statistics.get_size_histogram_width() / 2], 1) self.assertEqual(sizes_histogram[0].max(), 1) self.assertEqual(sizes_histogram[0].min(), 0) # Check other statistics values self.assertTrue(statistics.labels_are_consecutive()) self.assertEqual(statistics.get_min_intensity(), 0) self.assertEqual(statistics.get_max_intensity(), 0) self.assertEqual(statistics.get_min_label(), 0) self.assertEqual(statistics.get_max_label(), 0) self.assertEqual(statistics.get_label_count(), 1)