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.
18
21
22ML_START_NAMESPACE
23
24//----------------------------------------------------------------------------
26//----------------------------------------------------------------------------
28
29//---------------------------------------------------------------------------
45//---------------------------------------------------------------------------
46template <typename FILTER_TYPE, typename OIMAGE_TYPE>
47bool 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//----------------------------------------------------------------------------
137template <typename FILTER_TYPE, typename IN_IMAGE_TYPE>
138SubImageBox 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//----------------------------------------------------------------------------
207template <typename FILTER_TYPE, typename OUT_IMAGE_TYPE>
208SubImageBox 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//----------------------------------------------------------------------------
252template <typename FILTER_TYPE, typename OUT_IMAGE_TYPE, typename IN_IMAGE_TYPE>
253SubImageBox 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
310ML_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 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:577
#define ML_UNKNOWN_EXCEPTION
An unknown exception was detected and caught; this usually means that something for an unknown reason...
Definition: mlTypeDefs.h:831
@ ML_ERROR
Definition: mlTypeDefs.h:798
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.