/*========================================================================= * * Copyright Insight Software Consortium * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef itkJensenHavrdaCharvatTsallisPointSetToPointSetMetricv4_hxx #define itkJensenHavrdaCharvatTsallisPointSetToPointSetMetricv4_hxx #include "itkMath.h" #include "itkJensenHavrdaCharvatTsallisPointSetToPointSetMetricv4.h" namespace itk { /** Constructor */ template JensenHavrdaCharvatTsallisPointSetToPointSetMetricv4 ::JensenHavrdaCharvatTsallisPointSetToPointSetMetricv4() : m_UseAnisotropicCovariances( false ), m_PointSetSigma( static_cast( 1.0 ) ), m_KernelSigma( static_cast( 10.0 ) ), m_CovarianceKNeighborhood( static_cast( 5 ) ), m_EvaluationKNeighborhood( static_cast( 50 ) ), m_Alpha( static_cast( 1.0 ) ), m_TotalNumberOfPoints( 0 ), m_Prefactor0( 0.0 ), m_Prefactor1( 0.0 ) { } /** Destructor */ template JensenHavrdaCharvatTsallisPointSetToPointSetMetricv4 ::~JensenHavrdaCharvatTsallisPointSetToPointSetMetricv4() { } /** Initialize the metric */ template void JensenHavrdaCharvatTsallisPointSetToPointSetMetricv4 ::Initialize( void ) { Superclass::Initialize(); // Initialize the fixed density function this->m_FixedDensityFunction = DensityFunctionType::New(); this->m_FixedDensityFunction->SetKernelSigma( this->m_KernelSigma ); this->m_FixedDensityFunction->SetRegularizationSigma( this->m_PointSetSigma ); this->m_FixedDensityFunction->SetNormalize( true ); this->m_FixedDensityFunction->SetUseAnisotropicCovariances( this->m_UseAnisotropicCovariances ); this->m_FixedDensityFunction->SetCovarianceKNeighborhood( this->m_CovarianceKNeighborhood ); this->m_FixedDensityFunction->SetEvaluationKNeighborhood( this->m_EvaluationKNeighborhood ); this->m_FixedDensityFunction->SetInputPointSet( this->m_FixedTransformedPointSet ); // Initialize the moving density function this->m_MovingDensityFunction = DensityFunctionType::New(); this->m_MovingDensityFunction->SetKernelSigma( this->m_KernelSigma ); this->m_MovingDensityFunction->SetRegularizationSigma( this->m_PointSetSigma ); this->m_MovingDensityFunction->SetNormalize( true ); this->m_MovingDensityFunction->SetUseAnisotropicCovariances( this->m_UseAnisotropicCovariances ); this->m_MovingDensityFunction->SetCovarianceKNeighborhood( this->m_CovarianceKNeighborhood ); this->m_MovingDensityFunction->SetEvaluationKNeighborhood( this->m_EvaluationKNeighborhood ); this->m_MovingDensityFunction->SetInputPointSet( this->m_MovingTransformedPointSet ); // Pre-calc some values for efficiency this->m_TotalNumberOfPoints = static_cast( this->m_NumberOfValidPoints + this->m_MovingDensityFunction->GetInputPointSet()->GetNumberOfPoints() ); this->m_Prefactor0 = -1.0 / static_cast( this->m_TotalNumberOfPoints ); if( this->m_Alpha != 1.0 ) { this->m_Prefactor0 /= ( this->m_Alpha - 1.0 ); } this->m_Prefactor1 = 1.0 / ( this->m_TotalNumberOfPoints * this->m_TotalNumberOfPoints ); } template typename JensenHavrdaCharvatTsallisPointSetToPointSetMetricv4 ::MeasureType JensenHavrdaCharvatTsallisPointSetToPointSetMetricv4 ::GetLocalNeighborhoodValue( const PointType & point, const PixelType & itkNotUsed( pixel ) ) const { MeasureType value; LocalDerivativeType derivative; this->ComputeValueAndDerivative( point, value, derivative, true, false ); return value; } /** Get both the match Measure and the Derivative Measure */ template void JensenHavrdaCharvatTsallisPointSetToPointSetMetricv4 ::GetLocalNeighborhoodValueAndDerivative( const PointType & point, MeasureType & value, LocalDerivativeType & derivative, const PixelType & itkNotUsed( pixel ) ) const { this->ComputeValueAndDerivative( point, value, derivative, true, true ); } template void JensenHavrdaCharvatTsallisPointSetToPointSetMetricv4 ::ComputeValueAndDerivative( const PointType & samplePoint, MeasureType & value, LocalDerivativeType & derivativeReturn, bool calcValue, bool calcDerivative ) const { if( calcDerivative ) { derivativeReturn.Fill( NumericTraits::ZeroValue() ); } value = NumericTraits::ZeroValue(); /** * first term only */ typename PointSetType::PointIdentifier numberOfMovingPoints = this->m_MovingDensityFunction->GetInputPointSet()->GetNumberOfPoints(); RealType probabilityStar = this->m_MovingDensityFunction->Evaluate( samplePoint ) * static_cast( numberOfMovingPoints ); probabilityStar /= this->m_TotalNumberOfPoints; if( Math::AlmostEquals( probabilityStar, NumericTraits::ZeroValue() ) ) { return; } if( calcValue ) { RealType realOne = NumericTraits::OneValue(); if( Math::AlmostEquals( this->m_Alpha, realOne ) ) { value = ( std::log( probabilityStar ) ); } else { value = realOne * ( std::pow( probabilityStar, static_cast( this->m_Alpha - realOne ) ) ); } value *= this->m_Prefactor0; } if( calcDerivative ) { RealType probabilityStarFactor = std::pow( probabilityStar, static_cast( 2.0 - this->m_Alpha ) ); typename DensityFunctionType::NeighborsIdentifierType neighbors; this->m_MovingDensityFunction->GetPointsLocator()->FindClosestNPoints( samplePoint, this->m_EvaluationKNeighborhood, neighbors ); for( SizeValueType n = 0; n < neighbors.size(); n++ ) { RealType gaussian = this->m_MovingDensityFunction->GetGaussian( neighbors[n] )->Evaluate( samplePoint ); if( Math::AlmostEquals( gaussian, NumericTraits::ZeroValue() ) ) { continue; } typename GaussianType::MeanVectorType mean = this->m_MovingDensityFunction->GetGaussian( neighbors[n] )->GetMean(); Array diffMean( PointDimension ); for( unsigned int i = 0; i < PointDimension; i++ ) { diffMean[i] = mean[i] - samplePoint[i]; } if( this->m_UseAnisotropicCovariances ) { typename GaussianType::CovarianceMatrixType Ci = this->m_MovingDensityFunction->GetGaussian( neighbors[n] )->GetInverseCovariance(); diffMean = Ci * diffMean; } else { diffMean /= this->m_MovingDensityFunction->GetGaussian( neighbors[n] )->GetCovariance()( 0, 0 ); } DerivativeValueType factor = this->m_Prefactor1 * gaussian / probabilityStarFactor; for( unsigned int i = 0; i < PointDimension; i++ ) { derivativeReturn[i] += diffMean[i] * factor; } } } } template typename LightObject::Pointer JensenHavrdaCharvatTsallisPointSetToPointSetMetricv4 ::InternalClone( void ) const { typename Self::Pointer rval = Self::New(); rval->SetMovingPointSet( this->m_MovingPointSet ); rval->SetFixedPointSet( this->m_FixedPointSet ); rval->SetPointSetSigma( this->m_PointSetSigma ); rval->SetEvaluationKNeighborhood( this->m_EvaluationKNeighborhood ); rval->SetAlpha( this->m_Alpha ); rval->SetKernelSigma( this->m_KernelSigma ); rval->SetCovarianceKNeighborhood( this->m_CovarianceKNeighborhood ); rval->SetUseAnisotropicCovariances( this->m_UseAnisotropicCovariances ); return rval.GetPointer(); } template void JensenHavrdaCharvatTsallisPointSetToPointSetMetricv4 ::PrintSelf( std::ostream& os, Indent indent ) const { Superclass::PrintSelf( os, indent ); os << indent << "Alpha: " << this->m_Alpha << std::endl; os << indent << "Point set sigma: " << this->m_PointSetSigma << std::endl; os << indent << "Evaluation k-neighborhood: " << this->m_EvaluationKNeighborhood << std::endl; if( this->m_UseAnisotropicCovariances ) { os << indent << "Kernel sigma: " << this->m_KernelSigma << std::endl; os << indent << "Covariance k-neighborhood: " << this->m_CovarianceKNeighborhood << std::endl; } else { os << indent << "Isotropic covariances are used." << std::endl; } } } // end namespace itk #endif