Forked from Cresson Remi / otbtf
Source project has a limited visibility.
otbDensePolygonClassStatistics.cxx 10.40 KiB
/*=========================================================================
  Copyright (c) Remi Cresson (IRSTEA). All rights reserved.
     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.
=========================================================================*/
#include "otbWrapperApplication.h"
#include "otbWrapperApplicationFactory.h"
#include "otbStatisticsXMLFileWriter.h"
#include "otbWrapperElevationParametersHandler.h"
#include "otbVectorDataToLabelImageFilter.h"
#include "otbImageToNoDataMaskFilter.h"
#include "otbStreamingStatisticsMapFromLabelImageFilter.h"
#include "otbVectorDataIntoImageProjectionFilter.h"
#include "otbImageToVectorImageCastFilter.h"
#include "otbOGR.h"
namespace otb
namespace Wrapper
/** Utility function to negate std::isalnum */
bool IsNotAlphaNum(char c)
  return !std::isalnum(c);
class DensePolygonClassStatistics : public Application
public:
  /** Standard class typedefs. */
  typedef DensePolygonClassStatistics        Self;
  typedef Application                   Superclass;
  typedef itk::SmartPointer<Self>       Pointer;
  typedef itk::SmartPointer<const Self> ConstPointer;
  /** Standard macro */
  itkNewMacro(Self);
  itkTypeMacro(DensePolygonClassStatistics, otb::Application);
  /** DataObjects typedef */
  typedef UInt32ImageType                           LabelImageType;
  typedef UInt8ImageType                            MaskImageType;
  typedef VectorData<>                              VectorDataType;
  /** ProcessObjects typedef */
  typedef otb::VectorDataIntoImageProjectionFilter<VectorDataType,
      FloatVectorImageType>                                                       VectorDataReprojFilterType;
  typedef otb::VectorDataToLabelImageFilter<VectorDataType, LabelImageType>       RasterizeFilterType;
  typedef otb::VectorImage<MaskImageType::PixelType>                              InternalMaskImageType;
  typedef otb::ImageToNoDataMaskFilter<FloatVectorImageType, MaskImageType>       NoDataMaskFilterType;
  typedef otb::ImageToVectorImageCastFilter<MaskImageType, InternalMaskImageType> CastFilterType;
  typedef otb::StreamingStatisticsMapFromLabelImageFilter<InternalMaskImageType,
      LabelImageType>                                                             StatsFilterType;
  typedef otb::StatisticsXMLFileWriter<FloatVectorImageType::PixelType>           StatWriterType;
private:
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
DensePolygonClassStatistics() { } void DoInit() override { SetName("DensePolygonClassStatistics"); SetDescription("Computes statistics on a training polygon set."); // Documentation SetDocName("Fast Polygon Class Statistics"); SetDocLongDescription("The application processes a dense set of polygons " "intended for training (they should have a field giving the associated " "class). The geometries are analyzed against a support image to compute " "statistics : \n" " - number of samples per class\n" " - number of samples per geometry\n"); SetDocLimitations("None"); SetDocAuthors("Remi Cresson"); SetDocSeeAlso(" "); AddDocTag(Tags::Learning); AddParameter(ParameterType_InputImage, "in", "Input image"); SetParameterDescription("in", "Support image that will be classified"); AddParameter(ParameterType_InputVectorData, "vec", "Input vectors"); SetParameterDescription("vec","Input geometries to analyze"); AddParameter(ParameterType_OutputFilename, "out", "Output XML statistics file"); SetParameterDescription("out","Output file to store statistics (XML format)"); AddParameter(ParameterType_ListView, "field", "Field Name"); SetParameterDescription("field","Name of the field carrying the class number in the input vectors."); SetListViewSingleSelectionMode("field",true); ElevationParametersHandler::AddElevationParameters(this, "elev"); AddRAMParameter(); // Doc example parameter settings SetDocExampleParameterValue("in", "support_image.tif"); SetDocExampleParameterValue("vec", "variousVectors.shp"); SetDocExampleParameterValue("field", "label"); SetDocExampleParameterValue("out","polygonStat.xml"); SetOfficialDocLink(); } void DoUpdateParameters() override { if ( HasValue("vec") ) { std::string vectorFile = GetParameterString("vec"); ogr::DataSource::Pointer ogrDS = ogr::DataSource::New(vectorFile, ogr::DataSource::Modes::Read); ogr::Layer layer = ogrDS->GetLayer(0); ogr::Feature feature = layer.ogr().GetNextFeature(); ClearChoices("field"); for(int iField=0; iField<feature.ogr().GetFieldCount(); iField++) { std::string key, item = feature.ogr().GetFieldDefnRef(iField)->GetNameRef(); key = item; std::string::iterator end = std::remove_if(key.begin(),key.end(),IsNotAlphaNum); std::transform(key.begin(), end, key.begin(), tolower); OGRFieldType fieldType = feature.ogr().GetFieldDefnRef(iField)->GetType();
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
if(fieldType == OFTString || fieldType == OFTInteger || ogr::version_proxy::IsOFTInteger64(fieldType)) { std::string tmpKey="field."+key.substr(0, end - key.begin()); AddChoice(tmpKey,item); } } } // Check that the extension of the output parameter is XML (mandatory for // StatisticsXMLFileWriter) // Check it here to trigger the error before polygons analysis if ( HasValue("out") ) { // Store filename extension // Check that the right extension is given : expected .xml const std::string extension = itksys::SystemTools::GetFilenameLastExtension(this->GetParameterString("out")); if (itksys::SystemTools::LowerCase(extension) != ".xml") { otbAppLogFATAL( << extension << " is a wrong extension for parameter \"out\": Expected .xml" ); } } } void DoExecute() override { // Filters VectorDataReprojFilterType::Pointer m_VectorDataReprojectionFilter; RasterizeFilterType::Pointer m_RasterizeFIDFilter; RasterizeFilterType::Pointer m_RasterizeClassFilter; NoDataMaskFilterType::Pointer m_NoDataFilter; CastFilterType::Pointer m_NoDataCastFilter; StatsFilterType::Pointer m_FIDStatsFilter; StatsFilterType::Pointer m_ClassStatsFilter; // Retrieve the field name std::vector<int> selectedCFieldIdx = GetSelectedItems("field"); if(selectedCFieldIdx.empty()) { otbAppLogFATAL(<<"No field has been selected for data labelling!"); } std::vector<std::string> cFieldNames = GetChoiceNames("field"); std::string fieldName = cFieldNames[selectedCFieldIdx.front()]; otb::Wrapper::ElevationParametersHandler::SetupDEMHandlerFromElevationParameters(this,"elev"); // Get inputs FloatVectorImageType::Pointer xs = GetParameterImage("in"); VectorDataType* shp = GetParameterVectorData("vec"); // Reproject vector data m_VectorDataReprojectionFilter = VectorDataReprojFilterType::New(); m_VectorDataReprojectionFilter->SetInputVectorData(shp); m_VectorDataReprojectionFilter->SetInputImage(xs); m_VectorDataReprojectionFilter->Update(); // Internal no-data value const LabelImageType::ValueType intNoData = itk::NumericTraits<LabelImageType::ValueType>::max(); // Rasterize vector data (geometry ID) m_RasterizeFIDFilter = RasterizeFilterType::New(); m_RasterizeFIDFilter->AddVectorData(m_VectorDataReprojectionFilter->GetOutput()); m_RasterizeFIDFilter->SetOutputOrigin(xs->GetOrigin()); m_RasterizeFIDFilter->SetOutputSpacing(xs->GetSignedSpacing());