/*========================================================================= * * 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 itkRegistrationParameterScalesFromShiftBase_hxx #define itkRegistrationParameterScalesFromShiftBase_hxx #include "itkRegistrationParameterScalesFromShiftBase.h" namespace itk { template< typename TMetric > RegistrationParameterScalesFromShiftBase< TMetric > ::RegistrationParameterScalesFromShiftBase() { this->m_SmallParameterVariation = 0.01; } /** Compute parameter scales */ template< typename TMetric > void RegistrationParameterScalesFromShiftBase< TMetric > ::EstimateScales(ScalesType ¶meterScales) { this->CheckAndSetInputs(); this->SetScalesSamplingStrategy(); this->SampleVirtualDomain(); const SizeValueType numAllPara = this->GetTransform()->GetNumberOfParameters(); const SizeValueType numLocalPara = this->GetNumberOfLocalParameters(); parameterScales.SetSize(numLocalPara); FloatType maxShift; ParametersType deltaParameters(numAllPara); // minNonZeroShift: the minimum non-zero shift. FloatType minNonZeroShift = NumericTraits::max(); OffsetValueType offset = 0; if( this->IsDisplacementFieldTransform() ) { //FIXME: remove if we end up not using this //if( this->MetricIsPointSetToPointSetType() ) if (this->GetSamplingStrategy() == Superclass::VirtualDomainPointSetSampling) { // Use the first virtual point since the center of the virtual domain // may not line up with a sample point. offset = this->m_Metric->ComputeParameterOffsetFromVirtualPoint( this->m_SamplePoints[0], numLocalPara ); } else { VirtualIndexType centralIndex = this->GetVirtualDomainCentralIndex(); offset = this->m_Metric->ComputeParameterOffsetFromVirtualIndex( centralIndex, numLocalPara ); } } // compute voxel shift generated from each transform parameter for (SizeValueType i=0; i::ZeroValue()); deltaParameters[offset + i] = this->m_SmallParameterVariation; maxShift = this->ComputeMaximumVoxelShift(deltaParameters); parameterScales[i] = maxShift; if ( maxShift > NumericTraits::epsilon() && maxShift < minNonZeroShift ) { minNonZeroShift = maxShift; } } if (Math::ExactlyEquals(minNonZeroShift, NumericTraits::max())) { itkWarningMacro( << "Variation in any parameter won't change a voxel position. The default scales (1.0) are used to avoid division-by-zero." ); parameterScales.Fill(NumericTraits< typename ScalesType::ValueType >::OneValue()); } else { if( this->IsBSplineTransform() ) { parameterScales.Fill( minNonZeroShift ); } else { for (SizeValueType i=0; i::epsilon()) { // To avoid division-by-zero in optimizers, assign a small value for a zero scale. parameterScales[i] = minNonZeroShift * minNonZeroShift; } else { parameterScales[i] *= parameterScales[i]; } //normalize to unit variation parameterScales[i] *= NumericTraits< typename ScalesType::ValueType >::OneValue() / itk::Math::sqr( this->m_SmallParameterVariation ); } } } } /** Compute the scale for a step. For transform T(x + t * step), the scale * w.r.t. the step is the shift produced by step. */ template< typename TMetric > typename RegistrationParameterScalesFromShiftBase< TMetric >::FloatType RegistrationParameterScalesFromShiftBase< TMetric > ::EstimateStepScale(const ParametersType &step) { this->CheckAndSetInputs(); this->SetStepScaleSamplingStrategy(); this->SampleVirtualDomain(); if( this->TransformHasLocalSupportForScalesEstimation() ) { return this->ComputeMaximumVoxelShift(step); } // For global transforms, we want a linear approximation of the function // of step scale w.r.t "step". This is true only when "step" is close to // zero. Therefore, we need to scale "step" down. FloatType maxStep = NumericTraits::ZeroValue(); for (typename ParametersType::SizeValueType p = 0; p < step.GetSize(); p++) { if (maxStep < std::abs(step[p])) { maxStep = std::abs(step[p]); } } if (maxStep <= NumericTraits::epsilon()) { return NumericTraits::ZeroValue(); } else { FloatType factor = this->m_SmallParameterVariation / maxStep; ParametersType smallStep(step.size()); //Use a small step to have a linear approximation. smallStep = step * factor; return this->ComputeMaximumVoxelShift(smallStep) / factor; } } /** * Estimate the scales of local steps. */ template< typename TMetric > void RegistrationParameterScalesFromShiftBase< TMetric > ::EstimateLocalStepScales(const ParametersType &step, ScalesType &localStepScales) { if( !this->TransformHasLocalSupportForScalesEstimation() ) { itkExceptionMacro( "EstimateLocalStepScales: the transform doesn't have local support (displacement field or b-spline)." ); } this->CheckAndSetInputs(); this->SetStepScaleSamplingStrategy(); this->SampleVirtualDomain(); ScalesType sampleShifts; this->ComputeSampleShifts(step, sampleShifts); const SizeValueType numAllPara = this->GetTransform()->GetNumberOfParameters(); const SizeValueType numPara = this->GetNumberOfLocalParameters(); const SizeValueType numLocals = numAllPara / numPara; localStepScales.SetSize(numLocals); localStepScales.Fill(NumericTraits::ZeroValue()); const SizeValueType numSamples = static_cast< const SizeValueType >( this->m_SamplePoints.size() ); for (SizeValueType c=0; cm_SamplePoints[c]; IndexValueType localId = this->m_Metric->ComputeParameterOffsetFromVirtualPoint( point, numPara) / numPara; localStepScales[localId] = sampleShifts[c]; } } /** * Compute the maximum shift when a transform is changed with deltaParameters */ template< typename TMetric > typename RegistrationParameterScalesFromShiftBase< TMetric >::FloatType RegistrationParameterScalesFromShiftBase< TMetric > ::ComputeMaximumVoxelShift(const ParametersType &deltaParameters) { ScalesType sampleShifts; this->ComputeSampleShifts(deltaParameters, sampleShifts); FloatType maxShift = NumericTraits< FloatType >::ZeroValue(); for (SizeValueType s=0; s void RegistrationParameterScalesFromShiftBase< TMetric > ::PrintSelf(std::ostream& os, Indent indent) const { Superclass::PrintSelf(os,indent); } } // namespace itk #endif /* itkRegistrationParameterScalesFromShiftBase_hxx */