121 * For algorithmic details see \cite sapiro1996.
123 * \ingroup GradientFilters
129 * \ingroup ITKImageGradient
131template <
typename TInputImage,
132 typename TRealType = float,
153 using OutputPixelType =
typename TOutputImage::PixelType;
154 using InputPixelType =
typename TInputImage::PixelType;
157 using InputImageType = TInputImage;
158 using OutputImageType = TOutputImage;
159 using InputImagePointer =
typename InputImageType::Pointer;
160 using OutputImagePointer =
typename OutputImageType::Pointer;
164 static constexpr unsigned int InputImageDimension = TInputImage::ImageDimension;
165 static constexpr unsigned int ImageDimension = TOutputImage::ImageDimension;
168 static constexpr unsigned int VectorDimension = InputPixelType::Dimension;
178 using RadiusType =
typename ConstNeighborhoodIteratorType::RadiusType;
181 using typename Superclass::OutputImageRegionType;
192 GenerateInputRequestedRegion()
override;
200 SetUseImageSpacing(
bool);
201 itkGetConstMacro(UseImageSpacing,
bool);
202 itkBooleanMacro(UseImageSpacing);
205#if !defined(ITK_FUTURE_LEGACY_REMOVE)
212 SetUseImageSpacingOn()
214 this->SetUseImageSpacing(
true);
222 SetUseImageSpacingOff()
224 this->SetUseImageSpacing(
false);
230#if !defined(ITK_LEGACY_REMOVE)
231 using WeightsType [[deprecated(
"Use DerivativeWeightsType or ComponentWeightsType instead.")]] = ComponentWeightsType;
236 itkSetMacro(DerivativeWeights, DerivativeWeightsType);
237 itkGetConstReferenceMacro(DerivativeWeights, DerivativeWeightsType);
242 itkSetMacro(ComponentWeights, ComponentWeightsType);
243 itkGetConstReferenceMacro(ComponentWeights, ComponentWeightsType);
256#if !defined(ITK_FUTURE_LEGACY_REMOVE)
259 SetUsePrincipleComponentsOn()
261 this->SetUsePrincipleComponents(
true);
266 SetUsePrincipleComponentsOff()
268 this->SetUsePrincipleComponents(
false);
275 CubicSolver(
const double *,
double *);
289 BeforeThreadedGenerateData()
override;
303 DynamicThreadedGenerateData(
const OutputImageRegionType & outputRegionForThread)
override;
307 PrintSelf(std::ostream & os,
Indent indent)
const override;
309 using ImageBaseType =
typename InputImageType::Superclass;
312 itkGetConstObjectMacro(RealValuedInputImage, RealVectorImageType);
315 NonPCEvaluateAtNeighborhood(
const ConstNeighborhoodIteratorType & it)
const
321 auto accum = TRealType{};
322 for (i = 0; i < ImageDimension; ++i)
325 for (j = 0; j < VectorDimension; ++j)
327 dx = m_DerivativeWeights[i] * m_SqrtComponentWeights[j] * 0.5 * (it.GetNext(i)[j] - it.GetPrevious(i)[j]);
332 return std::sqrt(accum);
336 EvaluateAtNeighborhood3D(
const ConstNeighborhoodIteratorType & it)
const
345 vnl_matrix<TRealType> g(ImageDimension, ImageDimension);
346 vnl_vector_fixed<TRealType, VectorDimension> d_phi_du[TInputImage::ImageDimension];
350 for (i = 0; i < ImageDimension; ++i)
352 for (j = 0; j < VectorDimension; ++j)
355 m_DerivativeWeights[i] * m_SqrtComponentWeights[j] * 0.5 * (it.GetNext(i)[j] - it.GetPrevious(i)[j]);
360 for (i = 0; i < ImageDimension; ++i)
362 for (j = i; j < ImageDimension; ++j)
364 g[j][i] = g[i][j] = dot_product(d_phi_du[i], d_phi_du[j]);
371 CharEqn[2] = -(g[0][0] + g[1][1] + g[2][2]);
373 CharEqn[1] = (g[0][0] * g[1][1] + g[0][0] * g[2][2] + g[1][1] * g[2][2]) -
374 (g[0][1] * g[1][0] + g[0][2] * g[2][0] + g[1][2] * g[2][1]);
376 CharEqn[0] = g[0][0] * (g[1][2] * g[2][1] - g[1][1] * g[2][2]) + g[1][0] * (g[2][2] * g[0][1] - g[0][2] * g[2][1]) +
377 g[2][0] * (g[1][1] * g[0][2] - g[0][1] * g[1][2]);
380 const int numberOfDistinctRoots = this->CubicSolver(CharEqn, Lambda);
384 if (numberOfDistinctRoots == 3)
386 if (Lambda[0] > Lambda[1])
388 if (Lambda[1] > Lambda[2])
390 ans = Lambda[0] - Lambda[1];
394 if (Lambda[0] > Lambda[2])
396 ans = Lambda[0] - Lambda[2];
400 ans = Lambda[2] - Lambda[0];
406 if (Lambda[0] > Lambda[2])
408 ans = Lambda[1] - Lambda[0];
412 if (Lambda[1] > Lambda[2])
414 ans = Lambda[1] - Lambda[2];
418 ans = Lambda[2] - Lambda[1];
423 else if (numberOfDistinctRoots == 2)
425 if (Lambda[0] > Lambda[1])
427 ans = Lambda[0] - Lambda[1];
431 ans = Lambda[1] - Lambda[0];
434 else if (numberOfDistinctRoots == 1)
440 itkExceptionMacro(
"Undefined condition. Cubic root solver returned " << numberOfDistinctRoots
441 <<
" distinct roots.");
451 EvaluateAtNeighborhood(
const ConstNeighborhoodIteratorType & it)
const
456 vnl_matrix<TRealType> g(ImageDimension, ImageDimension);
457 vnl_vector_fixed<TRealType, VectorDimension> d_phi_du[TInputImage::ImageDimension];
461 for (i = 0; i < ImageDimension; ++i)
463 for (j = 0; j < VectorDimension; ++j)
466 m_DerivativeWeights[i] * m_SqrtComponentWeights[j] * 0.5 * (it.GetNext(i)[j] - it.GetPrevious(i)[j]);
471 for (i = 0; i < ImageDimension; ++i)
473 for (j = i; j < ImageDimension; ++j)
475 g[j][i] = g[i][j] = dot_product(d_phi_du[i], d_phi_du[j]);
480 const vnl_symmetric_eigensystem<TRealType> E(g);
484 return (E.get_eigenvalue(ImageDimension - 1) - E.get_eigenvalue(ImageDimension - 2));
488 DerivativeWeightsType m_DerivativeWeights = DerivativeWeightsType::Filled(1);
493 ComponentWeightsType m_ComponentWeights = ComponentWeightsType::Filled(1);
494 ComponentWeightsType m_SqrtComponentWeights = ComponentWeightsType::Filled(1);
498 bool m_UseImageSpacing{
true };
499 bool m_UsePrincipleComponents{};
503 typename RealVectorImageType::ConstPointer m_RealValuedInputImage{};