OTB  9.0.0
Orfeo Toolbox
otbSarDeburstImageFilter.hxx
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2022 Centre National d'Etudes Spatiales (CNES)
3  *
4  * This file is part of Orfeo Toolbox
5  *
6  * https://www.orfeo-toolbox.org/
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 
21 #ifndef otbSarDeburstImageFilter_hxx
22 #define otbSarDeburstImageFilter_hxx
23 
25 
26 #include "otbSarSensorModel.h"
27 #include "itkImageScanlineIterator.h"
28 #include "itkImageScanlineConstIterator.h"
29 #include "itkImageRegionIterator.h"
30 #include "itkImageRegionConstIterator.h"
31 
32 namespace otb
33 {
34 // Constructor
35 template <class TImage>
36 SarDeburstImageFilter<TImage>::SarDeburstImageFilter() : m_LinesRecord(), m_SamplesRecord(), m_OnlyValidSample(false)
37 {
38 }
39 
40 // Needs to be re-implemented since size of output is modified
41 template <class TImage>
43 {
44  // Call superclass implementation
45  Superclass::GenerateOutputInformation();
46 
47  // Retrieve the input image pointer
48  const ImageType* inputPtr = this->GetInput();
49  ImageType* outputPtr = this->GetOutput();
50 
51  // Check that azimuth spacing has not been modified
52  if (std::abs(inputPtr->GetSignedSpacing()[1] - 1.) >= std::numeric_limits<double>::epsilon())
53  itkExceptionMacro("Can not perform deburst if input image azimuth spacing is not 1.");
54 
55  // Check that the azimuth sampling grid has not been modified
56  if (std::abs(inputPtr->GetOrigin()[1] - static_cast<long>(inputPtr->GetOrigin()[1]) - 0.5) >= std::numeric_limits<double>::epsilon())
57  itkExceptionMacro("Can not perform deburst if input image azimuth origin is not N.5");
58 
59  // Retrieve input image metadata
60  auto imd = inputPtr->GetImageMetadata();
61 
62  SarSensorModel sarSensorModel(imd);
63 
64  // Try to call the deburst function
65  bool deburstOk = sarSensorModel.Deburst(m_LinesRecord, m_SamplesRecord, m_OnlyValidSample);
66 
67  if (!deburstOk || m_LinesRecord.empty())
68  itkExceptionMacro(<< "Could not deburst SAR sensor model from input image");
69 
70  // Compute the actual lines to remove
71  typename ImageType::RegionType largestPossibleRegion = this->GetInput()->GetLargestPossibleRegion();
72  typename ImageType::PointType origin = this->GetInput()->GetOrigin();
73 
74  // Now, filter the LinesRecord so as to account for possible
75  // extracts on input image
76  long firstInputLine = static_cast<long>(origin[1] - 0.5);
77 
78  // We know that spacing[1]=1.
79  long lastInputLine = static_cast<long>(origin[1] - 0.5 + largestPossibleRegion.GetSize()[1] - 1);
80 
81  // Move origin
82  unsigned long outputOriginLine = 0;
83  SarSensorModel::ImageLineToDeburstLine(m_LinesRecord, firstInputLine, outputOriginLine);
84 
85  long originOffset_samples = static_cast<long>(this->GetInput()->GetOrigin()[0] - 0.5);
86  unsigned long outputOriginSample = 0;
87  if (m_OnlyValidSample)
88  {
89  if (static_cast<int>(m_SamplesRecord.first) > originOffset_samples)
90  {
91  outputOriginSample = 0;
92  }
93  else
94  {
95  outputOriginSample = originOffset_samples - static_cast<int>(m_SamplesRecord.first);
96  }
97  origin[0] = 0.5 + outputOriginSample;
98  }
99 
100  origin[1] = 0.5 + outputOriginLine;
101  outputPtr->SetOrigin(origin);
102 
103  // Update line records to accommodate actual input image region
104  LinesRecordVectorType filteredRecords;
105 
106  for (LinesRecordVectorType::const_iterator it = m_LinesRecord.begin(); it != m_LinesRecord.end(); ++it)
107  {
108  // If record is inside input image region
109  if ((long)it->first <= lastInputLine && (long)it->second >= firstInputLine)
110  {
111  RecordType filteredRecord = *it;
112  filteredRecord.first = std::max(static_cast<long>(filteredRecord.first), firstInputLine);
113  filteredRecord.second = std::min(static_cast<long>(filteredRecord.second), lastInputLine);
114  filteredRecords.push_back(filteredRecord);
115  }
116  }
117 
118  // Use filtered records
119  // m_LinesRecord.swap(filteredRecords);
120 
121  // TODO: Ensure that records are sorted ?
122 
123 
124  // Compute deburst azimuth size
125  typename ImageType::SizeType deburstSize = largestPossibleRegion.GetSize();
126  deburstSize[1] = 0;
127 
128 
129  for (LinesRecordVectorType::const_iterator it = filteredRecords.begin(); it != filteredRecords.end(); ++it)
130  {
131  deburstSize[1] += it->second - it->first + 1;
132  }
133 
134  if (m_OnlyValidSample)
135  {
136  long minEnd = static_cast<long>(
137  std::min(static_cast<long>(m_SamplesRecord.second), static_cast<long>(largestPossibleRegion.GetSize()[0] + originOffset_samples - 1)));
138  long maxStart = static_cast<long>(std::max(static_cast<long>(m_SamplesRecord.first), originOffset_samples));
139  deburstSize[0] = minEnd - maxStart + 1;
140  }
141 
142  // Set largest possible region
143  typename ImageType::RegionType outputLargestPossibleRegion = largestPossibleRegion;
144  largestPossibleRegion.SetSize(deburstSize);
145  outputPtr->SetLargestPossibleRegion(largestPossibleRegion);
146 
147  imd.Add(MDNum::NumberOfLines, deburstSize[0]);
148  imd.Add(MDNum::NumberOfColumns, deburstSize[1]);
149 
150  // Update and set the output image metadata
151  sarSensorModel.UpdateImageMetadata(imd);
152  outputPtr->SetImageMetadata(imd);
153 }
154 
155 template <class TImage>
157 {
158  PointType outputUperLeft, outputLowerLeft;
159 
160  typename RegionType::IndexType outputUpperLeftIndex = outputRegion.GetIndex();
161  typename RegionType::IndexType outputLowerLeftIndex = outputUpperLeftIndex;
162  outputLowerLeftIndex[1] += outputRegion.GetSize()[1] - 1;
163 
164  this->GetOutput()->TransformIndexToPhysicalPoint(outputUpperLeftIndex, outputUperLeft);
165  this->GetOutput()->TransformIndexToPhysicalPoint(outputLowerLeftIndex, outputLowerLeft);
166 
167  // TODO: Watch for <0
168  unsigned long upperLeftLine = static_cast<unsigned long>(outputUperLeft[1] - 0.5);
169  unsigned long lowerLeftLine = static_cast<unsigned long>(outputLowerLeft[1] - 0.5);
170 
171  unsigned long inputUpperLeftLine, inputLowerLeftLine;
172 
173  SarSensorModel::DeburstLineToImageLine(m_LinesRecord, upperLeftLine, inputUpperLeftLine);
174  SarSensorModel::DeburstLineToImageLine(m_LinesRecord, lowerLeftLine, inputLowerLeftLine);
175 
176  long originOffset = static_cast<long>(this->GetInput()->GetOrigin()[1] - 0.5);
177  long originOffset_samples = static_cast<long>(this->GetInput()->GetOrigin()[0] - 0.5);
178 
179  inputUpperLeftLine -= originOffset;
180  inputLowerLeftLine -= originOffset;
181 
182  RegionType inputRegion = outputRegion;
183 
184  typename RegionType::SizeType size = inputRegion.GetSize();
185  typename RegionType::IndexType index = inputRegion.GetIndex();
186 
187  if (m_OnlyValidSample)
188  {
189  if (static_cast<int>(m_SamplesRecord.first) > originOffset_samples)
190  {
191  index[0] += m_SamplesRecord.first - originOffset_samples;
192  }
193  }
194 
195  index[1] = inputUpperLeftLine;
196  size[1] = inputLowerLeftLine - inputUpperLeftLine + 1;
197 
198  inputRegion.SetIndex(index);
199  inputRegion.SetSize(size);
200 
201  return inputRegion;
202 }
203 
204 
205 // Needs to be re-implemented since size of output is modified
206 template <class TImage>
208 {
209  RegionType outputRequestedRegion = this->GetOutput()->GetRequestedRegion();
210  RegionType inputRequestedRegion = OutputRegionToInputRegion(outputRequestedRegion);
211 
212  ImageType* inputPtr = const_cast<ImageType*>(this->GetInput());
213 
214  inputPtr->SetRequestedRegion(inputRequestedRegion);
215 }
216 
217 // Actual processing
218 template <class TImage>
219 void SarDeburstImageFilter<TImage>::ThreadedGenerateData(const RegionType& outputRegionForThread, itk::ThreadIdType itkNotUsed(threadId))
220 {
221  if (m_OnlyValidSample)
222  {
223  this->ThreadedGenerateDataWithOnlyValidSamples(outputRegionForThread, 0);
224  }
225  else
226  {
227  this->ThreadedGenerateDataWithAllSamples(outputRegionForThread, 0);
228  }
229 }
230 
231 // Actual processing with all samples
232 template <class TImage>
233 void SarDeburstImageFilter<TImage>::ThreadedGenerateDataWithAllSamples(const RegionType& outputRegionForThread, itk::ThreadIdType itkNotUsed(threadId))
234 {
235  // Compute corresponding input region
236  RegionType inputRegionForThread = OutputRegionToInputRegion(outputRegionForThread);
237 
238  itk::ImageScanlineConstIterator<ImageType> inputIt(this->GetInput(), inputRegionForThread);
239  itk::ImageScanlineIterator<ImageType> outputIt(this->GetOutput(), outputRegionForThread);
240 
241  inputIt.GoToBegin();
242  outputIt.GoToBegin();
243 
244  while (!inputIt.IsAtEnd() && !outputIt.IsAtEnd())
245  {
246  typename ImageType::IndexType currentInputIndex = inputIt.GetIndex();
247  PointType currentInputPoint;
248  this->GetInput()->TransformIndexToPhysicalPoint(currentInputIndex, currentInputPoint);
249 
250  bool lineToKeep = false;
251 
252  for (auto const& record : m_LinesRecord)
253  {
254  if (currentInputPoint[1] - 0.5 >= record.first && currentInputPoint[1] - 0.5 <= record.second)
255  {
256  lineToKeep = true;
257  break;
258  }
259  }
260  if (lineToKeep)
261  {
262  for (inputIt.GoToBeginOfLine(), outputIt.GoToBeginOfLine(); !inputIt.IsAtEndOfLine() && !outputIt.IsAtEndOfLine(); ++inputIt, ++outputIt)
263  {
264  outputIt.Set(inputIt.Get());
265  }
266  outputIt.NextLine();
267  }
268 
269 
270  inputIt.NextLine();
271  }
272 }
273 
274 // Actual processing with only valid samples
275 template <class TImage>
276 void SarDeburstImageFilter<TImage>::ThreadedGenerateDataWithOnlyValidSamples(const RegionType& outputRegionForThread, itk::ThreadIdType itkNotUsed(threadId))
277 {
278  // Compute corresponding input region
279  RegionType inputRegionForThread = OutputRegionToInputRegion(outputRegionForThread);
280 
281  itk::ImageRegionConstIterator<ImageType> inputIt(this->GetInput(), inputRegionForThread);
282  itk::ImageRegionIterator<ImageType> outputIt(this->GetOutput(), outputRegionForThread);
283 
284  inputIt.GoToBegin();
285  outputIt.GoToBegin();
286 
287  while (!inputIt.IsAtEnd() && !outputIt.IsAtEnd())
288  {
289  typename ImageType::IndexType currentInputIndex = inputIt.GetIndex();
290  PointType currentInputPoint;
291  this->GetInput()->TransformIndexToPhysicalPoint(currentInputIndex, currentInputPoint);
292 
293  bool lineToKeep = false;
294  bool sampleToKeep = false;
295 
296  for (auto const& record : m_LinesRecord)
297  {
298  if (currentInputPoint[1] - 0.5 >= record.first && currentInputPoint[1] - 0.5 <= record.second)
299  {
300  lineToKeep = true;
301  break;
302  }
303  }
304 
305  if (currentInputPoint[0] - 0.5 >= static_cast<int>(m_SamplesRecord.first) && currentInputPoint[1] - 0.5 <= static_cast<int>(m_SamplesRecord.second))
306  {
307  sampleToKeep = true;
308  }
309 
310  if (lineToKeep && sampleToKeep)
311  {
312  outputIt.Set(inputIt.Get());
313 
314  ++outputIt;
315  }
316 
317 
318  ++inputIt;
319  }
320 }
321 
322 
323 } // End namespace otb
324 
325 #endif
otb::SarSensorModel
Definition: otbSarSensorModel.h:36
otbSarSensorModel.h
otb::SarDeburstImageFilter::ThreadedGenerateData
virtual void ThreadedGenerateData(const RegionType &outputRegionForThread, itk::ThreadIdType threadId) override
Definition: otbSarDeburstImageFilter.hxx:219
otbSarDeburstImageFilter.h
otb
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.
Definition: otbJoinContainer.h:32
otb::SarDeburstImageFilter::ImageType
TImage ImageType
Definition: otbSarDeburstImageFilter.h:59
otb::SarDeburstImageFilter::RecordType
std::pair< unsigned long, unsigned long > RecordType
Definition: otbSarDeburstImageFilter.h:65
otb::SarSensorModel::ImageLineToDeburstLine
static bool ImageLineToDeburstLine(const std::vector< std::pair< unsigned long, unsigned long > > &lines, unsigned long imageLine, unsigned long &deburstLine)
otb::SarDeburstImageFilter::GenerateInputRequestedRegion
virtual void GenerateInputRequestedRegion() override
Definition: otbSarDeburstImageFilter.hxx:207
otb::MDNum::NumberOfColumns
@ NumberOfColumns
otb::SarDeburstImageFilter::LinesRecordVectorType
std::vector< RecordType > LinesRecordVectorType
Definition: otbSarDeburstImageFilter.h:66
otb::SarDeburstImageFilter::ThreadedGenerateDataWithAllSamples
void ThreadedGenerateDataWithAllSamples(const RegionType &outputRegionForThread, itk::ThreadIdType threadId)
Definition: otbSarDeburstImageFilter.hxx:233
otb::SarDeburstImageFilter::ThreadedGenerateDataWithOnlyValidSamples
void ThreadedGenerateDataWithOnlyValidSamples(const RegionType &outputRegionForThread, itk::ThreadIdType threadId)
Definition: otbSarDeburstImageFilter.hxx:276
otb::SarSensorModel::DeburstLineToImageLine
static void DeburstLineToImageLine(const std::vector< std::pair< unsigned long, unsigned long > > &lines, unsigned long deburstLine, unsigned long &imageLine)
otb::SarDeburstImageFilter::RegionType
ImageType::RegionType RegionType
Definition: otbSarDeburstImageFilter.h:62
otb::SarDeburstImageFilter::GenerateOutputInformation
virtual void GenerateOutputInformation() override
Definition: otbSarDeburstImageFilter.hxx:42
otb::SarSensorModel::Deburst
bool Deburst(std::vector< std::pair< unsigned long, unsigned long >> &lines, std::pair< unsigned long, unsigned long > &samples, bool onlyValidSample=false)
otb::SarSensorModel::UpdateImageMetadata
void UpdateImageMetadata(ImageMetadata &imd)
otb::SarDeburstImageFilter::SarDeburstImageFilter
SarDeburstImageFilter()
Definition: otbSarDeburstImageFilter.hxx:36
otb::SarDeburstImageFilter::OutputRegionToInputRegion
RegionType OutputRegionToInputRegion(const RegionType &outputRegion) const
Definition: otbSarDeburstImageFilter.hxx:156
otb::SarDeburstImageFilter::PointType
ImageType::PointType PointType
Definition: otbSarDeburstImageFilter.h:63
otb::MDNum::NumberOfLines
@ NumberOfLines