00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef __itkVectorGradientMagnitudeImageFilter_h
00018 #define __itkVectorGradientMagnitudeImageFilter_h
00019
00020 #include "itkConstNeighborhoodIterator.h"
00021 #include "itkNeighborhoodIterator.h"
00022 #include "itkImageToImageFilter.h"
00023 #include "itkImage.h"
00024 #include "itkVector.h"
00025 #include "vnl/vnl_matrix.h"
00026 #include "vnl/vnl_vector_fixed.h"
00027 #include "vnl/algo/vnl_symmetric_eigensystem.h"
00028 #include "vnl/vnl_math.h"
00029
00030 namespace itk
00031 {
00133 template < typename TInputImage,
00134 typename TRealType = float,
00135 typename TOutputImage = Image< TRealType,
00136 ::itk::GetImageDimension<TInputImage>::ImageDimension >
00137 >
00138 class ITK_EXPORT VectorGradientMagnitudeImageFilter :
00139 public ImageToImageFilter< TInputImage, TOutputImage >
00140 {
00141 public:
00143 typedef VectorGradientMagnitudeImageFilter Self;
00144 typedef ImageToImageFilter< TInputImage, TOutputImage > Superclass;
00145 typedef SmartPointer<Self> Pointer;
00146 typedef SmartPointer<const Self> ConstPointer;
00147
00149 itkNewMacro(Self);
00150
00152 itkTypeMacro(VectorGradientMagnitudeImageFilter, ImageToImageFilter);
00153
00156 typedef typename TOutputImage::PixelType OutputPixelType;
00157 typedef typename TInputImage::PixelType InputPixelType;
00158
00160 typedef TInputImage InputImageType;
00161 typedef TOutputImage OutputImageType;
00162 typedef typename InputImageType::Pointer InputImagePointer;
00163 typedef typename OutputImageType::Pointer OutputImagePointer;
00164
00166 itkStaticConstMacro(ImageDimension, unsigned int,
00167 TOutputImage::ImageDimension);
00168
00170 itkStaticConstMacro(VectorDimension, unsigned int,
00171 InputPixelType::Dimension);
00172
00174 typedef TRealType RealType;
00175 typedef Vector<TRealType, ::itk::GetVectorDimension<InputPixelType>::VectorDimension> RealVectorType;
00176 typedef Image<RealVectorType, ::itk::GetImageDimension<TInputImage>::ImageDimension> RealVectorImageType;
00177
00178
00181 typedef ConstNeighborhoodIterator<RealVectorImageType> ConstNeighborhoodIteratorType;
00182 typedef typename ConstNeighborhoodIteratorType::RadiusType RadiusType;
00183
00185 typedef typename Superclass::OutputImageRegionType OutputImageRegionType;
00186
00195 virtual void GenerateInputRequestedRegion() throw(InvalidRequestedRegionError);
00196
00200 void SetUseImageSpacingOn()
00201 { this->SetUseImageSpacing(true); }
00202
00206 void SetUseImageSpacingOff()
00207 { this->SetUseImageSpacing(false); }
00208
00211 void SetUseImageSpacing(bool);
00212 itkGetMacro(UseImageSpacing, bool);
00213
00216 void SetDerivativeWeights(TRealType data[]);
00217 itkGetVectorMacro(DerivativeWeights, const TRealType, itk::GetImageDimension<TInputImage>::ImageDimension);
00218
00221 itkSetVectorMacro(ComponentWeights, TRealType, itk::GetVectorDimension<InputPixelType>::VectorDimension);
00222 itkGetVectorMacro(ComponentWeights, const TRealType, itk::GetVectorDimension<InputPixelType>::VectorDimension);
00223
00229 itkSetMacro(UsePrincipleComponents, bool);
00230 itkGetMacro(UsePrincipleComponents, bool);
00231 void SetUsePrincipleComponentsOn()
00232 {
00233 this->SetUsePrincipleComponents(true);
00234 }
00235 void SetUsePrincipleComponentsOff()
00236 {
00237 this->SetUsePrincipleComponents(false);
00238 }
00239
00242 static int CubicSolver(double *, double *);
00243
00244 protected:
00245 VectorGradientMagnitudeImageFilter();
00246 virtual ~VectorGradientMagnitudeImageFilter() {}
00247
00251 void BeforeThreadedGenerateData ();
00252
00264 void ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread,
00265 int threadId );
00266
00267 void PrintSelf(std::ostream& os, Indent indent) const;
00268
00269 typedef typename InputImageType::Superclass ImageBaseType;
00270
00272 itkGetConstObjectMacro( RealValuedInputImage, ImageBaseType );
00273
00275 itkGetConstReferenceMacro( NeighborhoodRadius, RadiusType );
00276 itkSetMacro( NeighborhoodRadius, RadiusType );
00277
00278
00279 TRealType NonPCEvaluateAtNeighborhood(const ConstNeighborhoodIteratorType &it) const
00280 {
00281 unsigned i, j;
00282 TRealType dx, sum, accum;
00283 accum = NumericTraits<TRealType>::Zero;
00284 for (i = 0; i < ImageDimension; ++i)
00285 {
00286 sum = NumericTraits<TRealType>::Zero;
00287 for (j = 0; j < VectorDimension; ++j)
00288 {
00289 dx = m_DerivativeWeights[i] * m_SqrtComponentWeights[j]
00290 * 0.5 * (it.GetNext(i)[j] - it.GetPrevious(i)[j]);
00291 sum += dx * dx;
00292 }
00293 accum += sum;
00294 }
00295 return vcl_sqrt(accum);
00296 }
00297
00298 TRealType EvaluateAtNeighborhood3D(const ConstNeighborhoodIteratorType &it) const
00299 {
00300
00301 unsigned int i, j;
00302 double Lambda[3];
00303 double CharEqn[3];
00304 double ans;
00305
00306 vnl_matrix<TRealType> g(ImageDimension, ImageDimension);
00307 vnl_vector_fixed<TRealType, VectorDimension>
00308 d_phi_du[itk::GetImageDimension<TInputImage>::ImageDimension];
00309
00310
00311
00312 for (i = 0; i < ImageDimension; i++)
00313 {
00314 for (j = 0; j < VectorDimension; j++)
00315 { d_phi_du[i][j] = m_DerivativeWeights[i] * m_SqrtComponentWeights[j]
00316 * 0.5 * (it.GetNext(i)[j] - it.GetPrevious(i)[j]); }
00317 }
00318
00319
00320 for (i = 0; i < ImageDimension; i++)
00321 {
00322 for (j = i; j < ImageDimension; j++)
00323 {
00324 g[j][i] = g[i][j] = dot_product(d_phi_du[i], d_phi_du[j]);
00325 }
00326 }
00327
00328
00329
00330
00331 CharEqn[2] = -( g[0][0] + g[1][1] + g[2][2] );
00332
00333 CharEqn[1] =(g[0][0]*g[1][1] + g[0][0]*g[2][2] + g[1][1]*g[2][2])
00334 - (g[0][1]*g[1][0] + g[0][2]*g[2][0] + g[1][2]*g[2][1]);
00335
00336 CharEqn[0] = g[0][0] * ( g[1][2]*g[2][1] - g[1][1]*g[2][2] ) +
00337 g[1][0] * ( g[2][2]*g[0][1] - g[0][2]*g[2][1] ) +
00338 g[2][0] * ( g[1][1]*g[0][2] - g[0][1]*g[1][2] );
00339
00340
00341
00342
00343
00344 int numberOfDistinctRoots = this->CubicSolver(CharEqn, Lambda);
00345
00346
00347
00348 if (numberOfDistinctRoots == 3)
00349 {
00350 if (Lambda[0] > Lambda[1])
00351 {
00352 if ( Lambda[1] > Lambda[2] )
00353 { ans = Lambda[0] - Lambda[1]; }
00354 else
00355 {
00356 if ( Lambda[0] > Lambda[2] )
00357 { ans = Lambda[0] - Lambda[2]; }
00358 else
00359 { ans = Lambda[2] - Lambda[0]; }
00360 }
00361 }
00362 else
00363 {
00364 if ( Lambda[0] > Lambda[2] )
00365 { ans = Lambda[1] - Lambda[0]; }
00366 else
00367 {
00368 if ( Lambda[1] > Lambda[2] )
00369 { ans = Lambda[1] - Lambda[2]; }
00370 else
00371 { ans = Lambda[2] - Lambda[1]; }
00372 }
00373 }
00374 }
00375 else if (numberOfDistinctRoots == 2)
00376 {
00377 if ( Lambda[0] > Lambda[1] )
00378 { ans = Lambda[0] - Lambda[1]; }
00379 else
00380 { ans = Lambda[1] - Lambda[0]; }
00381 }
00382 else if (numberOfDistinctRoots == 1)
00383 {
00384 ans = 0.0;
00385 }
00386 else
00387 {
00388 itkExceptionMacro( << "Undefined condition. Cubic root solver returned "
00389 << numberOfDistinctRoots << " distinct roots." );
00390 }
00391
00392 return ans;
00393 }
00394
00395
00396
00397 TRealType EvaluateAtNeighborhood(const ConstNeighborhoodIteratorType &it) const
00398 {
00399 unsigned int i, j;
00400 vnl_matrix<TRealType> g(ImageDimension, ImageDimension);
00401 vnl_vector_fixed<TRealType, VectorDimension>
00402 d_phi_du[itk::GetImageDimension<TInputImage>::ImageDimension];
00403
00404
00405
00406 for (i = 0; i < ImageDimension; i++)
00407 {
00408 for (j = 0; j < VectorDimension; j++)
00409 { d_phi_du[i][j] = m_DerivativeWeights[i] * m_SqrtComponentWeights[j]
00410 * 0.5 * (it.GetNext(i)[j] - it.GetPrevious(i)[j] ); }
00411 }
00412
00413
00414 for (i = 0; i < ImageDimension; i++)
00415 {
00416 for (j = i; j < ImageDimension; j++)
00417 {
00418 g[j][i] = g[i][j] = dot_product(d_phi_du[i], d_phi_du[j]);
00419 }
00420 }
00421
00422
00423 vnl_symmetric_eigensystem<TRealType> E(g);
00424
00425
00426
00427 return ( E.get_eigenvalue(ImageDimension - 1) - E.get_eigenvalue(ImageDimension - 2) );
00428 }
00429
00431 TRealType m_DerivativeWeights[itk::GetImageDimension<TInputImage>::ImageDimension];
00432
00436 TRealType m_ComponentWeights[itk::GetVectorDimension<InputPixelType>::VectorDimension];
00437 TRealType m_SqrtComponentWeights[itk::GetVectorDimension<InputPixelType>::VectorDimension];
00438
00439 private:
00440 bool m_UseImageSpacing;
00441 bool m_UsePrincipleComponents;
00442 int m_RequestedNumberOfThreads;
00443
00444
00445 typename ImageBaseType::ConstPointer m_RealValuedInputImage;
00446
00447 VectorGradientMagnitudeImageFilter(const Self&);
00448 void operator=(const Self&);
00449
00450 RadiusType m_NeighborhoodRadius;
00451 };
00452
00453 }
00454
00455 #ifndef ITK_MANUAL_INSTANTIATION
00456 #include "itkVectorGradientMagnitudeImageFilter.txx"
00457 #endif
00458
00459 #endif