OTB  9.0.0
Orfeo Toolbox
otbLabelImageToOGRDataSourceFilter.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 otbLabelImageToOGRDataSourceFilter_hxx
22 #define otbLabelImageToOGRDataSourceFilter_hxx
23 
25 #include "otbGdalDataTypeBridge.h"
26 
27 // gdal libraries
28 #include "gdal.h"
29 #include "gdal_priv.h"
30 #include "cpl_conv.h"
31 #include "gdal_alg.h"
32 
33 #include "stdint.h" //needed for uintptr_t
34 
35 namespace otb
36 {
37 template <class TInputImage>
39 {
40  this->SetNumberOfRequiredInputs(2);
41  this->SetNumberOfRequiredInputs(1);
42  this->SetNumberOfRequiredOutputs(1);
43 
44  GDALAllRegister();
45 
46  this->ProcessObject::SetNthOutput(0, this->MakeOutput(0));
47 }
48 
49 
50 template <class TInputImage>
53 {
54  return static_cast<DataObjectPointer>(OGRDataSourceType::New().GetPointer());
55 }
56 
57 template <class TInputImage>
59 {
60  return static_cast<const OGRDataSourceType*>(this->ProcessObject::GetOutput(0));
61 }
62 
63 template <class TInputImage>
65 {
66  this->Superclass::SetNthInput(0, const_cast<InputImageType*>(input));
67 }
68 
69 template <class TInputImage>
71 {
72  if (this->GetNumberOfInputs() < 1)
73  {
74  return nullptr;
75  }
76 
77  return static_cast<const InputImageType*>(this->Superclass::GetInput(0));
78 }
79 
80 template <class TInputImage>
82 {
83  this->Superclass::SetNthInput(1, const_cast<InputImageType*>(input));
84 }
85 
86 template <class TInputImage>
88 {
89  if (this->GetNumberOfInputs() < 2)
90  {
91  return nullptr;
92  }
93 
94  return static_cast<const InputImageType*>(this->Superclass::GetInput(1));
95 }
96 
97 template <class TInputImage>
99 {
100  // call the superclass' implementation of this method
101  Superclass::GenerateInputRequestedRegion();
102 
103  // get pointers to the inputs
104  typename InputImageType::Pointer input = const_cast<InputImageType*>(this->GetInput());
105 
106  if (!input)
107  {
108  return;
109  }
110  // The input is necessarily the largest possible region.
111  input->SetRequestedRegionToLargestPossibleRegion();
112 
113  typename InputImageType::Pointer mask = const_cast<InputImageType*>(this->GetInputMask());
114  if (!mask)
115  {
116  return;
117  }
118  // The input is necessarily the largest possible region.
119  mask->SetRequestedRegionToLargestPossibleRegion();
120 }
121 
122 
123 template <class TInputImage>
125 {
126  if (this->GetInput()->GetRequestedRegion() != this->GetInput()->GetLargestPossibleRegion())
127  {
128  itkExceptionMacro(<< "Not streamed filter. ERROR : requested region is not the largest possible region.");
129  }
130 
131  SizeType size;
132  unsigned int nbBands = 0;
133  unsigned int bytePerPixel = 0;
134 
135  /* Convert the input image into a GDAL raster needed by GDALPolygonize */
136  size = this->GetInput()->GetLargestPossibleRegion().GetSize();
137  nbBands = this->GetInput()->GetNumberOfComponentsPerPixel();
138  bytePerPixel = sizeof(InputPixelType);
139 
140  // buffer casted in unsigned long cause under Win32 the address
141  // don't begin with 0x, the address in not interpreted as
142  // hexadecimal but alpha numeric value, then the conversion to
143  // integer make us pointing to an non allowed memory block => Crash.
144  std::ostringstream stream;
145  stream << "MEM:::"
146  << "DATAPOINTER=" << (uintptr_t)(this->GetInput()->GetBufferPointer()) << ","
147  << "PIXELS=" << size[0] << ","
148  << "LINES=" << size[1] << ","
149  << "BANDS=" << nbBands << ","
150  << "DATATYPE=" << GDALGetDataTypeName(GdalDataTypeBridge::GetGDALDataType<InputPixelType>()) << ","
151  << "PIXELOFFSET=" << bytePerPixel * nbBands << ","
152  << "LINEOFFSET=" << bytePerPixel * nbBands * size[0] << ","
153  << "BANDOFFSET=" << bytePerPixel;
154 
155  GDALDataset* dataset = static_cast<GDALDataset*>(GDALOpen(stream.str().c_str(), GA_ReadOnly));
156 
157  // Set input Projection ref and Geo transform to the dataset.
158  dataset->SetProjection(this->GetInput()->GetProjectionRef().c_str());
159 
160  unsigned int projSize = this->GetInput()->GetGeoTransform().size();
161  double geoTransform[6];
162 
163  // Set the geo transform of the input image (if any)
164  // Reporting origin and spacing of the buffered region
165  // the spacing is unchanged, the origin is relative to the buffered region
166  IndexType bufferIndexOrigin = this->GetInput()->GetBufferedRegion().GetIndex();
167  OriginType bufferOrigin;
168  this->GetInput()->TransformIndexToPhysicalPoint(bufferIndexOrigin, bufferOrigin);
169  geoTransform[0] = bufferOrigin[0] - 0.5 * this->GetInput()->GetSignedSpacing()[0];
170  geoTransform[3] = bufferOrigin[1] - 0.5 * this->GetInput()->GetSignedSpacing()[1];
171  geoTransform[1] = this->GetInput()->GetSignedSpacing()[0];
172  geoTransform[5] = this->GetInput()->GetSignedSpacing()[1];
173  // FIXME: Here component 1 and 4 should be replaced by the orientation parameters
174  if (projSize == 0)
175  {
176  geoTransform[2] = 0.;
177  geoTransform[4] = 0.;
178  }
179  else
180  {
181  geoTransform[2] = this->GetInput()->GetGeoTransform()[2];
182  geoTransform[4] = this->GetInput()->GetGeoTransform()[4];
183  }
184  dataset->SetGeoTransform(geoTransform);
185 
186  // Create the output layer for GDALPolygonize().
188 
189  OGRLayerType outputLayer = ogrDS->CreateLayer("layer", nullptr, wkbPolygon);
190 
191  OGRFieldDefn field(m_FieldName.c_str(), OFTInteger);
192  outputLayer.CreateField(field, true);
193 
194  // Call GDALPolygonize()
195  char** options;
196  options = nullptr;
197  char* option[2] = {nullptr, nullptr};
198  if (m_Use8Connected == true)
199  {
200  std::string opt("8CONNECTED:8");
201  option[0] = const_cast<char*>(opt.c_str());
202  options = option;
203  }
204 
205  /* Convert the mask input into a GDAL raster needed by GDALPolygonize */
206  typename InputImageType::ConstPointer inputMask = this->GetInputMask();
207  if (!inputMask.IsNull())
208  {
209  size = this->GetInputMask()->GetLargestPossibleRegion().GetSize();
210  nbBands = this->GetInputMask()->GetNumberOfComponentsPerPixel();
211  bytePerPixel = sizeof(InputPixelType);
212  // buffer casted in unsigned long cause under Win32 the address
213  // don't begin with 0x, the address in not interpreted as
214  // hexadecimal but alpha numeric value, then the conversion to
215  // integer make us pointing to an non allowed memory block => Crash.
216  std::ostringstream maskstream;
217  maskstream << "MEM:::"
218  << "DATAPOINTER=" << (uintptr_t)(this->GetInputMask()->GetBufferPointer()) << ","
219  << "PIXELS=" << size[0] << ","
220  << "LINES=" << size[1] << ","
221  << "BANDS=" << nbBands << ","
222  << "DATATYPE=" << GDALGetDataTypeName(GdalDataTypeBridge::GetGDALDataType<InputPixelType>()) << ","
223  << "PIXELOFFSET=" << bytePerPixel * nbBands << ","
224  << "LINEOFFSET=" << bytePerPixel * nbBands * size[0] << ","
225  << "BANDOFFSET=" << bytePerPixel;
226 
227  GDALDataset* maskDataset = static_cast<GDALDataset*>(GDALOpen(maskstream.str().c_str(), GA_ReadOnly));
228 
229  // Set input Projection ref and Geo transform to the dataset.
230  maskDataset->SetProjection(this->GetInputMask()->GetProjectionRef().c_str());
231 
232  projSize = this->GetInputMask()->GetGeoTransform().size();
233 
234  // Set the geo transform of the input mask image (if any)
235  // Reporting origin and spacing of the buffered region
236  // the spacing is unchanged, the origin is relative to the buffered region
237  bufferIndexOrigin = this->GetInputMask()->GetBufferedRegion().GetIndex();
238  this->GetInputMask()->TransformIndexToPhysicalPoint(bufferIndexOrigin, bufferOrigin);
239  geoTransform[0] = bufferOrigin[0] - 0.5 * this->GetInputMask()->GetSignedSpacing()[0];
240  geoTransform[3] = bufferOrigin[1] - 0.5 * this->GetInputMask()->GetSignedSpacing()[1];
241  geoTransform[1] = this->GetInputMask()->GetSignedSpacing()[0];
242  geoTransform[5] = this->GetInputMask()->GetSignedSpacing()[1];
243  // FIXME: Here component 1 and 4 should be replaced by the orientation parameters
244  if (projSize == 0)
245  {
246  geoTransform[2] = 0.;
247  geoTransform[4] = 0.;
248  }
249  else
250  {
251  geoTransform[2] = this->GetInputMask()->GetGeoTransform()[2];
252  geoTransform[4] = this->GetInputMask()->GetGeoTransform()[4];
253  }
254  maskDataset->SetGeoTransform(geoTransform);
255 
256  GDALPolygonize(dataset->GetRasterBand(1), maskDataset->GetRasterBand(1), &outputLayer.ogr(), 0, options, nullptr, nullptr);
257  GDALClose(maskDataset);
258  }
259  else
260  {
261  GDALPolygonize(dataset->GetRasterBand(1), nullptr, &outputLayer.ogr(), 0, options, nullptr, nullptr);
262  }
263 
264  this->SetNthOutput(0, ogrDS);
265 
266  // Clear memory
267  GDALClose(dataset);
268 }
269 
270 
271 } // end namespace otb
272 
273 #endif
otb::LabelImageToOGRDataSourceFilter::GetInputMask
virtual const InputImageType * GetInputMask(void)
Definition: otbLabelImageToOGRDataSourceFilter.hxx:87
otb::LabelImageToOGRDataSourceFilter::GetInput
virtual const InputImageType * GetInput(void)
Definition: otbLabelImageToOGRDataSourceFilter.hxx:70
otb::LabelImageToOGRDataSourceFilter::OriginType
InputImageType::PointType OriginType
Definition: otbLabelImageToOGRDataSourceFilter.h:70
otb::LabelImageToOGRDataSourceFilter::IndexType
InputImageType::IndexType IndexType
Definition: otbLabelImageToOGRDataSourceFilter.h:71
otb
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.
Definition: otbJoinContainer.h:32
otb::ogr::DataSource
Collection of geometric objects.
Definition: otbOGRDataSourceWrapper.h:83
otb::LabelImageToOGRDataSourceFilter::DataObjectPointer
itk::DataObject::Pointer DataObjectPointer
Definition: otbLabelImageToOGRDataSourceFilter.h:130
otb::LabelImageToOGRDataSourceFilter::GenerateData
void GenerateData() override
Definition: otbLabelImageToOGRDataSourceFilter.hxx:124
otb::LabelImageToOGRDataSourceFilter::InputPixelType
InputImageType::PixelType InputPixelType
Definition: otbLabelImageToOGRDataSourceFilter.h:65
otb::LabelImageToOGRDataSourceFilter::GetOutput
const OGRDataSourceType * GetOutput()
Definition: otbLabelImageToOGRDataSourceFilter.hxx:58
otb::LabelImageToOGRDataSourceFilter::LabelImageToOGRDataSourceFilter
LabelImageToOGRDataSourceFilter()
Definition: otbLabelImageToOGRDataSourceFilter.hxx:38
otb::LabelImageToOGRDataSourceFilter::GenerateInputRequestedRegion
void GenerateInputRequestedRegion() override
Definition: otbLabelImageToOGRDataSourceFilter.hxx:98
otb::ogr::Layer::ogr
OGRLayer & ogr()
otb::LabelImageToOGRDataSourceFilter::InputImageType
TInputImage InputImageType
Definition: otbLabelImageToOGRDataSourceFilter.h:61
otbLabelImageToOGRDataSourceFilter.h
otb::ogr::Layer::CreateField
void CreateField(FieldDefn const &field, bool bApproxOK=true)
otbGdalDataTypeBridge.h
otb::LabelImageToOGRDataSourceFilter::MakeOutput
DataObjectPointer MakeOutput(DataObjectPointerArraySizeType idx) override
Definition: otbLabelImageToOGRDataSourceFilter.hxx:52
otb::ogr::DataSource::Pointer
itk::SmartPointer< Self > Pointer
Definition: otbOGRDataSourceWrapper.h:90
otb::LabelImageToOGRDataSourceFilter::SetInput
virtual void SetInput(const InputImageType *input)
Definition: otbLabelImageToOGRDataSourceFilter.hxx:64
otb::ogr::Layer
Layer of geometric objects.
Definition: otbOGRLayerWrapper.h:80
otb::LabelImageToOGRDataSourceFilter::SizeType
InputImageType::SizeType SizeType
Definition: otbLabelImageToOGRDataSourceFilter.h:67
otb::ogr::DataSource::New
static Pointer New()
otb::LabelImageToOGRDataSourceFilter::DataObjectPointerArraySizeType
itk::ProcessObject::DataObjectPointerArraySizeType DataObjectPointerArraySizeType
Definition: otbLabelImageToOGRDataSourceFilter.h:77
otb::LabelImageToOGRDataSourceFilter::SetInputMask
virtual void SetInputMask(const InputImageType *input)
Definition: otbLabelImageToOGRDataSourceFilter.hxx:81