Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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.