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 <mitkLabeledImageToSurfaceFilter.h>
00019
00020 #include <vtkImageChangeInformation.h>
00021 #include <vtkImageThreshold.h>
00022 #include <vtkImageGaussianSmooth.h>
00023 #include <vtkImageMarchingCubes.h>
00024 #include <vtkPolyData.h>
00025 #include <vtkSmoothPolyDataFilter.h>
00026 #include <vtkDecimatePro.h>
00027 #if (VTK_MAJOR_VERSION < 5)
00028 #include <vtkDecimate.h>
00029 #endif
00030 #include <vtkLinearTransform.h>
00031 #include <vtkMatrix4x4.h>
00032
00033 #include <mitkImageAccessByItk.h>
00034 #include <itkImageRegionIterator.h>
00035 #include <itkNumericTraits.h>
00036
00037
00038 mitk::LabeledImageToSurfaceFilter::LabeledImageToSurfaceFilter() :
00039 m_GaussianStandardDeviation(1.5),
00040 m_GenerateAllLabels(true),
00041 m_Label(1),
00042 m_BackgroundLabel(0)
00043 {
00044 }
00045
00046 mitk::LabeledImageToSurfaceFilter::~LabeledImageToSurfaceFilter()
00047 {
00048 }
00049
00050 void mitk::LabeledImageToSurfaceFilter::GenerateOutputInformation()
00051 {
00052 Superclass::GenerateOutputInformation();
00053
00054
00055
00056 m_AvailableLabels = this->GetAvailableLabels();
00057 m_IdxToLabels.clear();
00058
00059
00060
00061
00062
00063
00064 if ( ! m_GenerateAllLabels )
00065 {
00066 LabelMapType tmp;
00067 LabelMapType::iterator it;
00068 it = m_AvailableLabels.find( m_Label );
00069 if ( it != m_AvailableLabels.end() )
00070 tmp[m_Label] = it->second;
00071 else
00072 tmp[m_Label] = 0;
00073
00074 it = m_AvailableLabels.find( m_BackgroundLabel );
00075 if ( it != m_AvailableLabels.end() )
00076 tmp[m_BackgroundLabel] = it->second;
00077 else
00078 tmp[m_BackgroundLabel] = 0;
00079
00080 m_AvailableLabels = tmp;
00081 }
00082
00083
00084
00085
00086
00087
00088
00089
00090 unsigned int numberOfOutputs = 0;
00091 if ( m_AvailableLabels.find( m_BackgroundLabel ) == m_AvailableLabels.end() )
00092 numberOfOutputs = m_AvailableLabels.size();
00093 else
00094 numberOfOutputs = m_AvailableLabels.size() - 1;
00095 if ( numberOfOutputs == 0 )
00096 {
00097 itkWarningMacro("Number of outputs == 0");
00098 }
00099
00100
00101
00102
00103 mitk::Image* image = ( mitk::Image* )GetInput();
00104 unsigned int numberOfTimeSteps = image->GetTimeSlicedGeometry()->GetTimeSteps();
00105
00106
00107
00108
00109
00110 this->SetNumberOfOutputs( numberOfOutputs );
00111 this->SetNumberOfRequiredOutputs( numberOfOutputs );
00112 for ( unsigned int i = 0 ; i < numberOfOutputs; ++i )
00113 {
00114 if ( ! this->GetOutput( i ) )
00115 {
00116 mitk::Surface::Pointer output = static_cast<mitk::Surface*>( this->MakeOutput(0).GetPointer() );
00117 assert ( output.IsNotNull() );
00118 output->Expand( numberOfTimeSteps );
00119 this->SetNthOutput( i, output.GetPointer() );
00120 }
00121 }
00122 }
00123
00124
00125 void mitk::LabeledImageToSurfaceFilter::GenerateData()
00126 {
00127 mitk::Image* image = ( mitk::Image* )GetInput();
00128 if ( image == NULL )
00129 {
00130 itkWarningMacro("Image is NULL");
00131 return;
00132 }
00133
00134 mitk::Image::RegionType outputRegion = image->GetRequestedRegion();
00135
00136 m_IdxToLabels.clear();
00137
00138 if ( this->GetNumberOfOutputs() == 0 )
00139 return;
00140
00141
00142
00143
00144 unsigned int currentOutputIndex = 0;
00145 for ( LabelMapType::iterator it = m_AvailableLabels.begin() ; it != m_AvailableLabels.end() ; ++it )
00146 {
00147 if ( it->first == m_BackgroundLabel )
00148 continue;
00149 if ( ( it->second == 0 ) && m_GenerateAllLabels )
00150 continue;
00151
00152 assert ( currentOutputIndex < this->GetNumberOfOutputs() );
00153 mitk::Surface::Pointer surface = this->GetOutput( currentOutputIndex );
00154 assert( surface.IsNotNull() );
00155
00156 int tstart=outputRegion.GetIndex(3);
00157 int tmax=tstart+outputRegion.GetSize(3);
00158 int t;
00159 for( t=tstart; t < tmax; ++t)
00160 {
00161 vtkImageData *vtkimagedata = image->GetVtkImageData( t );
00162 CreateSurface( t,vtkimagedata,surface.GetPointer(), it->first );
00163 }
00164 m_IdxToLabels[ currentOutputIndex ] = it->first;
00165 currentOutputIndex++;
00166 }
00167 }
00168
00169 void mitk::LabeledImageToSurfaceFilter::CreateSurface( int time, vtkImageData *vtkimage, mitk::Surface * surface, mitk::LabeledImageToSurfaceFilter::LabelType label )
00170 {
00171 vtkImageChangeInformation *indexCoordinatesImageFilter = vtkImageChangeInformation::New();
00172 indexCoordinatesImageFilter->SetInput(vtkimage);
00173 indexCoordinatesImageFilter->SetOutputOrigin(0.0,0.0,0.0);
00174
00175 vtkImageThreshold* threshold = vtkImageThreshold::New();
00176 threshold->SetInput( indexCoordinatesImageFilter->GetOutput() );
00177
00178 threshold->SetInValue( 100 );
00179 threshold->SetOutValue( 0 );
00180 threshold->ThresholdBetween( label, label );
00181 threshold->SetOutputScalarTypeToUnsignedChar();
00182 threshold->ReleaseDataFlagOn();
00183
00184 vtkImageGaussianSmooth *gaussian = vtkImageGaussianSmooth::New();
00185 gaussian->SetInput( threshold->GetOutput() );
00186
00187 gaussian->SetDimensionality( 3 );
00188 gaussian->SetRadiusFactor( 0.49 );
00189 gaussian->SetStandardDeviation( GetGaussianStandardDeviation() );
00190 gaussian->ReleaseDataFlagOn();
00191 gaussian->UpdateInformation();
00192 gaussian->Update();
00193
00194
00195 vtkMarchingCubes *skinExtractor = vtkMarchingCubes::New();
00196 skinExtractor->ReleaseDataFlagOn();
00197 skinExtractor->SetInput(gaussian->GetOutput());
00198 indexCoordinatesImageFilter->Delete();
00199 skinExtractor->SetValue(0, 50);
00200
00201 vtkPolyData *polydata;
00202 polydata = skinExtractor->GetOutput();
00203 polydata->Register(NULL);
00204 skinExtractor->Delete();
00205
00206 if (m_Smooth)
00207 {
00208 vtkSmoothPolyDataFilter *smoother = vtkSmoothPolyDataFilter::New();
00209
00210 smoother->SetInput(polydata);
00211 smoother->SetNumberOfIterations( m_SmoothIteration );
00212 smoother->SetRelaxationFactor( m_SmoothRelaxation );
00213 smoother->SetFeatureAngle( 60 );
00214 smoother->FeatureEdgeSmoothingOff();
00215 smoother->BoundarySmoothingOff();
00216 smoother->SetConvergence( 0 );
00217
00218 polydata->Delete();
00219 polydata = smoother->GetOutput();
00220 polydata->Register(NULL);
00221 smoother->Delete();
00222 }
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235 if(m_Decimate==DecimatePro)
00236 {
00237 vtkDecimatePro *decimate = vtkDecimatePro::New();
00238 decimate->SplittingOff();
00239 decimate->SetErrorIsAbsolute(5);
00240 decimate->SetFeatureAngle(30);
00241 decimate->PreserveTopologyOn();
00242 decimate->BoundaryVertexDeletionOff();
00243 decimate->SetDegree(10);
00244
00245 decimate->SetInput(polydata);
00246 decimate->SetTargetReduction(m_TargetReduction);
00247 decimate->SetMaximumError(0.002);
00248
00249 polydata->Delete();
00250 polydata = decimate->GetOutput();
00251 polydata->Register(NULL);
00252 decimate->Delete();
00253 }
00254 #if (VTK_MAJOR_VERSION < 5)
00255 else if (m_Decimate==Decimate)
00256 {
00257 vtkDecimate *decimate = vtkDecimate::New();
00258 decimate->SetInput( polydata );
00259 decimate->PreserveTopologyOn();
00260 decimate->BoundaryVertexDeletionOff();
00261 decimate->SetTargetReduction( m_TargetReduction );
00262 polydata->Delete();
00263 polydata = decimate->GetOutput();
00264 polydata->Register(NULL);
00265 decimate->Delete();
00266 }
00267 #endif
00268
00269 polydata->Update();
00270
00271 polydata->SetSource(NULL);
00272
00273 if(polydata->GetNumberOfPoints() > 0)
00274 {
00275 mitk::Vector3D spacing = GetInput()->GetGeometry(time)->GetSpacing();
00276
00277 vtkPoints * points = polydata->GetPoints();
00278 vtkMatrix4x4 *vtkmatrix = vtkMatrix4x4::New();
00279 GetInput()->GetGeometry(time)->GetVtkTransform()->GetMatrix(vtkmatrix);
00280 double (*matrix)[4] = vtkmatrix->Element;
00281
00282 unsigned int i,j;
00283 for(i=0;i<3;++i)
00284 for(j=0;j<3;++j)
00285 matrix[i][j]/=spacing[j];
00286
00287 unsigned int n = points->GetNumberOfPoints();
00288 vtkFloatingPointType point[3];
00289
00290 for (i = 0; i < n; i++)
00291 {
00292 points->GetPoint(i, point);
00293 mitkVtkLinearTransformPoint(matrix,point,point);
00294 points->SetPoint(i, point);
00295 }
00296 vtkmatrix->Delete();
00297 }
00298
00299 surface->SetVtkPolyData(polydata, time);
00300 polydata->UnRegister(NULL);
00301
00302 gaussian->Delete();
00303 threshold->Delete();
00304 }
00305
00306 template < typename TPixel, unsigned int VImageDimension >
00307 void GetAvailableLabelsInternal( itk::Image<TPixel, VImageDimension>* image, mitk::LabeledImageToSurfaceFilter::LabelMapType& availableLabels )
00308 {
00309 typedef itk::Image<TPixel, VImageDimension> ImageType;
00310 typedef itk::ImageRegionIterator< ImageType > ImageRegionIteratorType;
00311 availableLabels.clear();
00312 ImageRegionIteratorType it( image, image->GetLargestPossibleRegion() );
00313 it.GoToBegin();
00314 mitk::LabeledImageToSurfaceFilter::LabelMapType::iterator labelIt;
00315 while( ! it.IsAtEnd() )
00316 {
00317 labelIt = availableLabels.find( ( mitk::LabeledImageToSurfaceFilter::LabelType ) ( it.Get() ) );
00318 if ( labelIt == availableLabels.end() )
00319 {
00320 availableLabels[ ( mitk::LabeledImageToSurfaceFilter::LabelType ) ( it.Get() ) ] = 1;
00321 }
00322 else
00323 {
00324 labelIt->second += 1;
00325 }
00326
00327 ++it;
00328 }
00329 }
00330
00331 InstantiateAccessFunctionForFixedDimension_1(GetAvailableLabelsInternal, 3, mitk::LabeledImageToSurfaceFilter::LabelMapType&);
00332
00333
00334 mitk::LabeledImageToSurfaceFilter::LabelMapType mitk::LabeledImageToSurfaceFilter::GetAvailableLabels()
00335 {
00336 mitk::Image::Pointer image = ( mitk::Image* )GetInput();
00337 LabelMapType availableLabels;
00338 AccessFixedDimensionByItk_1( image, GetAvailableLabelsInternal, 3, availableLabels );
00339 return availableLabels;
00340 }
00341
00342
00343 void mitk::LabeledImageToSurfaceFilter::CreateSurface(int, vtkImageData*, mitk::Surface*, const ScalarType)
00344 {
00345 itkWarningMacro( "This function should never be called!" );
00346 assert(false);
00347 }
00348
00349 mitk::LabeledImageToSurfaceFilter::LabelType mitk::LabeledImageToSurfaceFilter::GetLabelForNthOutput( const unsigned int& idx )
00350 {
00351 IdxToLabelMapType::iterator it = m_IdxToLabels.find( idx );
00352 if ( it != m_IdxToLabels.end() )
00353 {
00354 return it->second;
00355 }
00356 else
00357 {
00358 itkWarningMacro( "Unknown index encountered: " << idx << ". There are " << this->GetNumberOfOutputs() << " outputs available." );
00359 return itk::NumericTraits<LabelType>::max();
00360 }
00361 }
00362
00363 mitk::ScalarType mitk::LabeledImageToSurfaceFilter::GetVolumeForNthOutput( const unsigned int& i )
00364 {
00365 return GetVolumeForLabel( GetLabelForNthOutput( i ) );
00366 }
00367
00368 mitk::ScalarType mitk::LabeledImageToSurfaceFilter::GetVolumeForLabel( const mitk::LabeledImageToSurfaceFilter::LabelType& label )
00369 {
00370
00371 mitk::Image* image = ( mitk::Image* )GetInput();
00372 const float* spacing = image->GetSlicedGeometry()->GetFloatSpacing();
00373
00374
00375
00376 LabelMapType::iterator it = m_AvailableLabels.find( label );
00377 if ( it != m_AvailableLabels.end() )
00378 {
00379 return static_cast<float>(it->second) * ( spacing[0] * spacing[1] * spacing[2] / 1000.0f );
00380 }
00381 else
00382 {
00383 itkWarningMacro( "Unknown label encountered: " << label );
00384 return 0.0;
00385 }
00386 }
00387
00388