Medical Imaging Interaction Toolkit  2018.4.99-a3d2e8fb
Medical Imaging Interaction Toolkit
mitkMorphologicalOperations.cpp
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
14 #include <itkBinaryBallStructuringElement.h>
15 #include <itkBinaryCrossStructuringElement.h>
16 #include <itkBinaryDilateImageFilter.h>
17 #include <itkBinaryErodeImageFilter.h>
18 #include <itkBinaryFillholeImageFilter.h>
19 #include <itkBinaryMorphologicalClosingImageFilter.h>
20 #include <itkBinaryMorphologicalOpeningImageFilter.h>
21 #include <mitkImageAccessByItk.h>
22 #include <mitkImageCast.h>
23 #include <mitkImageReadAccessor.h>
24 #include <mitkImageTimeSelector.h>
25 
27  int factor,
29 {
30  MITK_INFO << "Start Closing...";
31 
32  auto timeSteps = static_cast<int>(image->GetTimeSteps());
33 
34  if (timeSteps > 1)
35  {
37  timeSelector->SetInput(image);
38 
39  for (int t = 0; t < timeSteps; ++t)
40  {
41  MITK_INFO << " Processing time step " << t;
42 
43  timeSelector->SetTimeNr(t);
44  timeSelector->Update();
45 
46  mitk::Image::Pointer img3D = timeSelector->GetOutput();
47  img3D->DisconnectPipeline();
48 
49  AccessByItk_3(img3D, itkClosing, img3D, factor, structuralElement);
50 
51  mitk::ImageReadAccessor accessor(img3D);
52  image->SetVolume(accessor.GetData(), t);
53  }
54  }
55  else
56  {
57  AccessByItk_3(image, itkClosing, image, factor, structuralElement);
58  }
59 
60  MITK_INFO << "Finished Closing";
61 }
62 
64  int factor,
66 {
67  MITK_INFO << "Start Erode...";
68 
69  auto timeSteps = static_cast<int>(image->GetTimeSteps());
70 
71  if (timeSteps > 1)
72  {
74  timeSelector->SetInput(image);
75 
76  for (int t = 0; t < timeSteps; ++t)
77  {
78  MITK_INFO << " Processing time step " << t;
79 
80  timeSelector->SetTimeNr(t);
81  timeSelector->Update();
82 
83  mitk::Image::Pointer img3D = timeSelector->GetOutput();
84  img3D->DisconnectPipeline();
85 
86  AccessByItk_3(img3D, itkErode, img3D, factor, structuralElement);
87 
88  mitk::ImageReadAccessor accessor(img3D);
89  image->SetVolume(accessor.GetData(), t);
90  }
91  }
92  else
93  {
94  AccessByItk_3(image, itkErode, image, factor, structuralElement);
95  }
96 
97  MITK_INFO << "Finished Erode";
98 }
99 
101  int factor,
103 {
104  MITK_INFO << "Start Dilate...";
105 
106  auto timeSteps = static_cast<int>(image->GetTimeSteps());
107 
108  if (timeSteps > 1)
109  {
111  timeSelector->SetInput(image);
112 
113  for (int t = 0; t < timeSteps; ++t)
114  {
115  MITK_INFO << " Processing time step " << t;
116 
117  timeSelector->SetTimeNr(t);
118  timeSelector->Update();
119 
120  mitk::Image::Pointer img3D = timeSelector->GetOutput();
121  img3D->DisconnectPipeline();
122 
123  AccessByItk_3(img3D, itkDilate, img3D, factor, structuralElement);
124 
125  mitk::ImageReadAccessor accessor(img3D);
126  image->SetVolume(accessor.GetData(), t);
127  }
128  }
129  else
130  {
131  AccessByItk_3(image, itkDilate, image, factor, structuralElement);
132  }
133 
134  MITK_INFO << "Finished Dilate";
135 }
136 
138  int factor,
140 {
141  MITK_INFO << "Start Opening...";
142 
143  auto timeSteps = static_cast<int>(image->GetTimeSteps());
144 
145  if (timeSteps > 1)
146  {
148  timeSelector->SetInput(image);
149 
150  for (int t = 0; t < timeSteps; ++t)
151  {
152  MITK_INFO << " Processing time step " << t;
153 
154  timeSelector->SetTimeNr(t);
155  timeSelector->Update();
156 
157  mitk::Image::Pointer img3D = timeSelector->GetOutput();
158  img3D->DisconnectPipeline();
159 
160  AccessByItk_3(img3D, itkOpening, img3D, factor, structuralElement);
161 
162  mitk::ImageReadAccessor accessor(img3D);
163  image->SetVolume(accessor.GetData(), t);
164  }
165  }
166  else
167  {
168  AccessByItk_3(image, itkOpening, image, factor, structuralElement);
169  }
170 
171  MITK_INFO << "Finished Opening";
172 }
173 
175 {
176  MITK_INFO << "Start FillHole...";
177 
178  auto timeSteps = static_cast<int>(image->GetTimeSteps());
179 
180  if (timeSteps > 1)
181  {
183  timeSelector->SetInput(image);
184 
185  for (int t = 0; t < timeSteps; ++t)
186  {
187  MITK_INFO << " Processing time step " << t;
188 
189  timeSelector->SetTimeNr(t);
190  timeSelector->Update();
191 
192  mitk::Image::Pointer img3D = timeSelector->GetOutput();
193  img3D->DisconnectPipeline();
194 
195  AccessByItk_1(img3D, itkFillHoles, img3D);
196 
197  mitk::ImageReadAccessor accessor(img3D);
198  image->SetVolume(accessor.GetData(), t);
199  }
200  }
201  else
202  {
203  AccessByItk_1(image, itkFillHoles, image);
204  }
205 
206  MITK_INFO << "Finished FillHole";
207 }
208 
209 template <typename TPixel, unsigned int VDimension>
210 void mitk::MorphologicalOperations::itkClosing(
211  itk::Image<TPixel, VDimension> *sourceImage,
212  mitk::Image::Pointer &resultImage,
213  int factor,
215 {
216  typedef itk::Image<TPixel, VDimension> ImageType;
217  typedef itk::BinaryBallStructuringElement<TPixel, VDimension> BallType;
218  typedef itk::BinaryCrossStructuringElement<TPixel, VDimension> CrossType;
219  typedef typename itk::BinaryMorphologicalClosingImageFilter<ImageType, ImageType, BallType> BallClosingFilterType;
220  typedef typename itk::BinaryMorphologicalClosingImageFilter<ImageType, ImageType, CrossType> CrossClosingFilterType;
221 
222  if (structuralElementFlags & (Ball_Axial | Ball_Coronal | Ball_Sagital))
223  {
224  BallType ball = CreateStructuringElement<BallType>(structuralElementFlags, factor);
225 
226  typename BallClosingFilterType::Pointer closingFilter = BallClosingFilterType::New();
227  closingFilter->SetKernel(ball);
228  closingFilter->SetInput(sourceImage);
229  closingFilter->SetForegroundValue(1);
230  closingFilter->UpdateLargestPossibleRegion();
231 
232  mitk::CastToMitkImage(closingFilter->GetOutput(), resultImage);
233  }
234  else
235  {
236  CrossType cross = CreateStructuringElement<CrossType>(structuralElementFlags, factor);
237 
238  typename CrossClosingFilterType::Pointer closingFilter = CrossClosingFilterType::New();
239  closingFilter->SetKernel(cross);
240  closingFilter->SetInput(sourceImage);
241  closingFilter->SetForegroundValue(1);
242  closingFilter->UpdateLargestPossibleRegion();
243 
244  mitk::CastToMitkImage(closingFilter->GetOutput(), resultImage);
245  }
246 }
247 
248 template <typename TPixel, unsigned int VDimension>
249 void mitk::MorphologicalOperations::itkErode(
250  itk::Image<TPixel, VDimension> *sourceImage,
251  mitk::Image::Pointer &resultImage,
252  int factor,
254 {
255  typedef itk::Image<TPixel, VDimension> ImageType;
256  typedef itk::BinaryBallStructuringElement<TPixel, VDimension> BallType;
257  typedef itk::BinaryCrossStructuringElement<TPixel, VDimension> CrossType;
258  typedef typename itk::BinaryErodeImageFilter<ImageType, ImageType, BallType> BallErodeFilterType;
259  typedef typename itk::BinaryErodeImageFilter<ImageType, ImageType, CrossType> CrossErodeFilterType;
260 
261  if (structuralElementFlags & (Ball_Axial | Ball_Coronal | Ball_Sagital))
262  {
263  BallType ball = CreateStructuringElement<BallType>(structuralElementFlags, factor);
264 
265  typename BallErodeFilterType::Pointer erodeFilter = BallErodeFilterType::New();
266  erodeFilter->SetKernel(ball);
267  erodeFilter->SetInput(sourceImage);
268  erodeFilter->SetErodeValue(1);
269  erodeFilter->UpdateLargestPossibleRegion();
270 
271  mitk::CastToMitkImage(erodeFilter->GetOutput(), resultImage);
272  }
273  else
274  {
275  CrossType cross = CreateStructuringElement<CrossType>(structuralElementFlags, factor);
276 
277  typename CrossErodeFilterType::Pointer erodeFilter = CrossErodeFilterType::New();
278  erodeFilter->SetKernel(cross);
279  erodeFilter->SetInput(sourceImage);
280  erodeFilter->SetErodeValue(1);
281  erodeFilter->UpdateLargestPossibleRegion();
282 
283  mitk::CastToMitkImage(erodeFilter->GetOutput(), resultImage);
284  }
285 }
286 
287 template <typename TPixel, unsigned int VDimension>
288 void mitk::MorphologicalOperations::itkDilate(
289  itk::Image<TPixel, VDimension> *sourceImage,
290  mitk::Image::Pointer &resultImage,
291  int factor,
293 {
294  typedef itk::Image<TPixel, VDimension> ImageType;
295  typedef itk::BinaryBallStructuringElement<TPixel, VDimension> BallType;
296  typedef itk::BinaryCrossStructuringElement<TPixel, VDimension> CrossType;
297  typedef typename itk::BinaryDilateImageFilter<ImageType, ImageType, BallType> BallDilateFilterType;
298  typedef typename itk::BinaryDilateImageFilter<ImageType, ImageType, CrossType> CrossDilateFilterType;
299 
300  if (structuralElementFlags & (Ball_Axial | Ball_Coronal | Ball_Sagital))
301  {
302  BallType ball = CreateStructuringElement<BallType>(structuralElementFlags, factor);
303 
304  typename BallDilateFilterType::Pointer dilateFilter = BallDilateFilterType::New();
305  dilateFilter->SetKernel(ball);
306  dilateFilter->SetInput(sourceImage);
307  dilateFilter->SetDilateValue(1);
308  dilateFilter->UpdateLargestPossibleRegion();
309 
310  mitk::CastToMitkImage(dilateFilter->GetOutput(), resultImage);
311  }
312  else
313  {
314  CrossType cross = CreateStructuringElement<CrossType>(structuralElementFlags, factor);
315 
316  typename CrossDilateFilterType::Pointer dilateFilter = CrossDilateFilterType::New();
317  dilateFilter->SetKernel(cross);
318  dilateFilter->SetInput(sourceImage);
319  dilateFilter->SetDilateValue(1);
320  dilateFilter->UpdateLargestPossibleRegion();
321 
322  mitk::CastToMitkImage(dilateFilter->GetOutput(), resultImage);
323  }
324 }
325 
326 template <typename TPixel, unsigned int VDimension>
327 void mitk::MorphologicalOperations::itkOpening(
328  itk::Image<TPixel, VDimension> *sourceImage,
329  mitk::Image::Pointer &resultImage,
330  int factor,
332 {
333  typedef itk::Image<TPixel, VDimension> ImageType;
334  typedef itk::BinaryBallStructuringElement<TPixel, VDimension> BallType;
335  typedef itk::BinaryCrossStructuringElement<TPixel, VDimension> CrossType;
336  typedef typename itk::BinaryMorphologicalOpeningImageFilter<ImageType, ImageType, BallType> BallOpeningFiltertype;
337  typedef typename itk::BinaryMorphologicalOpeningImageFilter<ImageType, ImageType, CrossType> CrossOpeningFiltertype;
338 
339  if (structuralElementFlags & (Ball_Axial | Ball_Coronal | Ball_Sagital))
340  {
341  BallType ball = CreateStructuringElement<BallType>(structuralElementFlags, factor);
342 
343  typename BallOpeningFiltertype::Pointer openingFilter = BallOpeningFiltertype::New();
344  openingFilter->SetKernel(ball);
345  openingFilter->SetInput(sourceImage);
346  openingFilter->SetForegroundValue(1);
347  openingFilter->SetBackgroundValue(0);
348  openingFilter->UpdateLargestPossibleRegion();
349 
350  mitk::CastToMitkImage(openingFilter->GetOutput(), resultImage);
351  }
352  else
353  {
354  CrossType cross = CreateStructuringElement<CrossType>(structuralElementFlags, factor);
355 
356  typename CrossOpeningFiltertype::Pointer openingFilter = CrossOpeningFiltertype::New();
357  openingFilter->SetKernel(cross);
358  openingFilter->SetInput(sourceImage);
359  openingFilter->SetForegroundValue(1);
360  openingFilter->SetBackgroundValue(0);
361  openingFilter->UpdateLargestPossibleRegion();
362 
363  mitk::CastToMitkImage(openingFilter->GetOutput(), resultImage);
364  }
365 }
366 
367 template <typename TPixel, unsigned int VDimension>
368 void mitk::MorphologicalOperations::itkFillHoles(itk::Image<TPixel, VDimension> *sourceImage,
369  mitk::Image::Pointer &resultImage)
370 {
371  typedef itk::Image<TPixel, VDimension> ImageType;
372  typedef typename itk::BinaryFillholeImageFilter<ImageType> FillHoleFilterType;
373 
374  typename FillHoleFilterType::Pointer fillHoleFilter = FillHoleFilterType::New();
375  fillHoleFilter->SetInput(sourceImage);
376  fillHoleFilter->SetForegroundValue(1);
377  fillHoleFilter->UpdateLargestPossibleRegion();
378 
379  mitk::CastToMitkImage(fillHoleFilter->GetOutput(), resultImage);
380 }
381 
382 template <class TStructuringElement>
383 TStructuringElement mitk::MorphologicalOperations::CreateStructuringElement(StructuralElementType structuralElementFlag, int factor)
384 {
385  TStructuringElement strElem;
386  typename TStructuringElement::SizeType size;
387  size.Fill(0);
388  switch (structuralElementFlag)
389  {
390  case Ball_Axial:
391  case Cross_Axial:
392  size.SetElement(0, factor);
393  size.SetElement(1, factor);
394  break;
395  case Ball_Coronal:
396  case Cross_Coronal:
397  size.SetElement(0, factor);
398  size.SetElement(2, factor);
399  break;
400  case Ball_Sagital:
401  case Cross_Sagital:
402  size.SetElement(1, factor);
403  size.SetElement(2, factor);
404  break;
405  case Ball:
406  case Cross:
407  size.Fill(factor);
408  break;
409  }
410 
411  strElem.SetRadius(size);
412  strElem.CreateStructuringElement();
413  return strElem;
414 }
#define AccessByItk_3(mitkImage, itkImageTypeFunction, arg1, arg2, arg3)
#define MITK_INFO
Definition: mitkLogMacros.h:18
itk::Image< unsigned char, 3 > ImageType
#define AccessByItk_1(mitkImage, itkImageTypeFunction, arg1)
static void Closing(mitk::Image::Pointer &image, int factor, StructuralElementType structuralElement)
Perform morphological operation on 2D, 3D or 3D+t segmentation.
mitk::Image::Pointer image
static void Opening(mitk::Image::Pointer &image, int factor, StructuralElementType structuralElement)
Perform morphological operation on 2D, 3D or 3D+t segmentation.
void CastToMitkImage(const itk::SmartPointer< ItkOutputImageType > &itkimage, itk::SmartPointer< mitk::Image > &mitkoutputimage)
Cast an itk::Image (with a specific type) to an mitk::Image.
Definition: mitkImageCast.h:74
ImageReadAccessor class to get locked read access for a particular image part.
static void Dilate(mitk::Image::Pointer &image, int factor, StructuralElementType structuralElement)
Perform morphological operation on 2D, 3D or 3D+t segmentation.
const void * GetData() const
Gives const access to the data.
static Pointer New()
static void FillHoles(mitk::Image::Pointer &image)
Perform morphological operation on 2D, 3D or 3D+t segmentation.
static void Erode(mitk::Image::Pointer &image, int factor, StructuralElementType structuralElement)
Perform morphological operation on 2D, 3D or 3D+t segmentation.