SimpleITK  
SliceBySliceDecorator/SliceBySliceDecorator.py
1 #!/usr/bin/env python
2 # =========================================================================
3 #
4 # Copyright NumFOCUS
5 #
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
9 #
10 # http://www.apache.org/licenses/LICENSE-2.0.txt
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
17 #
18 # =========================================================================
19 
20 
21 import SimpleITK as sitk
22 import sys
23 
24 import itertools
25 from functools import wraps
26 
27 
28 def slice_by_slice_decorator(func):
29  """
30  A function decorator which executes func on each 3D sub-volume and
31  *in-place* pastes the results into the input image. The input image type
32  and the output image type are required to be the same type.
33 
34  :param func: A function which take a SimpleITK Image as it's first
35  argument and returns an Image as results.
36 
37  :return: A decorated function.
38  """
39 
40  iter_dim = 2
41 
42  @wraps(func)
43  def slice_by_slice(image, *args, **kwargs):
44 
45  dim = image.GetDimension()
46 
47  if dim <= iter_dim:
48  #
49  image = func(image, *args, **kwargs)
50  return image
51 
52  extract_size = list(image.GetSize())
53  extract_size[iter_dim:] = itertools.repeat(0, dim - iter_dim)
54 
55  extract_index = [0] * dim
56  paste_idx = [slice(None, None)] * dim
57 
58  extractor = sitk.ExtractImageFilter()
59  extractor.SetSize(extract_size)
60 
61  for high_idx in itertools.product(
62  *[range(s) for s in image.GetSize()[iter_dim:]]
63  ):
64 
65  # The lower 2 elements of extract_index are always 0.
66  # The remaining indices are iterated through all indexes.
67  extract_index[iter_dim:] = high_idx
68  extractor.SetIndex(extract_index)
69 
70  # Sliced based indexing for setting image values internally uses
71  # the PasteImageFilter executed "in place". The lower 2 elements
72  # are equivalent to ":". For a less general case the assignment
73  # could be written as image[:,:,z] = ...
74  paste_idx[iter_dim:] = high_idx
75  image[paste_idx] = func(extractor.Execute(image), *args, **kwargs)
76 
77  return image
78 
79  return slice_by_slice
80 
81 
82 if len(sys.argv) < 3:
83  print("Usage: SubDimensionProcess inputImage outputImage", file=sys.stderr)
84  sys.exit(1)
85 
86 inputImage = sitk.ReadImage(sys.argv[1])
87 
88 # Decorate the function
89 adaptive_histogram_equalization_2d = slice_by_slice_decorator(
90  sitk.AdaptiveHistogramEqualization
91 )
92 
93 adaptive_histogram_equalization_2d(inputImage, radius=[20] * 2, alpha=0.3, beta=0.3)
94 
95 sitk.WriteImage(inputImage, sys.argv[2])
itk::simple::ExtractImageFilter
Decrease the image size by cropping the image to the selected region bounds.
Definition: sitkExtractImageFilter.h:72
itk::simple::WriteImage
SITKIO_EXPORT void WriteImage(const Image &image, const std::vector< PathType > &fileNames, bool useCompression=false, int compressionLevel=-1)
WriteImage is a procedural interface to the ImageSeriesWriter. class which is convenient for many ima...
itk::simple::ReadImage
SITKIO_EXPORT Image ReadImage(const std::vector< PathType > &fileNames, PixelIDValueEnum outputPixelType=sitkUnknown, const std::string &imageIO="")
ReadImage is a procedural interface to the ImageSeriesReader class which is convenient for most image...