Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F254
mitkOverwriteSliceImageFilter.cpp
Public
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Authored By
maleike
Oct 5 2009, 7:43 AM
2009-10-05 07:43:32 (UTC+2)
Size
13 KB
Referenced Files
None
Subscribers
None
mitkOverwriteSliceImageFilter.cpp
View Options
/*=========================================================================
Program: Medical Imaging & Interaction Toolkit
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#include "mitkOverwriteSliceImageFilter.h"
#include "mitkImageCast.h"
#include "mitkSegmentationInterpolationController.h"
#include "mitkApplyDiffImageOperation.h"
#include "mitkOperationEvent.h"
#include "mitkInteractionConst.h"
#include "mitkUndoController.h"
#include "mitkDiffImageApplier.h"
#include "mitkImageTimeSelector.h"
#include <itkImageSliceIteratorWithIndex.h>
#include <itkImageRegionIterator.h>
mitk
::
OverwriteSliceImageFilter
::
OverwriteSliceImageFilter
()
:
m_SliceIndex
(
0
),
m_SliceDimension
(
0
),
m_TimeStep
(
0
),
m_Dimension0
(
0
),
m_Dimension1
(
1
),
m_CreateUndoInformation
(
false
)
{
m_bSliceAndImageOriented
=
true
;
}
mitk
::
OverwriteSliceImageFilter
::~
OverwriteSliceImageFilter
()
{
}
void
mitk
::
OverwriteSliceImageFilter
::
GenerateData
()
{
//
// this is the place to implement the major part of undo functionality (bug #491)
// here we have to create undo/do operations
//
// WHO is the operation actor? This object may not be destroyed ever (design of undo stack)!
// -> some singleton method of this filter?
//
// neccessary additional objects:
// - something that executes the operations
// - the operation class (must hold a binary diff or something)
// - observer commands to know when the image is deleted (no further action then, perhaps even remove the operations from the undo stack)
//
Image
::
ConstPointer
input
=
ImageToImageFilter
::
GetInput
(
0
);
Image
::
ConstPointer
input3D
=
input
;
Image
::
ConstPointer
slice
=
m_SliceImage
;
if
(
input
.
IsNull
()
||
slice
.
IsNull
()
)
return
;
switch
(
m_SliceDimension
)
{
default
:
case
2
:
m_Dimension0
=
0
;
m_Dimension1
=
1
;
break
;
case
1
:
m_Dimension0
=
0
;
m_Dimension1
=
2
;
break
;
case
0
:
m_Dimension0
=
1
;
m_Dimension1
=
2
;
break
;
}
if
(
slice
->
GetDimension
()
!=
2
||
input
->
GetDimension
()
!=
3
)
{
itkExceptionMacro
(
"Slice and image dimensions differ or slice index is too large. Sorry, cannot work like this."
);
return
;
}
if
(
slice
->
GetDimension
(
0
)
!=
input
->
GetDimension
(
m_Dimension0
)
||
slice
->
GetDimension
(
1
)
!=
input
->
GetDimension
(
m_Dimension1
)
||
m_SliceIndex
>=
input
->
GetDimension
(
m_SliceDimension
)
)
{
m_bSliceAndImageOriented
=
false
;
}
if
(
input
->
GetDimension
()
==
4
)
{
ImageTimeSelector
::
Pointer
timeSelector
=
ImageTimeSelector
::
New
();
timeSelector
->
SetInput
(
input
);
timeSelector
->
SetTimeNr
(
m_TimeStep
);
timeSelector
->
UpdateLargestPossibleRegion
();
input3D
=
timeSelector
->
GetOutput
();
}
if
(
m_SliceDifferenceImage
.
IsNull
()
||
m_SliceDifferenceImage
->
GetDimension
(
0
)
!=
m_SliceImage
->
GetDimension
(
0
)
||
m_SliceDifferenceImage
->
GetDimension
(
1
)
!=
m_SliceImage
->
GetDimension
(
1
)
)
{
m_SliceDifferenceImage
=
mitk
::
Image
::
New
();
mitk
::
PixelType
pixelType
(
typeid
(
short
signed
int
)
);
m_SliceDifferenceImage
->
Initialize
(
pixelType
,
2
,
m_SliceImage
->
GetDimensions
()
);
}
// this will do a long long if/else to find out both pixel types
AccessFixedDimensionByItk
(
input3D
,
ItkImageSwitch
,
3
);
SegmentationInterpolationController
*
interpolator
=
SegmentationInterpolationController
::
InterpolatorForImage
(
input
);
if
(
interpolator
)
{
interpolator
->
BlockModified
(
true
);
if
(
m_bSliceAndImageOriented
)
{
interpolator
->
SetChangedSlice
(
m_SliceDifferenceImage
,
m_SliceDimension
,
m_SliceIndex
,
m_TimeStep
);
}
}
if
(
m_bSliceAndImageOriented
&&
m_CreateUndoInformation
)
{
// create do/undo operations (we don't execute the doOp here, because it has already been executed during calculation of the diff image
ApplyDiffImageOperation
*
doOp
=
new
ApplyDiffImageOperation
(
OpTEST
,
const_cast
<
Image
*>
(
input
.
GetPointer
()),
m_SliceDifferenceImage
,
m_TimeStep
,
m_SliceDimension
,
m_SliceIndex
);
ApplyDiffImageOperation
*
undoOp
=
new
ApplyDiffImageOperation
(
OpTEST
,
const_cast
<
Image
*>
(
input
.
GetPointer
()),
m_SliceDifferenceImage
,
m_TimeStep
,
m_SliceDimension
,
m_SliceIndex
);
undoOp
->
SetFactor
(
-
1.0
);
OperationEvent
*
undoStackItem
=
new
OperationEvent
(
DiffImageApplier
::
GetInstanceForUndo
(),
doOp
,
undoOp
,
this
->
EventDescription
(
m_SliceDimension
,
m_SliceIndex
,
m_TimeStep
)
);
UndoController
::
GetCurrentUndoModel
()
->
SetOperationEvent
(
undoStackItem
);
}
// this image is modified (good to know for the renderer)
input
->
Modified
();
if
(
interpolator
)
{
interpolator
->
BlockModified
(
false
);
}
}
// basically copied from mitk/Core/Algorithms/mitkImageAccessByItk.h
#define myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, pixeltype, dimension, itkimage2) \
if ( typeId == typeid(pixeltype) ) \
{ \
typedef itk::Image<pixeltype, dimension> ImageType; \
typedef mitk::ImageToItk<ImageType> ImageToItkType; \
itk::SmartPointer<ImageToItkType> imagetoitk = ImageToItkType::New(); \
imagetoitk->SetInput(mitkImage); \
imagetoitk->Update(); \
itkImageTypeFunction(imagetoitk->GetOutput(), itkimage2); \
}
#define myMITKOverwriteSliceImageFilterAccessAllTypesByItk(mitkImage, itkImageTypeFunction, dimension, itkimage2) \
{ \
myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, double, dimension, itkimage2) else \
myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, float, dimension, itkimage2) else \
myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, int, dimension, itkimage2) else \
myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, unsigned int, dimension, itkimage2) else \
myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, short, dimension, itkimage2) else \
myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, unsigned short, dimension, itkimage2) else \
myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, char, dimension, itkimage2) else \
myMITKOverwriteSliceImageFilterAccessByItk(mitkImage, itkImageTypeFunction, unsigned char, dimension, itkimage2) \
}
template
<
typename
TPixel
,
unsigned
int
VImageDimension
>
void
mitk
::
OverwriteSliceImageFilter
::
ItkImageSwitch
(
itk
::
Image
<
TPixel
,
VImageDimension
>*
itkImage
)
{
const
std
::
type_info
&
typeId
=*
(
m_SliceImage
->
GetPixelType
().
GetTypeId
());
myMITKOverwriteSliceImageFilterAccessAllTypesByItk
(
m_SliceImage
,
ItkImageProcessing
,
2
,
itkImage
);
}
template
<
typename
TPixel1
,
unsigned
int
VImageDimension1
,
typename
TPixel2
,
unsigned
int
VImageDimension2
>
void
mitk
::
OverwriteSliceImageFilter
::
ItkImageProcessing
(
itk
::
Image
<
TPixel1
,
VImageDimension1
>*
inputImage
,
itk
::
Image
<
TPixel2
,
VImageDimension2
>*
outputImage
)
{
typedef
itk
::
Image
<
TPixel1
,
VImageDimension1
>
SliceImageType
;
typedef
itk
::
Image
<
short
signed
int
,
VImageDimension1
>
DiffImageType
;
typedef
itk
::
Image
<
TPixel2
,
VImageDimension2
>
VolumeImageType
;
typedef
itk
::
ImageSliceIteratorWithIndex
<
VolumeImageType
>
OutputSliceIteratorType
;
typedef
itk
::
ImageRegionConstIterator
<
SliceImageType
>
InputSliceIteratorType
;
typedef
itk
::
ImageRegionIterator
<
DiffImageType
>
DiffSliceIteratorType
;
InputSliceIteratorType
inputIterator
(
inputImage
,
inputImage
->
GetLargestPossibleRegion
()
);
typename
DiffImageType
::
Pointer
diffImage
;
CastToItkImage
(
m_SliceDifferenceImage
,
diffImage
);
DiffSliceIteratorType
diffIterator
(
diffImage
,
diffImage
->
GetLargestPossibleRegion
()
);
// iterate over output slice (and over input slice simultaneously)
inputIterator
.
GoToBegin
();
diffIterator
.
GoToBegin
();
if
(
m_bSliceAndImageOriented
)
{
std
::
cout
<<
"Oriented"
<<
std
::
endl
;
typename
VolumeImageType
::
RegionType
sliceInVolumeRegion
;
sliceInVolumeRegion
=
outputImage
->
GetLargestPossibleRegion
();
sliceInVolumeRegion
.
SetSize
(
m_SliceDimension
,
1
);
// just one slice
sliceInVolumeRegion
.
SetIndex
(
m_SliceDimension
,
m_SliceIndex
);
// exactly this slice, please
// Get an iterator to the output image slice
OutputSliceIteratorType
outputIterator
(
outputImage
,
sliceInVolumeRegion
);
outputIterator
.
SetFirstDirection
(
m_Dimension0
);
outputIterator
.
SetSecondDirection
(
m_Dimension1
);
outputIterator
.
GoToBegin
();
while
(
!
outputIterator
.
IsAtEnd
()
)
{
while
(
!
outputIterator
.
IsAtEndOfSlice
()
)
{
while
(
!
outputIterator
.
IsAtEndOfLine
()
)
{
std
::
cout
<<
outputIterator
.
GetIndex
()[
0
]
<<
", "
<<
outputIterator
.
GetIndex
()[
1
]
<<
", "
<<
outputIterator
.
GetIndex
()[
2
]
<<
" = "
<<
int
(
inputIterator
.
Get
()
)
<<
std
::
endl
;
diffIterator
.
Set
(
static_cast
<
short
signed
int
>
(
inputIterator
.
Get
()
-
outputIterator
.
Get
())
);
// oh oh, not good for bigger values
outputIterator
.
Set
(
(
TPixel2
)
inputIterator
.
Get
()
);
++
outputIterator
;
++
inputIterator
;
++
diffIterator
;
}
outputIterator
.
NextLine
();
}
outputIterator
.
NextSlice
();
}
}
else
{
std
::
cout
<<
"NOT Oriented"
<<
std
::
endl
;
while
(
!
inputIterator
.
IsAtEnd
()
)
{
//itk::Point<double, 2> itkPhysicalPointInput;
// inputImage->TransformIndexToPhysicalPoint( inputIterator.GetIndex(), itkPhysicalPointInput );
//mitk::Point3D inputWorldPoint;
//itk::Point<double, 3> itkPhysicalPointInput3D;
//itkPhysicalPointInput3D[ 0 ] = itkPhysicalPointInput[ 0 ];
//itkPhysicalPointInput3D[ 1 ] = itkPhysicalPointInput[ 1 ];
//itkPhysicalPointInput3D[ 2 ] = 0;
//m_SliceGeometry3D->ItkPhysicalPointToWorld( itkPhysicalPointInput3D, inputWorldPoint );
mitk
::
Point2D
Pt_mm2D
;
mitk
::
Point3D
Pt_mm3D
;
mitk
::
Point2D
pt_units
;
pt_units
[
0
]
=
inputIterator
.
GetIndex
()[
0
];
pt_units
[
1
]
=
inputIterator
.
GetIndex
()[
1
];
m_PlaneGeometry
->
IndexToWorld
(
pt_units
,
Pt_mm2D
);
m_PlaneGeometry
->
Map
(
Pt_mm2D
,
Pt_mm3D
);
itk
::
Image
<
TPixel2
,
VImageDimension2
>::
IndexType
outputIndex
;
m_ImageGeometry3D
->
WorldToIndex
(
Pt_mm3D
,
outputIndex
);
bool
isInside
=
outputImage
->
GetLargestPossibleRegion
().
IsInside
(
outputIndex
);
// Convert index to MITK world
//mitk::Point3D atPt3d_units;
//atPt3d_units.Fill(0.0);
//atPt3d_units[ 0 ] = inputIterator.GetIndex()[ 0 ];
//atPt3d_units[ 1 ] = inputIterator.GetIndex()[ 1 ];
//atPt3d_units[ 2 ] = 0;
//mitk::Point3D pt_mm;
//itk::Point<double, 3> itkPhysicalPoint;
//m_SliceGeometry3D->IndexToWorld( atPt3d_units, pt_mm );
//itk::Point<double, 3> itkPhysicalPoint;
//m_ImageGeometry3D->WorldToItkPhysicalPoint( Pt_mm3D, itkPhysicalPoint );
TPixel2
outputPixel
=
0
;
// Only access ITK image if it's inside
if
(
isInside
)
{
outputPixel
=
outputImage
->
GetPixel
(
outputIndex
);
outputImage
->
SetPixel
(
outputIndex
,
(
TPixel2
)
inputIterator
.
Get
()
);
}
if
(
inputIterator
.
Get
()
!=
0
)
{
std
::
cout
<<
inputIterator
.
GetIndex
(
)[
0
]
<<
", "
<<
inputIterator
.
GetIndex
(
)[
1
]
<<
", "
<<
" ---> "
<<
outputIndex
[
0
]
<<
", "
<<
outputIndex
[
1
]
<<
", "
<<
outputIndex
[
2
]
<<
" = "
<<
int
(
inputIterator
.
Get
()
)
<<
std
::
endl
;
}
// Set difference image
diffIterator
.
Set
(
static_cast
<
short
signed
int
>
(
inputIterator
.
Get
()
-
outputPixel
)
);
// oh oh, not good for bigger values
++
inputIterator
;
++
diffIterator
;
}
}
}
std
::
string
mitk
::
OverwriteSliceImageFilter
::
EventDescription
(
unsigned
int
sliceDimension
,
unsigned
int
sliceIndex
,
unsigned
int
timeStep
)
{
std
::
stringstream
s
;
s
<<
"Changed slice ("
;
switch
(
sliceDimension
)
{
default
:
case
2
:
s
<<
"T"
;
break
;
case
1
:
s
<<
"C"
;
break
;
case
0
:
s
<<
"S"
;
break
;
}
s
<<
" "
<<
sliceIndex
<<
" "
<<
timeStep
<<
")"
;
return
s
.
str
();
}
const
mitk
::
Geometry3D
*
mitk
::
OverwriteSliceImageFilter
::
GetSliceGeometry3D
()
const
{
return
m_SliceGeometry3D
;
}
void
mitk
::
OverwriteSliceImageFilter
::
SetSliceGeometry3D
(
const
mitk
::
Geometry3D
*
val
)
{
m_SliceGeometry3D
=
val
;
}
const
mitk
::
PlaneGeometry
*
mitk
::
OverwriteSliceImageFilter
::
GetPlaneGeometry
()
const
{
return
m_PlaneGeometry
;
}
void
mitk
::
OverwriteSliceImageFilter
::
SetPlaneGeometry
(
const
mitk
::
PlaneGeometry
*
val
)
{
m_PlaneGeometry
=
val
;
}
const
mitk
::
Geometry3D
*
mitk
::
OverwriteSliceImageFilter
::
GetImageGeometry3D
()
const
{
return
m_ImageGeometry3D
;
}
void
mitk
::
OverwriteSliceImageFilter
::
SetImageGeometry3D
(
const
mitk
::
Geometry3D
*
val
)
{
m_ImageGeometry3D
=
val
;
}
File Metadata
Details
Attached
Mime Type
text/plain
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
245
Default Alt Text
mitkOverwriteSliceImageFilter.cpp (13 KB)
Attached To
Mode
T2210: Allow segmentation on reoriented 2D slices
Attached
Detach File
Event Timeline
maleike
added a comment.
Oct 5 2009, 7:43 AM
2009-10-05 07:43:32 (UTC+2)
Comment Actions
mitkOverwriteSliceImageFilter.cpp
Log In to Comment