OTB  10.0.0
Orfeo Toolbox
otbMultiChannelExtractROI.hxx
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2024 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 otbMultiChannelExtractROI_hxx
22 #define otbMultiChannelExtractROI_hxx
23 
25 
26 #include "itkImageRegionIterator.h"
27 #include "itkObjectFactory.h"
28 #include "itkExtractImageFilterRegionCopier.h"
29 
30 namespace otb
31 {
32 
36 template <class TInputPixelType, class TOutputPixelType>
38  : ExtractROIBase<VectorImage<TInputPixelType, 2>, VectorImage<TOutputPixelType, 2>>(), m_FirstChannel(0), m_LastChannel(0), m_ChannelsKind(0)
39 {
40  ClearChannels();
41  this->DynamicMultiThreadingOn();
42 }
44 
48 template <class TInputPixelType, class TOutputPixelType>
50 {
51  if (m_ChannelsKind == 1)
52  {
53  itkExceptionMacro(<< "m_Channels already set using channels interval.");
54  }
55  m_Channels.push_back(channel);
56  if (m_ChannelsKind == 0)
57  {
58  m_ChannelsKind = 2;
59  }
60  this->Modified();
61 }
63 
64 template <class TInputPixelType, class TOutputPixelType>
66 {
67  if (m_ChannelsKind == 2)
68  {
69  itkExceptionMacro(<< "m_Channels already set using SetChannels method.");
70  }
71  m_FirstChannel = id;
72  if (m_ChannelsKind == 0)
73  {
74  m_ChannelsKind = 1;
75  }
76  this->Modified();
77 }
78 
79 template <class TInputPixelType, class TOutputPixelType>
81 {
82  if (m_ChannelsKind == 2)
83  {
84  itkExceptionMacro(<< "m_Channels already set using SetChannels method.");
85  }
86  m_LastChannel = id;
87  if (m_ChannelsKind == 0)
88  {
89  m_ChannelsKind = 1;
90  }
91  this->Modified();
92 }
93 
97 template <class TInputPixelType, class TOutputPixelType>
99 {
100  m_FirstChannel = 0;
101  m_LastChannel = 0;
102  m_Channels.clear();
103  m_ChannelsKind = 0;
104  m_ChannelsWorks.clear();
105 }
107 
111 template <class TInputPixelType, class TOutputPixelType>
112 void MultiChannelExtractROI<TInputPixelType, TOutputPixelType>::PrintSelf(std::ostream& os, itk::Indent indent) const
113 {
114  Superclass::PrintSelf(os, indent);
115 }
116 
117 template <class TInputPixelType, class TOutputPixelType>
119 {
120  // The following conditions can be gathered but we'd loose in comprehension
121  m_ChannelsWorks.clear();
122  // First passage in the method:
123  if (m_Channels.empty() == true)
124  {
125  // - User SetFirst/LastChannel()
126  if (m_ChannelsKind == 1)
127  {
128  this->SetChannelsWorkWithLimits();
129  }
130  else
131  {
132  // - User called SetChannels()
133  if (m_Channels.empty() == true && m_ChannelsKind == 2)
134  {
135  m_ChannelsWorks = m_Channels;
136  }
137  }
138  }
139  // Second passage in the method: Update already donne
140  else
141  {
142  // - User SetFirst/LastChannel()
143  if (m_ChannelsKind == 1)
144  {
145  m_Channels.clear();
146  this->SetChannelsWorkWithLimits();
147  }
148  else
149  {
150  // - User called SetChannels()
151  if (m_ChannelsKind == 2)
152  {
153  m_ChannelsWorks = m_Channels;
154  }
155  }
156  }
157 }
158 
159 template <class TInputPixelType, class TOutputPixelType>
161 {
162  if ((m_FirstChannel == 0) || (m_LastChannel == 0))
163  {
164  itkExceptionMacro(<< "otb::ExtractImageFilter::GenerateOutputInformation "
165  << "Channels must reside into [1...] " << typeid(itk::ImageBase<InputImageDimension>*).name());
166  }
167  if (m_FirstChannel > m_LastChannel)
168  {
169  itkExceptionMacro(<< "otb::ExtractImageFilter::GenerateOutputInformation "
170  << "FirstChannel is greater than LastChannel" << typeid(itk::ImageBase<InputImageDimension>*).name());
171  }
172 
173  for (unsigned int channel = m_FirstChannel; channel <= m_LastChannel; channel++)
174  {
175  m_ChannelsWorks.push_back(channel);
176  }
177 
178  m_Channels = m_ChannelsWorks;
179 }
180 
190 template <class TInputPixelType, class TOutputPixelType>
192 {
193  // Call to the superclass implementation
194  Superclass::GenerateOutputInformation();
195  this->ChannelsReInitialization();
197 
198  typename Superclass::InputImageConstPointer inputPtr = this->GetInput();
199  typename Superclass::OutputImagePointer outputPtr = this->GetOutput();
200 
201  unsigned int nbComponentsPerPixel = inputPtr->GetNumberOfComponentsPerPixel();
202  if (m_ChannelsKind != 0)
203  {
204  // Test if the asked channels index exists in the input image
205  ChannelsType m_BadChannels;
206  m_BadChannels.clear();
207  for (unsigned int i = 0; i < m_ChannelsWorks.size(); ++i)
208  {
209  if ((m_ChannelsWorks[i] < 1) || (m_ChannelsWorks[i] > nbComponentsPerPixel))
210  {
211  bool isInsideBadChannels = false;
212  for (unsigned int j = 0; j < m_BadChannels.size(); ++j)
213  {
214  if (m_BadChannels[j] == m_ChannelsWorks[i])
215  isInsideBadChannels = true;
216  }
217  if (!isInsideBadChannels)
218  m_BadChannels.push_back(m_ChannelsWorks[i]);
219  }
220  }
221  if (m_BadChannels.empty() == false)
222  {
223  std::ostringstream oss;
224  oss << "otb::ExtractImageFilter::GenerateOutputInformation : ";
225  oss << "Channel(s) [ ";
226  for (unsigned int i = 0; i < m_BadChannels.size(); ++i)
227  {
228  oss << m_BadChannels[i] << " ";
229  }
230  oss << "] not authorized.";
231  oss << " Each channel index has to be in [1," << nbComponentsPerPixel << "].";
232  itkExceptionMacro(<< oss.str().c_str());
233  }
234  nbComponentsPerPixel = m_ChannelsWorks.size();
235  }
236 
237  // initialize the number of channels of the output image
238  outputPtr->SetNumberOfComponentsPerPixel(nbComponentsPerPixel);
239 }
240 
241 template <class TInputPixelType, class TOutputPixelType>
243 {
244  itkDebugMacro(<< "Actually executing");
245  // Get the input and output pointers
246  typename Superclass::InputImageConstPointer inputPtr = this->GetInput();
247  typename Superclass::OutputImagePointer outputPtr = this->GetOutput();
248 
249  // Define the portion of the input to walk for this thread
250  InputImageRegionType inputRegionForThread;
251  this->CallCopyOutputRegionToInputRegion(inputRegionForThread, outputRegionForThread);
252 
253  // Define the iterators.
254  typedef itk::ImageRegionIterator<OutputImageType> OutputIterator;
255  typedef itk::ImageRegionConstIterator<InputImageType> InputIterator;
256 
257  OutputIterator outIt(outputPtr, outputRegionForThread);
258  InputIterator inIt(inputPtr, inputRegionForThread);
259 
260  outIt.GoToBegin();
261  inIt.GoToBegin();
262 
263  // if default behaviour
264  if (m_ChannelsKind == 0)
265  {
266  // walk the output region, and sample the input image
267  while (!outIt.IsAtEnd())
268  {
269  outIt.Set(inIt.Get());
270  ++outIt;
271  ++inIt;
272  }
273  }
274  // Specific behaviour
275  else
276  {
277  // for each channel to process
278  unsigned int channelIn(0);
279  unsigned int channelOut(0);
280  unsigned int nbChannels(0);
281 
282  InputImagePixelType pixelInput;
283  while (!outIt.IsAtEnd())
284  {
285  OutputImagePixelType pixelOutput;
286  pixelOutput.Reserve(outputPtr->GetVectorLength());
287  pixelInput = inIt.Get();
288  channelOut = 0;
289  for (nbChannels = 0; nbChannels < m_ChannelsWorks.size(); ++nbChannels)
290  {
291  channelIn = m_ChannelsWorks[nbChannels] - 1;
292  pixelOutput[channelOut] = static_cast<OutputValueType>(pixelInput[channelIn]);
293  channelOut++;
294  }
295  outIt.Set(pixelOutput);
296  ++outIt;
297  ++inIt;
298  }
299  }
300 }
301 
302 } // end namespace otb
303 
304 #endif
Base class to extract area of images.
void PrintSelf(std::ostream &os, itk::Indent indent) const override
OutputImageType::InternalPixelType OutputValueType
InputImageType::RegionType InputImageRegionType
void SetChannel(unsigned int channel)
OutputImageType::PixelType OutputImagePixelType
std::vector< unsigned int > ChannelsType
InputImageType::PixelType InputImagePixelType
OutputImageType::RegionType OutputImageRegionType
void DynamicThreadedGenerateData(const OutputImageRegionType &outputRegionForThread) override
Creation of an "otb" vector image which contains metadata.
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.