Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "mitkAutoCropImageFilter.h"
00019
00020 #include "mitkImageCast.h"
00021 #include <itkImageRegionConstIterator.h>
00022 #include "mitkImageAccessByItk.h"
00023 #include "mitkGeometry3D.h"
00024 #include "mitkStatusBar.h"
00025
00026
00027 mitk::AutoCropImageFilter::AutoCropImageFilter()
00028 : m_BackgroundValue(0),
00029 m_MarginFactor(1.0),
00030 m_TimeSelector(NULL),
00031 m_OverrideCroppingRegion(false)
00032 {
00033
00034 }
00035
00036
00037 mitk::AutoCropImageFilter::~AutoCropImageFilter()
00038 {
00039
00040 }
00041
00042
00043 template < typename TPixel, unsigned int VImageDimension>
00044 void mitk::AutoCropImageFilter::ITKCrop3DImage( itk::Image< TPixel, VImageDimension >* inputItkImage, unsigned int timestep)
00045 {
00046
00047 if (inputItkImage == NULL)
00048 {
00049 mitk::StatusBar::GetInstance()->DisplayErrorText ("An internal error occurred. Can't convert Image. Please report to bugs@mitk.org");
00050 MITK_ERROR << "image is NULL...returning" << std::endl;
00051 return;
00052 }
00053
00054 typedef itk::Image< TPixel, VImageDimension > InternalImageType;
00055 typedef typename InternalImageType::Pointer InternalImagePointer;
00056
00057 typedef itk::CropImageFilter<InternalImageType,InternalImageType> FilterType;
00058 typedef typename itk::CropImageFilter<InternalImageType,InternalImageType>::Pointer FilterPointer;
00059
00060 InternalImagePointer outputItk = InternalImageType::New();
00061
00062 FilterPointer cropFilter = FilterType::New();
00063 cropFilter->SetLowerBoundaryCropSize( m_LowerBounds );
00064 cropFilter->SetUpperBoundaryCropSize( m_UpperBounds );
00065 cropFilter->SetInput( inputItkImage );
00066 cropFilter->Update();
00067 outputItk = cropFilter->GetOutput();
00068 outputItk->DisconnectPipeline();
00069
00070 mitk::Image::Pointer newMitkImage = mitk::Image::New();
00071 mitk::CastToMitkImage( outputItk, newMitkImage );
00072
00073 mitkIpPicDescriptor* image3D = newMitkImage->GetVolumeData(0)->GetPicDescriptor();
00074 this->GetOutput()->SetPicVolume( image3D , timestep );
00075 }
00076
00077 void mitk::AutoCropImageFilter::GenerateOutputInformation()
00078 {
00079 mitk::Image::Pointer input = const_cast< mitk::Image * > ( this->GetInput() );
00080 if(input->GetDimension() <= 2)
00081 {
00082 MITK_ERROR << "Only 3D any 4D images are supported." << std::endl;
00083 return;
00084 }
00085 ComputeNewImageBounds();
00086
00087 mitk::Image::Pointer output = this->GetOutput();
00088 if ((output->IsInitialized()) && (output->GetPipelineMTime() <= m_TimeOfHeaderInitialization.GetMTime()))
00089 return;
00090
00091 itkDebugMacro(<<"GenerateOutputInformation()");
00092
00093
00094
00095
00096
00097
00098
00099
00100 m_InputRequestedRegion = input->GetLargestPossibleRegion();
00101
00102
00103 mitk::SlicedData::IndexType index;
00104 index[0] = m_RegionIndex[0];
00105 index[1] = m_RegionIndex[1];
00106 index[2] = m_RegionIndex[2];
00107 index[3] = m_InputRequestedRegion.GetIndex()[3];
00108 index[4] = m_InputRequestedRegion.GetIndex()[4];
00109 mitk::SlicedData::SizeType size;
00110 size[0] = m_RegionSize[0];
00111 size[1] = m_RegionSize[1];
00112 size[2] = m_RegionSize[2];
00113 size[3] = m_InputRequestedRegion.GetSize()[3];
00114 size[4] = m_InputRequestedRegion.GetSize()[4];
00115
00116 mitk::SlicedData::RegionType boRegion(index, size);
00117
00118
00119 if(m_InputRequestedRegion.Crop(boRegion)==false)
00120 {
00121
00122 size.Fill(0);
00123 m_InputRequestedRegion.SetSize(size);
00124 return;
00125 }
00126
00127
00128
00129 input->SetRequestedRegion(&m_InputRequestedRegion);
00130
00131
00132
00133 unsigned int dimension = input->GetDimension();
00134 unsigned int *dimensions = new unsigned int [dimension];
00135 itk2vtk(m_InputRequestedRegion.GetSize(), dimensions);
00136 if(dimension>3)
00137 memcpy(dimensions+3, input->GetDimensions()+3, (dimension-3)*sizeof(unsigned int));
00138 output->Initialize(mitk::PixelType( GetOutputPixelType() ), dimension, dimensions);
00139 delete [] dimensions;
00140
00141
00142 output->GetGeometry()->SetIndexToWorldTransform( input->GetGeometry()->GetIndexToWorldTransform() );
00143 output->SetSpacing( input->GetSlicedGeometry()->GetSpacing() );
00144
00145
00146 mitk::SlicedGeometry3D* slicedGeometry = output->GetSlicedGeometry();
00147 const mitk::SlicedData::IndexType& start = m_InputRequestedRegion.GetIndex();
00148 mitk::Point3D origin; vtk2itk(start, origin);
00149 input->GetSlicedGeometry()->IndexToWorld(origin, origin);
00150 slicedGeometry->SetOrigin(origin);
00151
00152 mitk::TimeSlicedGeometry* timeSlicedGeometry = output->GetTimeSlicedGeometry();
00153 timeSlicedGeometry->InitializeEvenlyTimed(slicedGeometry, output->GetDimension(3));
00154 timeSlicedGeometry->CopyTimes(input->GetTimeSlicedGeometry());
00155
00156 m_TimeOfHeaderInitialization.Modified();
00157
00158 output->SetPropertyList(input->GetPropertyList()->Clone());
00159 }
00160
00161 void mitk::AutoCropImageFilter::GenerateData()
00162 {
00163 mitk::Image::ConstPointer input = this->GetInput();
00164 mitk::Image::Pointer output = this->GetOutput();
00165
00166 if(input.IsNull())
00167 return;
00168
00169 if(input->GetDimension() <= 2)
00170 {
00171 MITK_ERROR << "Only 3D and 4D images supported";
00172 return;
00173 }
00174
00175 if((output->IsInitialized()==false) )
00176 return;
00177
00178 if( m_TimeSelector.IsNull() ) m_TimeSelector = mitk::ImageTimeSelector::New();
00179
00180 m_TimeSelector->SetInput(input);
00181
00182 mitk::SlicedData::RegionType outputRegion = input->GetRequestedRegion();
00183
00184 int tstart = outputRegion.GetIndex(3);
00185 int tmax = tstart + outputRegion.GetSize(3);
00186
00187 for( int timestep=tstart;timestep<tmax;++timestep )
00188 {
00189 m_TimeSelector->SetTimeNr(timestep);
00190 m_TimeSelector->UpdateLargestPossibleRegion();
00191
00192 AccessFixedDimensionByItk_1( m_TimeSelector->GetOutput(), ITKCrop3DImage, 3, timestep );
00193 }
00194
00195
00196
00197 m_TimeOfHeaderInitialization.Modified();
00198 }
00199
00200 void mitk::AutoCropImageFilter::ComputeNewImageBounds()
00201 {
00202 mitk::Image::Pointer inputMitk = const_cast< mitk::Image * > ( this->GetInput() );
00203
00204 if (m_OverrideCroppingRegion)
00205 {
00206 for (unsigned int i=0; i<3; ++i)
00207 {
00208 m_RegionIndex[i] = m_CroppingRegion.GetIndex()[i];
00209 m_RegionSize[i] = m_CroppingRegion.GetSize()[i];
00210
00211 if (m_RegionIndex[i] >= inputMitk->GetDimension(i))
00212 {
00213 itkExceptionMacro("Cropping index is not inside the image. "
00214 << std::endl << "Index:"
00215 << std::endl << m_CroppingRegion.GetIndex()
00216 << std::endl << "Size:"
00217 << std::endl << m_CroppingRegion.GetSize());
00218 }
00219
00220 if (m_RegionIndex[i] + m_RegionSize[i] >= inputMitk->GetDimension(i))
00221 {
00222 m_RegionSize[i] = inputMitk->GetDimension(i) - m_RegionIndex[i];
00223 }
00224 }
00225
00226 for (unsigned int i=0; i<3; ++i)
00227 {
00228 m_RegionIndex[i] = m_CroppingRegion.GetIndex()[i];
00229 m_RegionSize[i] = m_CroppingRegion.GetSize()[i];
00230
00231
00232 m_LowerBounds[i] = m_CroppingRegion.GetIndex()[i];
00233 m_UpperBounds[i] = inputMitk->GetDimension(i)-m_CroppingRegion.GetSize()[i]-m_LowerBounds[i];
00234 }
00235 }
00236 else
00237 {
00238
00239 unsigned int timeSteps = 1;
00240 if (inputMitk->GetDimension() == 4 ) timeSteps = inputMitk->GetDimension(3);
00241
00242 ImageType::IndexType minima,maxima;
00243
00244 if (inputMitk->GetDimension() == 4)
00245 {
00246
00247 m_TimeSelector = mitk::ImageTimeSelector::New();
00248 m_TimeSelector->SetInput( inputMitk );
00249 m_TimeSelector->SetTimeNr( 0 );
00250 m_TimeSelector->UpdateLargestPossibleRegion();
00251 inputMitk = m_TimeSelector->GetOutput();
00252 }
00253
00254 ImagePointer inputItk = ImageType::New();
00255 mitk::CastToItkImage( inputMitk , inputItk );
00256
00257
00258 ImageType::RegionType origRegion = inputItk->GetLargestPossibleRegion();
00259
00260
00261 maxima = inputItk->GetLargestPossibleRegion().GetIndex();
00262 minima[0] = inputItk->GetLargestPossibleRegion().GetSize()[0];
00263 minima[1] = inputItk->GetLargestPossibleRegion().GetSize()[1];
00264 minima[2] = inputItk->GetLargestPossibleRegion().GetSize()[2];
00265
00266 typedef itk::ImageRegionConstIterator< ImageType > ConstIteratorType;
00267
00268 for(unsigned int idx = 0; idx < timeSteps; ++idx)
00269 {
00270
00271 if( idx > 0)
00272 {
00273 m_TimeSelector->SetTimeNr( idx );
00274 m_TimeSelector->UpdateLargestPossibleRegion();
00275 inputMitk = m_TimeSelector->GetOutput();
00276 mitk::CastToItkImage( inputMitk , inputItk );
00277 }
00278
00279 ConstIteratorType inIt( inputItk, origRegion );
00280
00281 for ( inIt.GoToBegin(); !inIt.IsAtEnd(); ++inIt)
00282 {
00283 float pix_val = inIt.Get();
00284 if ( fabs(pix_val - m_BackgroundValue) > mitk::eps )
00285 {
00286 for (int i=0; i < 3; i++)
00287 {
00288 minima[i] = vnl_math_min((int)minima[i],(int)(inIt.GetIndex()[i]));
00289 maxima[i] = vnl_math_max((int)maxima[i],(int)(inIt.GetIndex()[i]));
00290 }
00291 }
00292 }
00293 }
00294
00295 typedef ImageType::RegionType::SizeType::SizeValueType SizeValueType;
00296
00297 m_RegionSize[0] = (SizeValueType)(m_MarginFactor * (maxima[0] - minima[0] + 1 ));
00298 m_RegionSize[1] = (SizeValueType)(m_MarginFactor * (maxima[1] - minima[1] + 1 ));
00299 m_RegionSize[2] = (SizeValueType)(m_MarginFactor * (maxima[2] - minima[2] + 1 ));
00300 m_RegionIndex = minima;
00301
00302 m_RegionIndex[0] -= (m_RegionSize[0] - maxima[0] + minima[0] - 1 )/2;
00303 m_RegionIndex[1] -= (m_RegionSize[1] - maxima[1] + minima[1] - 1 )/2;
00304 m_RegionIndex[2] -= (m_RegionSize[2] - maxima[2] + minima[2] - 1 )/2;
00305
00306 ImageType::RegionType cropRegion(m_RegionIndex,m_RegionSize);
00307 origRegion.Crop(cropRegion);
00308
00309 m_RegionSize[0] = origRegion.GetSize()[0];
00310 m_RegionSize[1] = origRegion.GetSize()[1];
00311 m_RegionSize[2] = origRegion.GetSize()[2];
00312
00313 m_RegionIndex[0] = origRegion.GetIndex()[0];
00314 m_RegionIndex[1] = origRegion.GetIndex()[1];
00315 m_RegionIndex[2] = origRegion.GetIndex()[2];
00316
00317 m_LowerBounds[0] = m_RegionIndex[0];
00318 m_LowerBounds[1] = m_RegionIndex[1];
00319 m_LowerBounds[2] = m_RegionIndex[2];
00320
00321
00322
00323 m_UpperBounds[0] = inputItk->GetLargestPossibleRegion().GetSize()[0]-m_RegionSize[0]-m_RegionIndex[0];
00324 m_UpperBounds[1] = inputItk->GetLargestPossibleRegion().GetSize()[1]-m_RegionSize[1]-m_RegionIndex[1];
00325 m_UpperBounds[2] = inputItk->GetLargestPossibleRegion().GetSize()[2]-m_RegionSize[2]-m_RegionIndex[2];
00326 }
00327 }
00328
00329
00330 void mitk::AutoCropImageFilter::GenerateInputRequestedRegion()
00331 {
00332
00333 }
00334
00335 const std::type_info& mitk::AutoCropImageFilter::GetOutputPixelType()
00336 {
00337 return *this->GetInput()->GetPixelType().GetTypeId();
00338 }
00339
00340 void mitk::AutoCropImageFilter::SetCroppingRegion(RegionType overrideRegion)
00341 {
00342 m_CroppingRegion = overrideRegion;
00343 m_OverrideCroppingRegion = true;
00344 }