Source code for plugins.segmentation.geo_distance.geo_distance3D

# Copyright 2019 Diamond Light Source Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
.. module:: geo_distance_3D
   :platform: Unix
   :synopsis: Calculate geodesic distance transforms in 3D. \
Wraps the code for calculating geodesic distance transforms, can be a \
usefull tool for data segmentation with a proper seed initialisation.

.. moduleauthor:: Daniil Kazantsev <scientificsoftware@diamond.ac.uk>
"""

from savu.plugins.plugin import Plugin
from savu.plugins.driver.multi_threaded_plugin import MultiThreadedPlugin
from savu.plugins.utils import register_plugin

"""
Geodesic transformation of images can be implementated with two approaches: \
fast marching and raster scan. Fast marching is based on the iterative \
propagation of a pixel front with velocity F. Raster scan is based on  \
kernel operations that are sequentially applied over the image in multiple passes.\
In GeoS, the authors proposed to use a 3x3 kernel for forward and \
backward passes for efficient geodesic distance transform, which was used for  \
image segmentation. # https://github.com/taigw/geodesic_distance \
In order to make code work one need to specify valid coordinates to initialise the point\
(seed) from which the distances will be calculated.

lambda: weighting betwween 0.0 and 1.0
          if lambda==0.0, return spatial euclidean distance without considering gradient
          if lambda==1.0, the distance is based on gradient only without using spatial distance
"""
import GeodisTK
import numpy as np

[docs]@register_plugin class GeoDistance3d(Plugin, MultiThreadedPlugin): def __init__(self): super(GeoDistance3d, self).__init__("GeoDistance3d")
[docs] def setup(self): in_dataset, out_dataset = self.get_datasets() in_pData, out_pData = self.get_plugin_datasets() # If VOLUME_3D pattern doesn't exist then use "VOlUME_XZ" pattern with # all of voxel_y dimension as this is equivalent to one VOLUME_3D scan. getall = ['VOLUME_XZ', 'voxel_y'] in_pData[0].plugin_data_setup('VOLUME_3D', 'single', getall=getall) in_pData[1].plugin_data_setup('VOLUME_3D', 'single', getall=getall) # the mask initialisation out_dataset[0].create_dataset(in_dataset[0]) out_pData[0].plugin_data_setup('VOLUME_3D', 'single', getall=getall)
[docs] def pre_process(self): # extract given parameters self.lambda_par = self.parameters['lambda'] self.iterations = self.parameters['iterations']
[docs] def process_frames(self, data): input_temp = data[0] indices = np.where(np.isnan(input_temp)) input_temp[indices] = 0.0 spacing = [1.0, 1.0, 1.0] if (np.sum(data[1]) > 0): geoDist = GeodisTK.geodesic3d_raster_scan(input_temp, data[1], spacing, self.lambda_par, self.iterations) else: geoDist = np.float32(np.zeros(np.shape(data[0]))) return geoDist
[docs] def nInput_datasets(self): return 2
[docs] def nOutput_datasets(self): return 1