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