Medical Imaging Interaction Toolkit  2018.4.99-389bf124
Medical Imaging Interaction Toolkit
mitkOverwriteDirectedPlaneImageFilter.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 
15 #include "mitkDiffImageApplier.h"
16 #include "mitkImageAccessByItk.h"
17 #include "mitkImageCast.h"
18 #include "mitkImageTimeSelector.h"
19 #include "mitkInteractionConst.h"
20 #include "mitkOperationEvent.h"
22 #include "mitkUndoController.h"
23 
24 #include <itkImageRegionIterator.h>
25 #include <itkImageSliceIteratorWithIndex.h>
26 
28  : m_PlaneGeometry(nullptr),
29  m_ImageGeometry3D(nullptr),
30  m_TimeStep(0),
31  m_Dimension0(0),
32  m_Dimension1(1),
33  m_CreateUndoInformation(false)
34 {
35  MITK_WARN << "Class is deprecated! Use mitkVtkImageOverwrite instead.";
36 }
37 
39 {
40 }
41 
43 {
44  //
45  // this is the place to implement the major part of undo functionality (bug #491)
46  // here we have to create undo/do operations
47  //
48  // WHO is the operation actor? This object may not be destroyed ever (design of undo stack)!
49  // -> some singleton method of this filter?
50  //
51  // neccessary additional objects:
52  // - something that executes the operations
53  // - the operation class (must hold a binary diff or something)
54  // - observer commands to know when the image is deleted (no further action then, perhaps even remove the operations
55  // from the undo stack)
56  //
57  // Image::ConstPointer input = ImageToImageFilter::GetInput(0);
59 
60  // Image::ConstPointer slice = m_SliceImage;
61 
62  if (input3D.IsNull() || m_SliceImage.IsNull())
63  return;
64 
65  if (input3D->GetDimension() == 4)
66  {
68  timeSelector->SetInput(input3D);
69  timeSelector->SetTimeNr(m_TimeStep);
70  timeSelector->UpdateLargestPossibleRegion();
71  input3D = timeSelector->GetOutput();
72  }
73 
74  m_ImageGeometry3D = input3D->GetGeometry();
75  /*
76  if ( m_SliceDifferenceImage.IsNull() ||
77  m_SliceDifferenceImage->GetDimension(0) != m_SliceImage->GetDimension(0) ||
78  m_SliceDifferenceImage->GetDimension(1) != m_SliceImage->GetDimension(1) )
79  {
80  m_SliceDifferenceImage = mitk::Image::New();
81  mitk::PixelType pixelType( typeid(short signed int) );
82  m_SliceDifferenceImage->Initialize( pixelType, 2, m_SliceImage->GetDimensions() );
83  }
84  */
85  // MITK_INFO << "Overwriting slice " << m_SliceIndex << " in dimension " << m_SliceDimension << " at time step " <<
86  // m_TimeStep << std::endl;
87  // this will do a long long if/else to find out both pixel types
88  /*AccessFixedDimensionByItk( input3D, ItkImageSwitch, 3 );*/
90 
91  // SegmentationInterpolationController* interpolator = SegmentationInterpolationController::InterpolatorForImage(
92  // input3D );
93  // if (interpolator)
94  //{
95  // interpolator->BlockModified(true);
96  // //interpolator->SetChangedSlice( m_SliceDifferenceImage, m_SliceDimension, m_SliceIndex, m_TimeStep );
97  //}
98  /*
99  if ( m_CreateUndoInformation )
100  {
101  // create do/undo operations (we don't execute the doOp here, because it has already been executed during calculation
102  of the diff image
103  ApplyDiffImageOperation* doOp = new ApplyDiffImageOperation( OpTEST, const_cast<Image*>(input.GetPointer()),
104  m_SliceDifferenceImage, m_TimeStep, m_SliceDimension, m_SliceIndex );
105  ApplyDiffImageOperation* undoOp = new ApplyDiffImageOperation( OpTEST, const_cast<Image*>(input.GetPointer()),
106  m_SliceDifferenceImage, m_TimeStep, m_SliceDimension, m_SliceIndex );
107  undoOp->SetFactor( -1.0 );
108  OperationEvent* undoStackItem = new OperationEvent( DiffImageApplier::GetInstanceForUndo(), doOp, undoOp,
109  this->EventDescription(m_SliceDimension, m_SliceIndex, m_TimeStep) );
110  UndoController::GetCurrentUndoModel()->SetOperationEvent( undoStackItem );
111  }
112  */
113  // this image is modified (good to know for the renderer)
114  input3D->Modified();
115 
116  /*if (interpolator)
117  {
118  interpolator->BlockModified(false);
119  }*/
120 }
121 
122 template <typename TPixel, unsigned int VImageDimension>
123 void mitk::OverwriteDirectedPlaneImageFilter::ItkSliceOverwriting(itk::Image<TPixel, VImageDimension> *input3D)
124 {
125  typedef itk::Image<TPixel, VImageDimension - 1> SliceImageType;
126  typedef itk::ImageRegionConstIterator<SliceImageType> SliceIteratorType;
127 
128  typename SliceImageType::Pointer sliceImage = SliceImageType::New();
129  CastToItkImage(m_SliceImage, sliceImage);
130 
131  SliceIteratorType sliceIterator(sliceImage, sliceImage->GetLargestPossibleRegion());
132 
133  sliceIterator.GoToBegin();
134 
135  Point3D currentPointIn2D;
136  Point3D worldPointIn3D;
137 
138  // Here we just iterate over the slice which must be written into the 3D volumen and set the corresponding pixel in
139  // our 3D volume
140  while (!sliceIterator.IsAtEnd())
141  {
142  currentPointIn2D[0] = sliceIterator.GetIndex()[0] + 0.5;
143  currentPointIn2D[1] = sliceIterator.GetIndex()[1] + 0.5;
144  currentPointIn2D[2] = 0;
145 
146  m_PlaneGeometry->IndexToWorld(currentPointIn2D, worldPointIn3D);
147 
148  typename itk::Image<TPixel, VImageDimension>::IndexType outputIndex;
149  m_ImageGeometry3D->WorldToIndex(worldPointIn3D, outputIndex);
150 
151  // Only access ITK image if it's inside
152  if (m_ImageGeometry3D->IsIndexInside(outputIndex))
153  {
154  input3D->SetPixel(outputIndex, (TPixel)sliceIterator.Get());
155  }
156 
157  ++sliceIterator;
158  }
159 }
160 
161 /****TEST***/
162 // Maybe a bit more efficient but doesn`t already work. See also ExtractCirectedPlaneImageFilter
163 
164 // typename itk::Image<TPixel2,VImageDimension2>::IndexType outputIndex;
165 
166 // if ( columns == extent[0] )
167 //{
169 // currentImagePointIn3D = origin;
170 // currentImagePointIn3D += spacing[1]*bottom*currentPointIn2D[1];
171 // columns = 0;
172 // m_ImageGeometry3D->WorldToIndex(currentImagePointIn3D, outputIndex);
173 //}
174 // else
175 //{
176 // if ( columns != 0 )
177 //{
178 // currentImagePointIn3D += spacing[0]*right;
179 //}
180 // m_ImageGeometry3D->WorldToIndex(currentImagePointIn3D, outputIndex);
181 //}
182 
183 // if ( m_ImageGeometry3D->IsIndexInside( outputIndex ))
184 //{
185 // outputImage->SetPixel( outputIndex, (TPixel2)inputIterator.Get() );
186 //}
187 // else if (currentImagePointIn3D == origin)
188 //{
189 // Point3D temp;
190 // temp[0] = bottom[0]*spacing[0]*0.5;
191 // temp[1] = bottom[1]*spacing[1]*0.5;
192 // temp[2] = bottom[2]*spacing[2]*0.5;
193 // origin[0] += temp[0];
194 // origin[1] += temp[1];
195 // origin[2] += temp[2];
196 // currentImagePointIn3D = origin;
197 // m_ImageGeometry3D->WorldToIndex(currentImagePointIn3D, outputIndex);
198 // if ( m_ImageGeometry3D->IsIndexInside( outputIndex ))
199 //{
200 // outputImage->SetPixel( outputIndex, (TPixel2)inputIterator.Get() );
201 //}
202 //}
203 // columns++;
204 
205 /****TEST ENDE****/
206 
207 //*
208 // // Offset the world coordinate by one pixel to compensate for
209 // // index/world origin differences.
210 // Point3D offsetIndex;
211 // offsetIndex.Fill( 1 );
212 // Point3D offsetWorld;
213 // offsetWorld.Fill( 0 );
214 // m_PlaneGeometry->IndexToWorld( offsetIndex, offsetWorld );
215 // // remove origin shift
216 // const Point3D origin = m_PlaneGeometry->GetOrigin();
217 // offsetWorld[0] -= origin[0];
218 // offsetWorld[1] -= origin[1];
219 // offsetWorld[2] -= origin[2];
220 // // offset world coordinate
221 // worldPointIn3D[ 0 ] += offsetWorld[0];
222 // worldPointIn3D[ 1 ] += offsetWorld[1];
223 // worldPointIn3D[ 2 ] += offsetWorld[2];
224 //*/
225 
226 // basically copied from mitk/Core/Algorithms/mitkImageAccessByItk.h
227 /*#define myMITKOverwriteDirectedPlaneImageFilterAccessByItk(mitkImage, itkImageTypeFunction, pixeltype, dimension,
228 itkimage2) \
229 // if ( typeId == typeid(pixeltype) ) \
230 //{ \
231 // typedef itk::Image<pixeltype, dimension> ImageType; \
232 // typedef mitk::ImageToItk<ImageType> ImageToItkType; \
233 // itk::SmartPointer<ImageToItkType> imagetoitk = ImageToItkType::New(); \
234 // imagetoitk->SetInput(mitkImage); \
235 // imagetoitk->Update(); \
236 // itkImageTypeFunction(imagetoitk->GetOutput(), itkimage2); \
237 //}
238 //
239 //#define myMITKOverwriteDirectedPlaneImageFilterAccessAllTypesByItk(mitkImage, itkImageTypeFunction, dimension,
240 itkimage2) \
241 //{ \
242 // myMITKOverwriteDirectedPlaneImageFilterAccessByItk(mitkImage, itkImageTypeFunction, double, dimension,
243 itkimage2) else \
244 // myMITKOverwriteDirectedPlaneImageFilterAccessByItk(mitkImage, itkImageTypeFunction, float, dimension,
245 itkimage2) else \
246 // myMITKOverwriteDirectedPlaneImageFilterAccessByItk(mitkImage, itkImageTypeFunction, int, dimension,
247 itkimage2) else \
248 // myMITKOverwriteDirectedPlaneImageFilterAccessByItk(mitkImage, itkImageTypeFunction, unsigned int, dimension,
249 itkimage2) else \
250 // myMITKOverwriteDirectedPlaneImageFilterAccessByItk(mitkImage, itkImageTypeFunction, short, dimension,
251 itkimage2) else \
252 // myMITKOverwriteDirectedPlaneImageFilterAccessByItk(mitkImage, itkImageTypeFunction, unsigned short, dimension,
253 itkimage2) else \
254 // myMITKOverwriteDirectedPlaneImageFilterAccessByItk(mitkImage, itkImageTypeFunction, char, dimension,
255 itkimage2) else \
256 // myMITKOverwriteDirectedPlaneImageFilterAccessByItk(mitkImage, itkImageTypeFunction, unsigned char, dimension,
257 itkimage2) \
258 //}*/
259 //
260 //
261 // template<typename TPixel, unsigned int VImageDimension>
262 // void mitk::OverwriteDirectedPlaneImageFilter::ItkImageSwitch( itk::Image<TPixel,VImageDimension>* itkImage )
263 //{
264 // const std::type_info& typeId=*(m_SliceImage->GetPixelType().GetTypeId());
265 //
266 // myMITKOverwriteDirectedPlaneImageFilterAccessAllTypesByItk( m_SliceImage, ItkImageProcessing, 2, itkImage );
267 //}
268 
269 // template<typename TPixel1, unsigned int VImageDimension1, typename TPixel2, unsigned int VImageDimension2>
270 // void mitk::OverwriteDirectedPlaneImageFilter::ItkImageProcessing( itk::Image<TPixel1,VImageDimension1>* inputImage,
271 // itk::Image<TPixel2,VImageDimension2>* outputImage )
272 //{
273 // typedef itk::Image<TPixel1, VImageDimension1> SliceImageType;
274 // typedef itk::Image<short signed int, VImageDimension1> DiffImageType;
275 // typedef itk::Image<TPixel2, VImageDimension2> VolumeImageType;
276 //
277 // typedef itk::ImageSliceIteratorWithIndex< VolumeImageType > OutputSliceIteratorType;
278 // typedef itk::ImageRegionConstIterator< SliceImageType > InputSliceIteratorType;
279 // //typedef itk::ImageRegionIterator< DiffImageType > DiffSliceIteratorType;
280 //
281 // InputSliceIteratorType inputIterator( inputImage, inputImage->GetLargestPossibleRegion() );
282 //
283 // //typename DiffImageType::Pointer diffImage;
284 // //CastToItkImage( m_SliceDifferenceImage, diffImage );
285 // //DiffSliceIteratorType diffIterator( diffImage, diffImage->GetLargestPossibleRegion() );
286 //
287 // inputIterator.GoToBegin();
288 // //diffIterator.GoToBegin();
289 //
290 // //TEST
291 // Point3D origin = m_PlaneGeometry->GetOrigin();
292 // Vector3D right = m_PlaneGeometry->GetAxisVector(0);
293 // Vector3D bottom = m_PlaneGeometry->GetAxisVector(1);
294 // right.Normalize();
295 // bottom.Normalize();
296 //
297 // Vector2D spacing = inputImage->GetSpacing();
298 //
299 // Vector2D extentInMM;
300 // extentInMM[0] = m_PlaneGeometry->GetExtentInMM(0);
301 // extentInMM[1] = m_PlaneGeometry->GetExtentInMM(1);
302 //
303 // Vector2D extent;
304 // extent[0] = m_PlaneGeometry->GetExtent(0);
305 // extent[1] = m_PlaneGeometry->GetExtent(1);
306 // //TEST ENDE
307 //
308 // Point3D currentPointIn2D, worldPointIn3D;
309 // TPixel2 outputPixel = 0;
310 //
311 // int debugCounter( 0 );
312 //
313 // std::ofstream geometryFile;
314 // geometryFile.precision(30);
315 // geometryFile.open("C:/Users/fetzer/Desktop/TEST/geometryFileOv.txt");
316 //
317 // geometryFile<<"Offset: [ "<<m_PlaneGeometry->GetIndexToWorldTransform()->GetOffset()[0]<<",
318 // "<<m_PlaneGeometry->GetIndexToWorldTransform()->GetOffset()[1]<<",
319 // "<<m_PlaneGeometry->GetIndexToWorldTransform()->GetOffset()[2]<<" ]"<<std::endl;
320 // geometryFile<<"Transform: "<<m_PlaneGeometry->GetIndexToWorldTransform()->GetMatrix()<<std::endl;
321 //
322 // //std::ofstream overriderFile;
323 // //overriderFile.open("C:/Users/fetzer/Desktop/TEST/overridePoints.txt");
324 //
325 // //std::ofstream overriderFileIndex;
326 // //overriderFileIndex.open("C:/Users/fetzer/Desktop/TEST/overrideIndexPoints.txt");
327 //
328 //
329 // //TEST
330 // Point3D currentImagePointIn3D = origin;
331 // unsigned int columns ( 0 );
332 // //TEST ENDE
333 //
334 // while ( !inputIterator.IsAtEnd() )
335 // {
336 // // Input world point
337 // currentPointIn2D[0] = inputIterator.GetIndex()[0]+0.5;
338 // currentPointIn2D[1] = inputIterator.GetIndex()[1]+0.5;
339 // currentPointIn2D[2] = 0;
340 //
341 // m_PlaneGeometry->IndexToWorld( currentPointIn2D, worldPointIn3D );
342 //
343 // typename itk::Image<TPixel2,VImageDimension2>::IndexType outputIndex;
344 // m_ImageGeometry3D->WorldToIndex( worldPointIn3D, outputIndex );
345 //
346 // // Only access ITK image if it's inside
347 // if ( m_ImageGeometry3D->IsIndexInside( outputIndex ) )
348 // {
349 // //outputPixel = outputImage->GetPixel( outputIndex );
350 // outputImage->SetPixel( outputIndex, (TPixel2)inputIterator.Get() );
351 // /*if( inputIterator.Get() == mitk::paint::addPixelValue )
352 // {
353 // outputImage->SetPixel( outputIndex, (TPixel2)( 1 ) );
354 // }
355 // else if( inputIterator.Get() == mitk::paint::subPixelValue )
356 // {
357 // outputImage->SetPixel( outputIndex, (TPixel2)( 0 ) );
358 // }*/
359 // }
360 //
362 //
364 //
370 // columns = 0;
381 //
403 //
405 //
424 // // Output index
425 //
426 //
441 //
442 // // Set difference image
443 // //diffIterator.Set( static_cast<short signed int>(inputIterator.Get() - outputPixel ) ); // oh oh, not good for
444 // bigger values
445 // ++inputIterator;
447 // //++diffIterator;
448 // }
449 // /*overriderFile.close();
450 // overriderFileIndex.close();*/
451 // geometryFile.close();
452 //
454 // typename VolumeImageType::RegionType sliceInVolumeRegion;
455 //
456 // sliceInVolumeRegion = outputImage->GetLargestPossibleRegion();
457 // sliceInVolumeRegion.SetSize( m_SliceDimension, 1 ); // just one slice
458 // sliceInVolumeRegion.SetIndex( m_SliceDimension, m_SliceIndex ); // exactly this slice, please
459 //
460 // OutputSliceIteratorType outputIterator( outputImage, sliceInVolumeRegion );
461 // outputIterator.SetFirstDirection(m_Dimension0);
462 // outputIterator.SetSecondDirection(m_Dimension1);
463 //
464 // // iterate over output slice (and over input slice simultaneously)
465 // outputIterator.GoToBegin();
466 // while ( !outputIterator.IsAtEnd() )
467 // {
468 // while ( !outputIterator.IsAtEndOfSlice() )
469 // {
470 // while ( !outputIterator.IsAtEndOfLine() )
471 // {
472 // diffIterator.Set( static_cast<short signed int>(inputIterator.Get() - outputIterator.Get()) ); // oh oh, not
473 // good for bigger values
474 // outputIterator.Set( (TPixel2) inputIterator.Get() );
475 // ++outputIterator;
476 // ++inputIterator;
477 // ++diffIterator;
478 // }
479 // outputIterator.NextLine();
480 // }
481 // outputIterator.NextSlice();
482 // }
483 // */
484 //}
485 /*
486 std::string mitk::OverwriteDirectedPlaneImageFilter::EventDescription( unsigned int sliceDimension, unsigned int
487 sliceIndex, unsigned int timeStep )
488 {
489 std::stringstream s;
490 
491 s << "Changed slice (";
492 
493 switch (sliceDimension)
494 {
495 default:
496 case 2:
497 s << "T";
498 break;
499 case 1:
500 s << "C";
501 break;
502 case 0:
503 s << "S";
504 break;
505 }
506 
507 s << " " << sliceIndex << " " << timeStep << ")";
508 
509 return s.str();
510 }
511 */
void IndexToWorld(const mitk::Vector3D &vec_units, mitk::Vector3D &vec_mm) const
Convert (continuous or discrete) index coordinates of a vector vec_units to world coordinates (in mm)...
#define AccessFixedDimensionByItk(mitkImage, itkImageTypeFunction, dimension)
Access a mitk-image with known dimension by an itk-image.
bool IsIndexInside(const mitk::Point3D &index) const
Test whether the point p ((continous!)index coordinates in units) is inside the bounding box...
Constants for most interaction classes, due to the generic StateMachines.
void ItkSliceOverwriting(itk::Image< TPixel, VImageDimension > *input3D)
class ITK_EXPORT Image
#define MITK_WARN
Definition: mitkLogMacros.h:19
void WorldToIndex(const mitk::Point3D &pt_mm, mitk::Point3D &pt_units) const
Convert world coordinates (in mm) of a point to (continuous!) index coordinates.
InputImageType * GetInput(void)
void MITKCORE_EXPORT CastToItkImage(const mitk::Image *mitkImage, itk::SmartPointer< ItkOutputImageType > &itkOutputImage)
Cast an mitk::Image to an itk::Image with a specific type.
static Pointer New()