Page MenuHomePhabricator

mitkOverwriteSliceImageFilter.cpp

Authored By
maleike
Oct 5 2009, 7:43 AM
Size
13 KB
Referenced Files
None
Subscribers
None

mitkOverwriteSliceImageFilter.cpp

/*=========================================================================
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

Mime Type
text/plain
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
245
Default Alt Text
mitkOverwriteSliceImageFilter.cpp (13 KB)

Event Timeline

mitkOverwriteSliceImageFilter.cpp