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/algo/vnl_symmetric_eigensystem.h"
00027
#include "vnl/vnl_math.h"
00028
00029
namespace itk
00030 {
00132
template <
typename TInputImage,
00133
typename TRealType =
float,
00134
typename TOutputImage = Image< TRealType,
00135 ::itk::GetImageDimension<TInputImage>::ImageDimension >
00136 >
00137 class ITK_EXPORT VectorGradientMagnitudeImageFilter :
00138
public ImageToImageFilter< TInputImage, TOutputImage >
00139 {
00140
public:
00142 typedef VectorGradientMagnitudeImageFilter
Self;
00143 typedef ImageToImageFilter< TInputImage, TOutputImage > Superclass;
00144 typedef SmartPointer<Self> Pointer;
00145 typedef SmartPointer<const Self> ConstPointer;
00146
00148
itkNewMacro(
Self);
00149
00151
itkTypeMacro(VectorGradientMagnitudeImageFilter,
ImageToImageFilter);
00152
00155 typedef typename TOutputImage::PixelType
OutputPixelType;
00156 typedef typename TInputImage::PixelType
InputPixelType;
00157
00159 typedef TInputImage
InputImageType;
00160 typedef TOutputImage
OutputImageType;
00161 typedef typename InputImageType::Pointer
InputImagePointer;
00162 typedef typename OutputImageType::Pointer
OutputImagePointer;
00163
00165
itkStaticConstMacro(ImageDimension,
unsigned int,
00166 TOutputImage::ImageDimension);
00167
00169
itkStaticConstMacro(VectorDimension,
unsigned int,
00170 InputPixelType::Dimension);
00171
00173 typedef TRealType
RealType;
00174 typedef Vector<TRealType, ::itk::GetVectorDimension<InputPixelType>::VectorDimension>
RealVectorType;
00175 typedef Image<RealVectorType, ::itk::GetImageDimension<TInputImage>::ImageDimension>
RealVectorImageType;
00176
00177
00180 typedef ConstNeighborhoodIterator<RealVectorImageType> ConstNeighborhoodIteratorType;
00181
00183 typedef typename Superclass::OutputImageRegionType
OutputImageRegionType;
00184
00193
virtual void GenerateInputRequestedRegion() throw(
InvalidRequestedRegionError);
00194
00198 void SetUseImageSpacingOn()
00199 { this->SetUseImageSpacing(
true); }
00200
00204 void SetUseImageSpacingOff()
00205 { this->SetUseImageSpacing(
false); }
00206
00209
void SetUseImageSpacing(
bool);
00210
itkGetMacro(UseImageSpacing,
bool);
00211
00214
void SetDerivativeWeights(TRealType data[]);
00215
itkGetVectorMacro(DerivativeWeights,
const TRealType,
itk::GetImageDimension<TInputImage>::ImageDimension);
00216
00219
itkSetVectorMacro(ComponentWeights, TRealType,
itk::GetVectorDimension<InputPixelType>::VectorDimension);
00220
itkGetVectorMacro(ComponentWeights,
const TRealType,
itk::GetVectorDimension<InputPixelType>::VectorDimension);
00221
00227
itkSetMacro(UsePrincipleComponents,
bool);
00228
itkGetMacro(UsePrincipleComponents,
bool);
00229
void SetUsePrincipleComponentsOn()
00230 {
00231 this->SetUsePrincipleComponents(
true);
00232 }
00233
void SetUsePrincipleComponentsOff()
00234 {
00235 this->SetUsePrincipleComponents(
false);
00236 }
00237
00240
static int CubicSolver(
double *,
double *);
00241
00242
protected:
00243 VectorGradientMagnitudeImageFilter();
00244
virtual ~VectorGradientMagnitudeImageFilter() {}
00245
00249
void BeforeThreadedGenerateData ();
00250
00262
void ThreadedGenerateData(
const OutputImageRegionType& outputRegionForThread,
00263
int threadId );
00264
00265
void PrintSelf(std::ostream& os, Indent indent)
const;
00266
00267 TRealType NonPCEvaluateAtNeighborhood(
const ConstNeighborhoodIteratorType &it)
const
00268
{
00269
unsigned i, j;
00270 TRealType dx, sum, accum;
00271 accum =
NumericTraits<TRealType>::Zero;
00272
for (i = 0; i < ImageDimension; ++i)
00273 {
00274 sum =
NumericTraits<TRealType>::Zero;
00275
for (j = 0; j < VectorDimension; ++j)
00276 {
00277 dx = m_DerivativeWeights[i] * m_SqrtComponentWeights[j]
00278 * 0.5 * (it.GetNext(i)[j] - it.GetPrevious(i)[j]);
00279 sum += dx * dx;
00280 }
00281 accum += sum;
00282 }
00283
return vcl_sqrt(accum);
00284 }
00285
00286 TRealType EvaluateAtNeighborhood3D(
const ConstNeighborhoodIteratorType &it)
const
00287
{
00288
00289
unsigned int i, j;
00290 double Lambda[3];
00291
double CharEqn[3];
00292
double ans;
00293
00294
vnl_matrix<TRealType> g(ImageDimension, ImageDimension);
00295 vnl_vector_fixed<TRealType, VectorDimension>
00296 d_phi_du[
itk::GetImageDimension<TInputImage>::ImageDimension];
00297
00298
00299
00300
for (i = 0; i < ImageDimension; i++)
00301 {
00302
for (j = 0; j < VectorDimension; j++)
00303 { d_phi_du[i][j] = m_DerivativeWeights[i] * m_SqrtComponentWeights[j]
00304 * 0.5 * (it.GetNext(i)[j] - it.GetPrevious(i)[j]); }
00305 }
00306
00307
00308
for (i = 0; i < ImageDimension; i++)
00309 {
00310
for (j = i; j < ImageDimension; j++)
00311 {
00312 g[j][i] = g[i][j] = dot_product(d_phi_du[i], d_phi_du[j]);
00313 }
00314 }
00315
00316
00317
00318
00319 CharEqn[2] = -( g[0][0] + g[1][1] + g[2][2] );
00320
00321 CharEqn[1] =(g[0][0]*g[1][1] + g[0][0]*g[2][2] + g[1][1]*g[2][2])
00322 - (g[0][1]*g[1][0] + g[0][2]*g[2][0] + g[1][2]*g[2][1]);
00323
00324 CharEqn[0] = g[0][0] * ( g[1][2]*g[2][1] - g[1][1]*g[2][2] ) +
00325 g[1][0] * ( g[2][2]*g[0][1] - g[0][2]*g[2][1] ) +
00326 g[2][0] * ( g[1][1]*g[0][2] - g[0][1]*g[1][2] );
00327
00328
00329
00330
00331
00332
int numberOfDistinctRoots = this->CubicSolver(CharEqn, Lambda);
00333
00334
00335
00336
if (numberOfDistinctRoots == 3)
00337 {
00338
if (Lambda[0] > Lambda[1])
00339 {
00340
if ( Lambda[1] > Lambda[2] )
00341 { ans = Lambda[0] - Lambda[1]; }
00342
else
00343 {
00344
if ( Lambda[0] > Lambda[2] )
00345 { ans = Lambda[0] - Lambda[2]; }
00346
else
00347 { ans = Lambda[2] - Lambda[0]; }
00348 }
00349 }
00350
else
00351 {
00352
if ( Lambda[0] > Lambda[2] )
00353 { ans = Lambda[1] - Lambda[0]; }
00354
else
00355 {
00356
if ( Lambda[1] > Lambda[2] )
00357 { ans = Lambda[1] - Lambda[2]; }
00358
else
00359 { ans = Lambda[2] - Lambda[1]; }
00360 }
00361 }
00362 }
00363
else if (numberOfDistinctRoots == 2)
00364 {
00365
if ( Lambda[0] > Lambda[1] )
00366 { ans = Lambda[0] - Lambda[1]; }
00367
else
00368 { ans = Lambda[1] - Lambda[0]; }
00369 }
00370
else if (numberOfDistinctRoots == 1)
00371 {
00372 ans = 0.0;
00373 }
00374
else
00375 {
00376
itkExceptionMacro( <<
"Undefined condition. Cubic root solver returned "
00377 << numberOfDistinctRoots <<
" distinct roots." );
00378 }
00379
00380
return ans;
00381 }
00382
00383
00384
00385 TRealType EvaluateAtNeighborhood(
const ConstNeighborhoodIteratorType &it)
const
00386
{
00387
unsigned int i, j;
00388
vnl_matrix<TRealType> g(ImageDimension, ImageDimension);
00389 vnl_vector_fixed<TRealType, VectorDimension>
00390 d_phi_du[
itk::GetImageDimension<TInputImage>::ImageDimension];
00391
00392
00393
00394
for (i = 0; i < ImageDimension; i++)
00395 {
00396
for (j = 0; j < VectorDimension; j++)
00397 { d_phi_du[i][j] = m_DerivativeWeights[i] * m_SqrtComponentWeights[j]
00398 * 0.5 * (it.GetNext(i)[j] - it.GetPrevious(i)[j] ); }
00399 }
00400
00401
00402
for (i = 0; i < ImageDimension; i++)
00403 {
00404
for (j = i; j < ImageDimension; j++)
00405 {
00406 g[j][i] = g[i][j] = dot_product(d_phi_du[i], d_phi_du[j]);
00407 }
00408 }
00409
00410
00411 vnl_symmetric_eigensystem<TRealType> E(g);
00412
00413
00414
00415
return ( E.get_eigenvalue(ImageDimension - 1) - E.get_eigenvalue(ImageDimension - 2) );
00416 }
00417
00419 TRealType m_DerivativeWeights[
itk::GetImageDimension<TInputImage>::ImageDimension];
00420
00424 TRealType m_ComponentWeights[
itk::GetVectorDimension<InputPixelType>::VectorDimension];
00425 TRealType m_SqrtComponentWeights[
itk::GetVectorDimension<InputPixelType>::VectorDimension];
00426
00427
private:
00428 bool m_UseImageSpacing;
00429 bool m_UsePrincipleComponents;
00430
int m_RequestedNumberOfThreads;
00431
00432
typedef typename InputImageType::Superclass ImageBaseType;
00433
00434
typename ImageBaseType::ConstPointer m_RealValuedInputImage;
00435
00436 VectorGradientMagnitudeImageFilter(
const Self&);
00437
void operator=(
const Self&);
00438
00439
typename ConstNeighborhoodIteratorType::RadiusType m_NeighborhoodRadius;
00440 };
00441
00442 }
00443
00444
#ifndef ITK_MANUAL_INSTANTIATION
00445
#include "itkVectorGradientMagnitudeImageFilter.txx"
00446
#endif
00447
00448
#endif