OTB  10.0.0
Orfeo Toolbox
otbNCCRegistrationFunction.hxx
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1999-2011 Insight Software Consortium
3  * Copyright (C) 2005-2024 Centre National d'Etudes Spatiales (CNES)
4  *
5  * This file is part of Orfeo Toolbox
6  *
7  * https://www.orfeo-toolbox.org/
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */
21 
22 #ifndef otbNCCRegistrationFunction_hxx
23 #define otbNCCRegistrationFunction_hxx
24 
25 #include "vnl/vnl_math.h"
26 #include "itkNeighborhoodIterator.h"
27 
28 #include "otbMacro.h"
30 #include "vcl_legacy_aliases.h"
31 
32 namespace otb
33 {
34 
35 /*
36  * Default constructor
37  */
38 template <class TFixedImage, class TMovingImage, class TDisplacementField>
40 {
41 
42  RadiusType r;
43  unsigned int j;
44  for (j = 0; j < ImageDimension; ++j)
45  {
46  r[j] = 1;
47  }
48  this->SetRadius(r);
49  m_MetricTotal = 0.0;
50 
51  m_TimeStep = 1.0;
52  m_DenominatorThreshold = 1e-9;
53  m_IntensityDifferenceThreshold = 0.001;
54  this->SetMovingImage(nullptr);
55  this->SetFixedImage(nullptr);
56  m_FixedImageSpacing.Fill(1.0);
57  m_FixedImageOrigin.Fill(0.0);
58  m_FixedImageGradientCalculator = GradientCalculatorType::New();
59 
60  typename DefaultInterpolatorType::Pointer interp = DefaultInterpolatorType::New();
61 
62  m_MovingImageInterpolator = static_cast<InterpolatorType*>(interp.GetPointer());
63 }
64 
65 /*
66  * Standard "PrintSelf" method.
67  */
68 template <class TFixedImage, class TMovingImage, class TDisplacementField>
70 {
71 
72  Superclass::PrintSelf(os, indent);
73  /*
74  os << indent << "MovingImageIterpolator: ";
75  os << m_MovingImageInterpolator.GetPointer() << std::endl;
76  os << indent << "FixedImageGradientCalculator: ";
77  os << m_FixedImageGradientCalculator.GetPointer() << std::endl;
78  os << indent << "DenominatorThreshold: ";
79  os << m_DenominatorThreshold << std::endl;
80  os << indent << "IntensityDifferenceThreshold: ";
81  os << m_IntensityDifferenceThreshold << std::endl;
82  */
83 }
84 
85 /*
86  * Set the function state values before each iteration
87  */
88 template <class TFixedImage, class TMovingImage, class TDisplacementField>
90 {
91  if (!this->m_MovingImage || !this->m_FixedImage || !m_MovingImageInterpolator)
92  {
93  itkExceptionMacro(<< "MovingImage, FixedImage and/or Interpolator not set");
94  }
95 
96  // cache fixed image information
97  m_FixedImageSpacing = this->m_FixedImage->GetSignedSpacing();
98  m_FixedImageOrigin = this->m_FixedImage->GetOrigin();
99 
100  // setup gradient calculator
101  m_FixedImageGradientCalculator->SetInputImage(this->m_FixedImage);
102 
103  // setup moving image interpolator
104  m_MovingImageInterpolator->SetInputImage(this->m_MovingImage);
105 
106  otbMsgDevMacro(" total metric " << m_MetricTotal << " field size " << this->GetDisplacementField()->GetLargestPossibleRegion().GetSize() << " image size "
107  << this->m_FixedImage->GetLargestPossibleRegion().GetSize());
108  m_MetricTotal = 0.0;
109 }
110 
111 /*
112  * Compute update at a non boundary neighbourhood
113  */
114 template <class TFixedImage, class TMovingImage, class TDisplacementField>
117  const FloatOffsetType& itkNotUsed(offset))
118 {
119 
120  PixelType update;
121  update.Fill(0.0);
122  unsigned int j;
123 
124  IndexType oindex = it.GetIndex();
125 
126  typename FixedImageType::SizeType hradius = it.GetRadius();
127 
128  FixedImageType* img = const_cast<FixedImageType*>(this->m_FixedImage.GetPointer());
129 
130  typename FixedImageType::SizeType imagesize = img->GetLargestPossibleRegion().GetSize();
131 
132  itk::NeighborhoodIterator<FixedImageType> hoodIt(hradius, img, img->GetRequestedRegion());
133  hoodIt.SetLocation(oindex);
134 
135  double sff = 0.0;
136  double smm = 0.0;
137  double sfm = 0.0;
138  double fixedValue;
139  double movingValue;
140 
141  double derivativeF[ImageDimension];
142  double derivativeM[ImageDimension];
143  for (j = 0; j < ImageDimension; ++j)
144  {
145  derivativeF[j] = 0;
146  derivativeM[j] = 0;
147  }
148 
149  unsigned int indct;
150  unsigned int hoodlen = hoodIt.Size();
151 
152  for (indct = 0; indct < hoodlen - 1; indct++)
153  {
154 
155  IndexType index = hoodIt.GetIndex(indct);
156 
157  bool inimage = true;
158  for (unsigned int dd = 0; dd < ImageDimension; dd++)
159  {
160  if (index[dd] < 0 || index[dd] > static_cast<typename IndexType::IndexValueType>(imagesize[dd] - 1))
161  inimage = false;
162  }
163 
164  if (inimage)
165  {
166 
167  // Get fixed image related information
168 
169  CovariantVectorType fixedGradient;
170  double fixedGradientSquaredMagnitude = 0;
171 
172  // Note: no need to check the index is within
173  // fixed image buffer. This is done by the external filter.
174  fixedValue = (double)this->m_FixedImage->GetPixel(index);
175 
176  fixedGradient = m_FixedImageGradientCalculator->EvaluateAtIndex(index);
177  for (j = 0; j < ImageDimension; ++j)
178  {
179  fixedGradientSquaredMagnitude += vnl_math_sqr(fixedGradient[j]) * m_FixedImageSpacing[j];
180  }
181 
182  // Get moving image related information
183 
184  PointType mappedPoint;
185 
186  typedef typename TDisplacementField::PixelType DisplacementPixelType;
187 
188  // Edited by OTB developers
189  DisplacementPixelType vec;
190  vec.Fill(0);
191  if (this->GetDisplacementField()->GetBufferedRegion().IsInside(index))
192  {
193  vec = this->GetDisplacementField()->GetPixel(index);
194  }
195  // End Edited by OTB developers
196 
197  for (j = 0; j < ImageDimension; ++j)
198  {
199  mappedPoint[j] = double(index[j]) * m_FixedImageSpacing[j] + m_FixedImageOrigin[j];
200  mappedPoint[j] += vec[j];
201  }
202  if (m_MovingImageInterpolator->IsInsideBuffer(mappedPoint))
203  {
204  movingValue = m_MovingImageInterpolator->Evaluate(mappedPoint);
205  }
206  else
207  {
208  movingValue = 0.0;
209  }
210 
211  sff += fixedValue * fixedValue;
212  smm += movingValue * movingValue;
213  sfm += fixedValue * movingValue;
214 
215  for (unsigned int dim = 0; dim < ImageDimension; ++dim)
216  {
217  double differential = fixedGradient[dim];
218  derivativeF[dim] += fixedValue * differential;
219  derivativeM[dim] += movingValue * differential;
220  }
221  }
222  }
223 
224  double updatenorm = 0.0;
225  if ((sff * smm) != 0.0)
226  {
227  double factor = 1.0 / std::sqrt(sff * smm);
228  for (unsigned int i = 0; i < ImageDimension; ++i)
229  {
230  update[i] = factor * (derivativeF[i] - (sfm / smm) * derivativeM[i]);
231  updatenorm += (update[i] * update[i]);
232  }
233  updatenorm = std::sqrt(updatenorm);
234  m_MetricTotal += sfm * factor;
235  this->m_Energy += sfm * factor;
236  }
237  else
238  {
239  for (unsigned int i = 0; i < ImageDimension; ++i)
240  {
241  update[i] = 0.0;
242  }
243  updatenorm = 1.0;
244  }
245 
246  // if ( fixedValue > 0.40 && movingValue > 0.40) std::cout << " update norm " << updatenorm;
247 
248  if (this->GetNormalizeGradient() && updatenorm != 0.0)
249  {
250  update /= (updatenorm);
251  }
252 
253  return update * this->m_GradientStep;
254 }
255 
256 } // end namespace otbs
257 
258 #endif
Superclass::FloatOffsetType FloatOffsetType
Superclass::NeighborhoodType NeighborhoodType
itk::CovariantVector< double, itkGetStaticConstMacro(ImageDimension)> CovariantVectorType
void PrintSelf(std::ostream &os, itk::Indent indent) const override
FixedImageType::IndexType IndexType
InterpolatorType::PointType PointType
itk::InterpolateImageFunction< MovingImageType, CoordRepType > InterpolatorType
Superclass::FixedImageType FixedImageType
PixelType ComputeUpdate(const NeighborhoodType &neighborhood, void *globalData, const FloatOffsetType &offset=FloatOffsetType(0.0)) override
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.
#define otbMsgDevMacro(x)
Definition: otbMacro.h:116