OTB  9.0.0
Orfeo Toolbox
otbStreamingMultibandFeatherMosaicFilter.hxx
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1999-2011 Insight Software Consortium
3  * Copyright (C) 2005-2022 Centre National d'Etudes Spatiales (CNES)
4  * Copyright (C) 2016-2019 IRSTEA
5  *
6  * This file is part of Orfeo Toolbox
7  *
8  * https://www.orfeo-toolbox.org/
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  * http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  */
22 #ifndef __StreamingMultibandFeatherMosaicFilter_hxx
23 #define __StreamingMultibandFeatherMosaicFilter_hxx
24 
26 #include "itkProgressReporter.h"
27 
28 namespace otb
29 {
30 
34 template <class TInputImage, class TOutputImage, class TDistanceImage>
36 {
37  m_NumberOfLevels = 2;
38  m_FirstLevelTransitionDistance = 3;
39  m_FirstLevelVariance = 1;
40 }
41 
42 template <class TInputImage, class TOutputImage, class TDistanceImage>
44 {
45 
46  // Clear scales parameters
47  m_TransitionDistances.clear();
48  m_TransitionOffsets.clear();
49  m_Variances.clear();
50 
51  // Clear internal filters
52  m_SubImageFilter.clear();
53  m_Filter.clear();
54  m_SingleFilter.clear();
55  m_MosaicFilter.clear();
56 
57  // Compute transition distances
58  for (unsigned int level = 0; level <= m_NumberOfLevels; level++)
59  {
60  DistanceImageValueType distance = std::pow((DistanceImageValueType)level + 1, 2.0) * m_FirstLevelTransitionDistance;
61  m_TransitionDistances.push_back(distance);
62  }
63 
64  // Transition offsets are here to center the blending effect
65  for (unsigned int level = 0; level <= m_NumberOfLevels; level++)
66  {
67  DistanceImageValueType offset = 0.5 * (m_TransitionDistances.at(m_NumberOfLevels) - m_TransitionDistances.at(level));
68  m_TransitionOffsets.push_back(offset);
69  }
70 
71  // // When LF transition distance is manually set, change corresponding
72  // offset
73  // if (transitionDistanceLF>transitionsDistances[numberOfLevels])
74  // {
75  // // Set new LF transition distance
76  // transitionsDistances[numberOfLevels] = transitionDistanceLF;
77  // // Reset offset value same as level before
78  // transitionOffset[numberOfLevels] = transitionOffset[numberOfLevels-1];
79  // }
80 
81  // Prepare mosaic filters
82  for (unsigned int level = 0; level <= m_NumberOfLevels; level++)
83  {
84  itkDebugMacro("Create mosaic filter for level " << level);
85  MosaicFilterPointer mosaicFilter = MosaicFilterType::New();
86 
87  // Set output origin, size, spacing, AutomaticOutputParametersComputation,
88  // scale matrix, shift-scale mode
89  mosaicFilter->SetOutputOrigin(this->GetOutputOrigin());
90  mosaicFilter->SetOutputSize(this->GetOutputSize());
91  mosaicFilter->SetOutputSpacing(this->GetOutputSpacing());
92  mosaicFilter->SetAutomaticOutputParametersComputation(this->GetAutomaticOutputParametersComputation());
93  mosaicFilter->SetScaleMatrix(this->GetScaleMatrix()); // Set scales (HF
94  // and LF)
95  mosaicFilter->SetShiftScaleInputImages(this->GetShiftScaleInputImages());
96  mosaicFilter->SetInterpolator(this->GetInterpolator()); // Interpolator
97  mosaicFilter->SetNoDataOutputPixel(this->GetNoDataOutputPixel()); // No
98  // data
99  // (output)
100  mosaicFilter->SetNoDataInputPixel(this->GetNoDataInputPixel()); // No
101  // data
102  // (input)
103  mosaicFilter->SetFeatheringSmoothness(this->GetFeatheringSmoothness()); // feathering
104  // exponent
105  mosaicFilter->SetDistanceInterpolator(this->GetDistanceInterpolator()); // distance
106  // image
107  // interpolator
108 
109  // Set shifts
110  if (level == m_NumberOfLevels)
111  {
112  // ...for LF
113  mosaicFilter->SetShiftMatrix(this->GetShiftMatrix());
114  }
115  else
116  {
117  // ... but not for HF
118  typename MosaicFilterType::MatrixType nullshifts(this->GetShiftMatrix());
119  nullshifts.fill(0);
120  mosaicFilter->SetShiftMatrix(nullshifts);
121  }
122  m_MosaicFilter.push_back(mosaicFilter);
123  }
124 
125  // Now prepare all filters
126  const unsigned int numberOfImages = 0.5 * (this->GetNumberOfInputs());
127  for (unsigned int i = 0; i < numberOfImages; i++)
128  {
129 
130  const unsigned int inputImageIndex = 2 * i;
131  const unsigned int inputDistanceImageIndex = 2 * i + 1;
132 
133  itkDebugMacro("Create filters for image " << i);
134 
135  std::vector<DiscreteGaussianFilterPointer> gaussianFilters;
136  std::vector<PerBandFilterPointer> gaussianFilterAdapters;
137  std::vector<SubImageFilterPointer> subImageFilters;
138 
139  // Create N filters
140  for (unsigned int level = 0; level < m_NumberOfLevels; level++)
141  {
142 
143  itkDebugMacro("\tLevel " << level);
144 
145  // compute variance of the level
146  const double shrinkFactor = std::pow(2.0, (double)level); // 1 2 4 8 16
147  // ...
148  const double variance = std::pow(0.5 * shrinkFactor, 2.0); //
149 
150  // discrete gaussian filter
151  DiscreteGaussianFilterPointer discreteGaussianFilter = DiscreteGaussianFilterType::New();
152  discreteGaussianFilter->SetVariance(variance);
153  discreteGaussianFilter->SetUseImageSpacingOff();
154  discreteGaussianFilter->SetReleaseDataFlag(true);
155  gaussianFilters.push_back(discreteGaussianFilter);
156 
157  // filter adapter
158  PerBandFilterPointer gaussianFilterAdapter = PerBandFilterType::New();
159  gaussianFilterAdapter->SetFilter(discreteGaussianFilter);
160  gaussianFilterAdapter->SetInput(this->GetInput(inputImageIndex));
161  gaussianFilterAdapter->SetReleaseDataFlag(true);
162  gaussianFilterAdapters.push_back(gaussianFilterAdapter);
163 
164  // subtract filter
165  SubImageFilterPointer subtractFilter = SubImageFilterType::New();
166  if (level == 0)
167  {
168  // HF band is I* - b0
169  subtractFilter->SetInput1(this->GetInput(inputImageIndex));
170  subtractFilter->SetInput2(gaussianFilterAdapters.at(level)->GetOutput());
171  }
172  else
173  {
174  // band is bn-1 - bn
175  subtractFilter->SetInput1(gaussianFilterAdapters.at(level - 1)->GetOutput());
176  subtractFilter->SetInput2(gaussianFilterAdapters.at(level)->GetOutput());
177  }
178  subImageFilters.push_back(subtractFilter);
179 
180  // mosaic filter
181  m_MosaicFilter[level]->PushBackInputs(subtractFilter->GetOutput(),
182  static_cast<const DistanceImageType*>(Superclass::ProcessObject::GetInput(inputDistanceImageIndex)));
183  }
184  m_SingleFilter.push_back(gaussianFilters);
185  m_Filter.push_back(gaussianFilterAdapters);
186  m_SubImageFilter.push_back(subImageFilters);
187 
188  // Last band is lowest low pass filter
189  itkDebugMacro("m_Filter size = " << m_Filter.size() << " / i = " << i);
190  m_MosaicFilter[m_NumberOfLevels]->PushBackInputs(m_Filter.at(i).at(m_NumberOfLevels - 1)->GetOutput(),
191  static_cast<const DistanceImageType*>(Superclass::ProcessObject::GetInput(inputDistanceImageIndex)));
192  }
193 
194  // Compute extrapolation offset:
195  // Avoid extrapolation near borders (gaussian filters blurs "no data" values
196  // too...)
197  // Because LF gaussian filters have the biggest kernel, one must
198  // set an offset equal to this kernel size, in geographic unit. This will
199  // avoid the use of blurred "no data" values
200  const double maximumSpacingInXY = std::max(std::abs(this->GetOutputSpacing()[0]), std::abs(this->GetOutputSpacing()[1]));
201  const double extrapolationOffset = ((double)m_SingleFilter.at(0).at(m_NumberOfLevels - 1)->GetMaximumKernelWidth()) * maximumSpacingInXY;
202  itkDebugMacro(<< "Extrapolation offset: " << extrapolationOffset);
203 
204  // Set up mosaic filters offsets and transition distances
205  itkDebugMacro("Level\tDist\tOffset");
206  for (unsigned int level = 0; level <= m_NumberOfLevels; level++)
207  {
208  const double offset = extrapolationOffset + m_TransitionOffsets.at(level);
209  m_MosaicFilter.at(level)->SetDistanceOffset(offset);
210  m_MosaicFilter.at(level)->SetFeatheringTransitionDistance(m_TransitionDistances.at(level));
211  itkDebugMacro(<< level << "\t" << m_TransitionDistances.at(level) << "\t" << offset);
212  }
213 
214  // Recompose mosaic
215  m_SummingFilter = SummingFilterType::New();
216  for (unsigned int level = 0; level <= m_NumberOfLevels; level++)
217  {
218  // Sum LF and HF
219  m_SummingFilter->PushBackInput(m_MosaicFilter.at(level)->GetOutput());
220  }
221  m_SummingFilter->SetReleaseDataFlag(true);
222 }
223 
224 /*
225  * GenerateData
226  */
227 template <class TInputImage, class TOutputImage, class TDistanceImage>
229 {
230  itkDebugMacro("Generate data on region " << this->GetOutput()->GetRequestedRegion());
231 
232  m_SummingFilter->GraftOutput(this->GetOutput());
233  m_SummingFilter->Update();
234  this->GraftOutput(m_SummingFilter->GetOutput());
235 
236  itkDebugMacro("Generate data OK");
237 }
238 }
239 #endif
otb::StreamingMultibandFeatherMosaicFilter::StreamingMultibandFeatherMosaicFilter
StreamingMultibandFeatherMosaicFilter()
Definition: otbStreamingMultibandFeatherMosaicFilter.hxx:35
otb::StreamingMosaicFilterBase< TInputImage, TOutputImage, double >::MatrixType
vnl_matrix< InternalValueType > MatrixType
Definition: otbStreamingMosaicFilterBase.h:105
otbStreamingMultibandFeatherMosaicFilter.h
otb
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.
Definition: otbJoinContainer.h:32
otb::StreamingMultibandFeatherMosaicFilter::MosaicFilterPointer
MosaicFilterType::Pointer MosaicFilterPointer
Definition: otbStreamingMultibandFeatherMosaicFilter.h:92
otb::StreamingMultibandFeatherMosaicFilter::DistanceImageType
TDistanceImage DistanceImageType
Definition: otbStreamingMultibandFeatherMosaicFilter.h:74
otb::StreamingMultibandFeatherMosaicFilter::SubImageFilterPointer
SubImageFilterType::Pointer SubImageFilterPointer
Definition: otbStreamingMultibandFeatherMosaicFilter.h:90
otb::StreamingMultibandFeatherMosaicFilter::DiscreteGaussianFilterPointer
DiscreteGaussianFilterType::Pointer DiscreteGaussianFilterPointer
Definition: otbStreamingMultibandFeatherMosaicFilter.h:84
otb::StreamingMultibandFeatherMosaicFilter::GenerateData
virtual void GenerateData()
Definition: otbStreamingMultibandFeatherMosaicFilter.hxx:228
otb::StreamingMultibandFeatherMosaicFilter::Modified
virtual void Modified()
Definition: otbStreamingMultibandFeatherMosaicFilter.hxx:43
otb::StreamingMultibandFeatherMosaicFilter::PerBandFilterPointer
PerBandFilterType::Pointer PerBandFilterPointer
Definition: otbStreamingMultibandFeatherMosaicFilter.h:86
otb::StreamingMultibandFeatherMosaicFilter::DistanceImageValueType
DistanceImageType::PixelType DistanceImageValueType
Definition: otbStreamingMultibandFeatherMosaicFilter.h:76