OTB  6.3.0
Orfeo Toolbox
otbObjectDetectionClassifier.txx
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2017 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 otbObjectDetectionClassifier_txx
22 #define otbObjectDetectionClassifier_txx
23 
25 
26 #include "itkContinuousIndex.h"
27 
28 namespace otb
29 {
30 
31 template <class TInputImage, class TOutputVectorData, class TLabel, class TFunctionType>
34  : m_NeighborhoodRadius(0),
35  m_ClassKey("Class"),
36  m_NoClassLabel(0),
37  m_GridStep(10)
38 {
39  this->SetNumberOfRequiredInputs(1);
40 
41  // Have 2 outputs : the image created by Superclass, a vector data with points
42  this->SetNumberOfRequiredOutputs(3);
43  this->itk::ProcessObject::SetNthOutput(1, this->MakeOutput(1).GetPointer());
44  this->itk::ProcessObject::SetNthOutput(2, this->MakeOutput(2).GetPointer());
45 }
46 
47 template <class TInputImage, class TOutputVectorData, class TLabel, class TFunctionType>
50 {
51 }
52 
53 template <class TInputImage, class TOutputVectorData, class TLabel, class TFunctionType>
54 void
57 {
58  // This is commented to prevent the streaming of the whole image for the first stream strip
59  // It shall not cause any problem because the output image of this filter is not intended to be used.
60  //InputImagePointer image = const_cast< TInputImage * >( this->GetInput() );
61  //this->GraftOutput( image );
62  // Nothing that needs to be allocated for the remaining outputs
63 }
64 
65 template <class TInputImage, class TOutputVectorData, class TLabel, class TFunctionType>
66 void
69 {
70  Superclass::GenerateOutputInformation();
71  if (this->GetInput())
72  {
73  this->GetOutput()->CopyInformation(this->GetInput());
74  this->GetOutput()->SetLargestPossibleRegion(this->GetInput()->GetLargestPossibleRegion());
75 
76  if (this->GetOutput()->GetRequestedRegion().GetNumberOfPixels() == 0)
77  {
78  this->GetOutput()->SetRequestedRegion(this->GetOutput()->GetLargestPossibleRegion());
79  }
80  }
81 }
82 
83 template <class TInputImage, class TOutputVectorData, class TLabel, class TFunctionType>
84 void
87 {
88  if (model != m_Model)
89  {
90  m_Model = model;
91  this->Modified();
92  }
93 }
94 
95 template <class TInputImage, class TOutputVectorData, class TLabel, class TFunctionType>
98 ::GetModel(void) const
99 {
100  return m_Model;
101 }
102 
103 template <class TInputImage, class TOutputVectorData, class TLabel, class TFunctionType>
107 {
108  return static_cast<VectorDataType*>(this->itk::ProcessObject::GetOutput(1));
109 }
110 
111 template <class TInputImage, class TOutputVectorData, class TLabel, class TFunctionType>
115 {
117  switch (idx)
118  {
119  case 0:
120  output = static_cast<itk::DataObject*>(InputImageType::New().GetPointer());
121  break;
122  case 1:
123  {
124  output = static_cast<itk::DataObject*>(VectorDataType::New().GetPointer());
125  break;
126  }
127  default:
128  output = static_cast<itk::DataObject*>(InputImageType::New().GetPointer());
129  break;
130  }
131  return output;
132 }
133 
134 template <class TInputImage, class TOutputVectorData, class TLabel, class TFunctionType>
135 void
138 {
139  m_ThreadPointArray = PointArrayContainer(this->GetNumberOfThreads());
140 
141 }
142 
143 template <class TInputImage, class TOutputVectorData, class TLabel, class TFunctionType>
144 void
147 {
148  // merge all points in a single vector data
149  //std::copy(m_ThreadPointArray[0].begin(), m_ThreadPointArray[0].end(),
150  //std::ostream_iterator<DescriptorsFunctionPointType>(std::cout, "\n") );
151 
152  VectorDataType* vdata = this->GetOutputVectorData();
153 
154  // Retrieving root node
155  VectorDataNodePointerType root = vdata->GetDataTree()->GetRoot()->Get();
156  // Create the document node
157  VectorDataNodePointerType document = VectorDataNodeType::New();
158  document->SetNodeType(otb::DOCUMENT);
159  VectorDataNodePointerType folder = VectorDataNodeType::New();
160  folder->SetNodeType(otb::FOLDER);
161  // Adding the layer to the data tree
162  vdata->GetDataTree()->Add(document, root);
163  vdata->GetDataTree()->Add(folder, document);
164 
165  for (itk::ThreadIdType threadId = 0; threadId < m_ThreadPointArray.size(); ++threadId)
166  {
167  PointArray& pointArray = m_ThreadPointArray[threadId];
168  typename PointArray::const_iterator it = pointArray.begin();
169  typename PointArray::const_iterator end = pointArray.end();
170 
171  for (; it != end; ++it)
172  {
173  VectorDataNodePointerType currentGeometry = VectorDataNodeType::New();
174  currentGeometry->SetNodeId("FEATURE_POINT");
175  currentGeometry->SetNodeType(otb::FEATURE_POINT);
177  p[0] = it->first[0];
178  p[1] = it->first[1];
179  currentGeometry->SetPoint(p);
180  currentGeometry->SetFieldAsInt(m_ClassKey, it->second);
181  vdata->GetDataTree()->Add(currentGeometry, folder);
182  }
183  }
184 }
185 
186 template <class TInputImage, class TOutputVectorData, class TLabel, class TFunctionType>
187 void
189 ::PrintSelf(std::ostream& os, itk::Indent indent) const
190 {
191  Superclass::PrintSelf(os, indent);
192 }
193 
194 template <class TInputImage, class TOutputVectorData, class TLabel, class TFunctionType>
195 void
198 {
199  Superclass::GenerateInputRequestedRegion();
200 
201  // get pointers to the input and output
202  typename Superclass::InputImagePointer inputPtr =
203  const_cast< TInputImage * >( this->GetInput() );
204  typename Superclass::OutputImagePointer outputPtr = this->GetOutput();
205 
206  if ( !inputPtr || !outputPtr )
207  {
208  return;
209  }
210 
211  // get a copy of the input requested region (should equal the output
212  // requested region)
213  typename TInputImage::RegionType inputRequestedRegion;
214  inputRequestedRegion = inputPtr->GetRequestedRegion();
215 
216  // pad the input requested region by the operator radius
217  inputRequestedRegion.PadByRadius( m_NeighborhoodRadius + 1 );
218 
219  // crop the input requested region at the input's largest possible region
220  if ( inputRequestedRegion.Crop(inputPtr->GetLargestPossibleRegion()) )
221  {
222  inputPtr->SetRequestedRegion( inputRequestedRegion );
223  return;
224  }
225  else
226  {
227  // Couldn't crop the region (requested region is outside the largest
228  // possible region). Throw an exception.
229 
230  // store what we tried to request (prior to trying to crop)
231  inputPtr->SetRequestedRegion( inputRequestedRegion );
232  }
233 }
234 
235 template <class TInputImage, class TOutputVectorData, class TLabel, class TFunctionType>
236 void
239 {
240  // Compute the 1/(sigma) vector
241  m_InvertedScales = m_Scales;
242  for(unsigned int idx = 0; idx < m_Scales.Size(); ++idx)
243  {
244  if(m_Scales[idx]-1e-10 < 0.)
245  m_InvertedScales[idx] = 0.;
246  else
247  m_InvertedScales[idx] = 1 / m_Scales[idx];
248  }
249 
250 }
251 
252 template <class TInputImage, class TOutputVectorData, class TLabel, class TFunctionType>
253 void
255 ::ThreadedGenerateData(const RegionType& outputRegionForThread,
256  itk::ThreadIdType threadId)
257 {
258  InputImageType* input = static_cast<InputImageType*>(this->itk::ProcessObject::GetInput(0));
259  const ModelType* model = this->GetModel();
260 
261  typedef typename RegionType::IndexType IndexType;
262  IndexType begin = outputRegionForThread.GetIndex();
263  IndexType end = begin;
264  end[0] += outputRegionForThread.GetSize(0);
265  end[1] += outputRegionForThread.GetSize(1);
266 
267  IndexType current = begin;
268  for (; current[1] != end[1]; current[1]++)
269  {
270  if (current[1] % m_GridStep == 0)
271  {
272  for(current[0] = begin[0]; current[0] != end[0]; current[0]++)
273  {
274  if (current[0] % m_GridStep == 0)
275  {
277  input->TransformIndexToPhysicalPoint(current, point);
278 
279  DescriptorType descriptor = m_DescriptorsFunction->Evaluate(point);
280  ModelMeasurementType modelMeasurement(descriptor.GetSize());
281  for (unsigned int i = 0; i < descriptor.GetSize(); ++i)
282  {
283  modelMeasurement[i] = (descriptor[i] - m_Shifts[i]) * m_InvertedScales[i];
284  }
285  LabelType label = (model->Predict(modelMeasurement))[0];
286 
287  if (label != m_NoClassLabel)
288  {
289  m_ThreadPointArray[threadId].push_back(std::make_pair(point, label));
290  }
291  }
292  }
293  }
294  }
295 }
296 
297 
298 template <class TInputImage, class TOutputVectorData, class TLabel, class TFunctionPrecision, class TCoordRep>
301 {
302 
303 }
304 
305 template <class TInputImage, class TOutputVectorData, class TLabel, class TFunctionPrecision, class TCoordRep>
308 {
309 
310 }
311 
312 
313 } // end namespace otb
314 
315 #endif
DescriptorsFunctionType::OutputType DescriptorType
DescriptorsFunctionType::InputType DescriptorsFunctionPointType
Superclass::DataObjectPointerArraySizeType DataObjectPointerArraySizeType
MachineLearningModel is the base class for all classifier objects (SVM, KNN, Random Forests...
itk::DataObject::Pointer MakeOutput(DataObjectPointerArraySizeType idx) ITK_OVERRIDE
VectorDataType::DataNodePointerType VectorDataNodePointerType
itk::Index< Monteverdi_DIMENSION > IndexType
Definition: mvdTypes.h:142
void ThreadedGenerateData(const RegionType &outputRegionForThread, itk::ThreadIdType threadId) ITK_OVERRIDE
unsigned int ThreadIdType
DataObject * GetInput(const DataObjectIdentifierType &key)
TargetSampleType Predict(const InputSampleType &input, ConfidenceValueType *quality=ITK_NULLPTR) const
virtual void SetNthOutput(DataObjectPointerArraySizeType num, DataObject *output)
void PrintSelf(std::ostream &os, itk::Indent indent) const ITK_OVERRIDE
DataObject * GetOutput(const DataObjectIdentifierType &key)