MeVisLab Toolbox Reference
mlITKFilterSupport.h
Go to the documentation of this file.
1 /*************************************************************************************
2 **
3 ** Copyright 2007, MeVis Medical Solutions AG
4 **
5 ** The user may use this file in accordance with the license agreement provided with
6 ** the Software or, alternatively, in accordance with the terms contained in a
7 ** written agreement between the user and MeVis Medical Solutions AG.
8 **
9 ** For further information use the contact form at https://www.mevislab.de/contact
10 **
11 **************************************************************************************/
12 
13 #pragma once
14 
16 // Include dll-specific settings.
17 #include "mlInitSystemITKSupport.h"
18 
21 
22 ML_START_NAMESPACE
23 
24 //----------------------------------------------------------------------------
26 //----------------------------------------------------------------------------
28 
29 //---------------------------------------------------------------------------
45 //---------------------------------------------------------------------------
46 template <typename FILTER_TYPE, typename OIMAGE_TYPE>
47 bool processDataWithITKFilterAndFillOutSubImg(typename FILTER_TYPE::Pointer &filterPointer,
48  int outIndex,
49  MLint usedFilteringDim,
50  const ImageVector &shift,
51  const SubImageBox &outImgBox,
52  SubImage &outSubImg,
53  Module &module)
54 {
55  // Test and debug function call.
57 
58  bool okay=true;
59  if ((outIndex <0) || (usedFilteringDim < 0)){
60  okay = false;
61  }
62  else{
63  try {
64 
65  // Get filter output.
66  typename OIMAGE_TYPE::Pointer filterOutput = filterPointer->GetOutput(static_cast<unsigned int>(outIndex));
67 
68  // Be sure that extent of output page does not reach outside the output image
69  // to avoid that undefined regions are requested. In contrast to the ML ITK
70  // does not permit that.
71  SubImageBox outBox(outSubImg.getBox().intersect(outImgBox));
72 
73  // Shift the valid image region which is to be calculated to ITK coordinates.
74  outBox.translate(shift);
75 
76  // Set region to be calculated.
77  typename OIMAGE_TYPE::RegionType itkOutBox = ITKRegionFromMLSubImgBox<OIMAGE_TYPE>(outBox);
78  filterOutput->SetRequestedRegion(itkOutBox);
79 
80  // Process requested output region image buffer.
81  filterPointer->Update();
82 
83  // Get output image of the filter and pointer to its data.
84  typename OIMAGE_TYPE::PixelType* dataPtr = filterOutput->GetBufferPointer();
85 
86  // Get region of output image and build an ML SubImageBox from it.
87  SubImageBox outSubImgBox = MLSubImgBoxFromITKRegion<OIMAGE_TYPE>(filterOutput->GetBufferedRegion());
88 
89  // Shift processed ITK output region to ML coordinates.
90  outSubImgBox.translate(-shift);
91 
92  // Here we need to correct the position of the outSubimgBox in the case that
93  // we have images which are higher dimensional than the dimension of the
94  // compiled ITK filter. We need to place the box at the original high dimensional
95  // position to be able to copy it back to the output subimage box.
96  for (MLint d=usedFilteringDim; d<6; ++d){
97  // Cast down to avoid huge amounts of warnings in derived codes.
98  const size_t sizeTDimIdx = static_cast<size_t>(d);
99 
100  // Copy higher dimensional components of both corners from outBox.
101  // This will probably not work if filters project to lower dimensions,
102  // which, however, is not supported in other code fragments either.
103  outSubImgBox.v1[sizeTDimIdx] = outBox.v1[sizeTDimIdx];
104  outSubImgBox.v2[sizeTDimIdx] = outBox.v2[sizeTDimIdx];
105  }
106 
107  // Convert and copy the ITK buffer to the ML subimage.
108  copyITKDataBufferToMLSubImg(dataPtr, sizeof(ITKML_TYPENAME OIMAGE_TYPE::PixelType), outSubImgBox, outSubImg);
109  }
110  catch( itk::ExceptionObject & e ){
111  // Handle error.
112  postITKException(e, &module, ML_ERROR, "Leaving output subimage unprocessed.");
113  okay=false;
114  }
115  }
116  return okay;
117 }
118 
119 //----------------------------------------------------------------------------
121 //----------------------------------------------------------------------------
123 
124 //----------------------------------------------------------------------------
136 //----------------------------------------------------------------------------
137 template <typename FILTER_TYPE, typename IN_IMAGE_TYPE>
138 SubImageBox determineImageFilterInRegionTN(typename FILTER_TYPE::Pointer &filterPointer,
139  Module &module,
140  MLint inIndex,
141  const SubImageBox &outBox,
142  MLint outIndex,
143  MLint numActiveInputs)
144 {
145  // Test and debug function call.
147 
148  // Check for active input - on inactive inputs we simply return an empty box,
149  // because there data requests do not make sense.
150  if ((outIndex < 0) || (inIndex < 0) || (inIndex >= numActiveInputs)){
151  return SubImageBox();
152  }
153 
154  if(!filterPointer){
155  MLPrintAndNotify(ML_ERROR, "ML_","", "ITK Filter is NULL.",
156  "", "Returning empty box",
157  __FILE__, __LINE__, ML_UNKNOWN_EXCEPTION);
158  return SubImageBox();
159  }
160 
161  // For each input get input image region as box. All other are left empty.
162  // Get outBox as ITK region object.
163  typename IN_IMAGE_TYPE::RegionType region =
164  ITKRegionFromMLSubImgBox<IN_IMAGE_TYPE>(outBox);
165 
166  // Convert boxes to ITK boxes and pass them to the filter.
167  for (MLint inps=0; inps < numActiveInputs; ++inps){
168  // Get input image extents as ITK region object.
169  typename IN_IMAGE_TYPE::RegionType largestPossibleRegion =
170  ITKRegionFromMLSubImgBox<IN_IMAGE_TYPE>(module.getInputImage(inps)->getBoxFromImageExtent());
171 
172  // Create a filter object, set input image extents.
173  typename IN_IMAGE_TYPE::Pointer m_Image = IN_IMAGE_TYPE::New();
174  m_Image->SetRegions(largestPossibleRegion);
175  filterPointer->SetInput(static_cast<unsigned int>(inps), m_Image);
176  }
177 
178  // Set requested region at output, and ask for the input
179  // region which is needed by the filter.
180  try{
181  const unsigned int uOutIdx = static_cast<unsigned int>(outIndex);
182  filterPointer->GetOutput(uOutIdx)->SetRequestedRegion(region);
183  filterPointer->GetOutput(uOutIdx)->UpdateOutputInformation();
184  filterPointer->GetOutput(uOutIdx)->PropagateRequestedRegion();
185  typename IN_IMAGE_TYPE::RegionType inReg =
186  filterPointer->GetInput(static_cast<unsigned int>(inIndex))->GetRequestedRegion();
187  SubImageBox retRegion = MLSubImgBoxFromITKRegion<IN_IMAGE_TYPE>(inReg);
188  return retRegion;
189  }
190  catch( itk::ExceptionObject & e )
191  {
192  postITKException(e, &module, ML_ERROR);
193  return SubImageBox(); /* Return empty box in case of error. */
194  }
195 }
196 
197 
198 //----------------------------------------------------------------------------
200 //----------------------------------------------------------------------------
202 
203 //----------------------------------------------------------------------------
206 //----------------------------------------------------------------------------
207 template <typename FILTER_TYPE, typename OUT_IMAGE_TYPE>
208 SubImageBox determineImageFilterOutImageRegionT0(typename FILTER_TYPE::Pointer &filterPointer,
209  Module &module)
210 {
211  // Test and debug function call.
213 
214  if (!filterPointer){ return SubImageBox(); }
215 
216  /* Define a dummy region of one voxel. */
217  typename OUT_IMAGE_TYPE::RegionType region =
218  ITKRegionFromMLSubImgBox<OUT_IMAGE_TYPE>(SubImageBox(ImageVector(0), ImageVector(0)));
219 
220  try{
221  /* Propagate a dummy region through filter to update output infos */
222  /* correctly. It seems not to work for all filters without setting */
223  /* and propagating such a dummy region. */
224  filterPointer->GetOutput()->SetRequestedRegion(region);
225  filterPointer->GetOutput()->UpdateOutputInformation();
226  filterPointer->GetOutput()->PropagateRequestedRegion();
227 
228  /* Now filter regions are updated, get the largest possible region. */
229  typename OUT_IMAGE_TYPE::RegionType outRegion =
230  filterPointer->GetOutput()->GetLargestPossibleRegion();
231 
232  /* Return output image extent defined by largest possible region. */
233  SubImageBox retRegion = MLSubImgBoxFromITKRegion<OUT_IMAGE_TYPE>(outRegion);
234  return retRegion;
235  }
236  catch( itk::ExceptionObject & e )
237  {
238  postITKException(e, &module, ML_ERROR, "Setting empty output image region");
239  return SubImageBox(); /* Return empty box in case of error. */
240  }
241 }
242 
243 //----------------------------------------------------------------------------
245 //----------------------------------------------------------------------------
247 
248 //----------------------------------------------------------------------------
251 //----------------------------------------------------------------------------
252 template <typename FILTER_TYPE, typename OUT_IMAGE_TYPE, typename IN_IMAGE_TYPE>
253 SubImageBox determineImageFilterOutImageRegionTN(typename FILTER_TYPE::Pointer &filterPointer,
254  Module &module,
255  int numImageInputs)
256 {
257  // Test and debug function call.
259 
260  if (!filterPointer){ return SubImageBox(); }
261 
262  /* Define a dummy region of one voxel. */
263  typename OUT_IMAGE_TYPE::RegionType region =
264  ITKRegionFromMLSubImgBox<OUT_IMAGE_TYPE>(SubImageBox(ImageVector(0), ImageVector(0)));
265 
266  /* Create and set a dummy ITK input images. */
267  for (int inps=0; inps < numImageInputs; ++inps){
268 
269  /* Get input image extents as ITK region object. */
270  SubImageBox inSubImgBox(module.getInputImage(inps)->getImageExtent());
271  typename IN_IMAGE_TYPE::RegionType largestPossibleRegion =
272  ITKRegionFromMLSubImgBox<IN_IMAGE_TYPE>(inSubImgBox);
273 
274  /* Set a dummy ITK image with extents of input image as input. */
275  typename IN_IMAGE_TYPE::Pointer m_Image = IN_IMAGE_TYPE::New();
276  try{
277  m_Image->SetRegions(largestPossibleRegion);
278  filterPointer->SetInput(static_cast<unsigned int>(inps), m_Image);
279  }
280  catch( itk::ExceptionObject & e )
281  {
282  postITKException(e, &module, ML_ERROR, "Setting empty output image region");\
283  return SubImageBox(); /* Return empty box in case of error. */
284  }
285  }
286 
287  try{
288  /* Propagate a dummy region through filter to update output infos */
289  /* correctly. It seems not to work for all filters without setting */
290  /* and propagating such a dummy region. */
291  filterPointer->GetOutput()->SetRequestedRegion(region);
292  filterPointer->GetOutput()->UpdateOutputInformation();
293  filterPointer->GetOutput()->PropagateRequestedRegion();
294 
295  /* Now filter regions are updated, get the largest possible region. */
296  typename OUT_IMAGE_TYPE::RegionType outRegion =
297  filterPointer->GetOutput()->GetLargestPossibleRegion();
298 
299  /* Return output image extent defined by largest possible region. */
300  SubImageBox retRegion = MLSubImgBoxFromITKRegion<OUT_IMAGE_TYPE>(outRegion);
301  return retRegion;
302  }
303  catch( itk::ExceptionObject & e )
304  {
305  postITKException(e, &module, ML_ERROR, "Setting empty output image region");
306  return SubImageBox(); /* Return empty box in case of error. */
307  }
308 }
309 
310 ML_END_NAMESPACE
SubImageBox getBoxFromImageExtent() const
Returns size of image as box with origin 0.
ImageVector getImageExtent() const
Returns the extent of the (sub)image.
Base class for an image processing module of the ML.
Definition: mlModule.h:156
PagedImage * getInputImage(MLint inputIndex, bool getReal=false) const
Returns the output image of the module connected to input inputIndex.
This class manages/represents a rectangular 6d image region which is organized linearly in memory.
Definition: mlSubImage.h:75
const SubImageBox & getBox() const
Returns the box describing the origin/extent of the subimage.
Definition: mlSubImage.h:230
void translate(const VectorType &offsetVector)
Shifts the whole box by an offset given by offsetVector.
VectorType v1
Corner v1 of the subimage region (included in region).
Definition: mlSubImageBox.h:63
static TSubImageBox< intT > intersect(const TSubImageBox< intT > &box1, const TSubImageBox< intT > &box2)
Returns the overlapping region of subimage regions box1 and box2.
VectorType v2
Corner v2 of the subimage region (also included in region!).
Definition: mlSubImageBox.h:69
#define ML_UNKNOWN_EXCEPTION
An unknown exception was detected and caught; this usually means that something for an unknown reason...
Definition: mlTypeDefs.h:832
#define ITKML_TYPENAME
Define it empty. In some cases VC++6 does not accept "typename" where non WIN32 compilers do.
MLint64 MLint
A signed ML integer type with at least 64 bits used for index calculations on very large images even ...
Definition: mlTypeDefs.h:578
@ ML_ERROR
Definition: mlTypeDefs.h:799
ML_UTILS_EXPORT void MLPrintAndNotify(MLMessageType messageType, const char *libraryPrefix, const char *fPrefix, const char *functionName, const char *reason, const char *handling, const char *file, int line, MLErrorCode errCode)
Core error printing function which can be used by other applications.
SubImageBox determineImageFilterOutImageRegionTN(typename FILTER_TYPE::Pointer &filterPointer, Module &module, int numImageInputs)
Calculates the maximum extent of the ITK output image for 0 inputs and returns it as SubImageBox.
SubImageBox determineImageFilterInRegionTN(typename FILTER_TYPE::Pointer &filterPointer, Module &module, MLint inIndex, const SubImageBox &outBox, MLint outIndex, MLint numActiveInputs)
Calculates required input regions for any number of filter inputs.
SubImageBox determineImageFilterOutImageRegionT0(typename FILTER_TYPE::Pointer &filterPointer, Module &module)
Calculates the maximum extent of the ITK output image for 0 inputs and returns it as SubImageBox.
void testFunc_determineImageFilterOutImageRegionT0()
Test function for debugging purposes.
MLITK_SUPPORT_EXPORT void copyITKDataBufferToMLSubImg(void *itkData, size_t itkDataTypeSize, const SubImageBox &itkBox, SubImage &outSubImg)
Unpack ITK data buffer to an ML subimage and convert data formats if necessary.
TSubImageBox< MLint > SubImageBox
Define the standard SubImageBox type used in the ML. Its size varies with the size of the MLint type.
bool processDataWithITKFilterAndFillOutSubImg(typename FILTER_TYPE::Pointer &filterPointer, int outIndex, MLint usedFilteringDim, const ImageVector &shift, const SubImageBox &outImgBox, SubImage &outSubImg, Module &module)
Takes the output image of the filter pointed to by filterPointer, and copies overlapping contents int...
void testFunc_processDataWithITKFilterAndFillOutSubImg()
Test function for debugging purposes.
void testFunc_determineImageFilterInRegionTN()
Test function for debugging purposes.
void testFunc_determineImageFilterOutImageRegionTN()
Test function for debugging purposes.
MLITK_SUPPORT_EXPORT void postITKException(const itk::ExceptionObject &e, const Module *module, MLMessageType messageType, const std::string &handling="")
Sends all available information from the ITKException itkException to the ML error handler.
TImageVector< MLint > ImageVector
Defines the standard ImageVector type which is used by the ML for indexing and coordinates.