diff --git a/Documentation/SoftwareGuide/Latex/Installation.tex b/Documentation/SoftwareGuide/Latex/Installation.tex index 8ccfa9df9a6088ba295fd4b910c173a3af70f16c..b4ad2a3145da54529041519df2f1632c8fe07d50 100644 --- a/Documentation/SoftwareGuide/Latex/Installation.tex +++ b/Documentation/SoftwareGuide/Latex/Installation.tex @@ -86,7 +86,7 @@ See table \ref{tab:otb-dependencies} for the full list of dependencies. \hline \textbf{ITK} & \url{http://www.itk.org} & yes & 4.6.0 \\ \hline -\textbf{GDAL} & \url{http://www.gdal.org} & yes & 1.10 (2.x also supported) \\ +\textbf{GDAL} & \url{http://www.gdal.org} & yes & 2.0 \\ \hline \textbf{OSSIM} & \url{http://www.ossim.org} & yes & 1.8.20-3 \\ \hline diff --git a/Examples/Filtering/GeometriesChangeSpatialReference.cxx b/Examples/Filtering/GeometriesChangeSpatialReference.cxx index 082f426cf796a0be81df428fcff46d70a44a8aa9..e57e8c866d5cf82591d1152fa7b1d23baa611142 100644 --- a/Examples/Filtering/GeometriesChangeSpatialReference.cxx +++ b/Examples/Filtering/GeometriesChangeSpatialReference.cxx @@ -209,10 +209,10 @@ int main (int argc, char **argv) = options.workingInplace ? input : options.outputIsStdout ? nullptr : otb::ogr::DataSource::New( options.outputFile, otb::ogr::DataSource::Modes::Update_LayerCreateOnly); - std::cout << "input: " << otb::ogr::version_proxy::GetFileListAsStringVector(&input->ogr())[0] << " should be: " << options.inputFile << "\n"; + std::cout << "input: " << otb::ogr::GetFileListAsStringVector(&input->ogr())[0] << " should be: " << options.inputFile << "\n"; if (output) { - std::cout << "output: " << otb::ogr::version_proxy::GetFileListAsStringVector(&output->ogr())[0] << " should be: " << options.outputFile << "\n"; + std::cout << "output: " << otb::ogr::GetFileListAsStringVector(&output->ogr())[0] << " should be: " << options.outputFile << "\n"; } // std::cout << "\n"; diff --git a/Examples/Filtering/GeometriesFilter.cxx b/Examples/Filtering/GeometriesFilter.cxx index 922d05e5eccf83481f797b94e89cc9569765f660..bd59d09dfeb04fa9834d8b04d1411d4607af31dc 100644 --- a/Examples/Filtering/GeometriesFilter.cxx +++ b/Examples/Filtering/GeometriesFilter.cxx @@ -76,10 +76,10 @@ int main (int argc, char **argv) = workingInplace ? input : outputIsStdout ? nullptr : otb::ogr::DataSource::New( outputFile, otb::ogr::DataSource::Modes::Update_LayerCreateOnly); - std::cout << "input: " << otb::ogr::version_proxy::GetFileListAsStringVector(&input->ogr())[0] << " should be: " << inputFile << "\n"; + std::cout << "input: " << otb::ogr::GetFileListAsStringVector(&input->ogr())[0] << " should be: " << inputFile << "\n"; if (output) { - std::cout << "output: " << otb::ogr::version_proxy::GetFileListAsStringVector(&output->ogr())[0] << " should be: " << outputFile << "\n"; + std::cout << "output: " << otb::ogr::GetFileListAsStringVector(&output->ogr())[0] << " should be: " << outputFile << "\n"; } // std::cout << "\n"; diff --git a/Modules/Adapters/GdalAdapters/include/otbOGRDataSourceWrapper.h b/Modules/Adapters/GdalAdapters/include/otbOGRDataSourceWrapper.h index f75d86e7847099a0c757f3e0b239f48fa47ad51b..f3a149a974367e652a821ada687d731096bca4cb 100644 --- a/Modules/Adapters/GdalAdapters/include/otbOGRDataSourceWrapper.h +++ b/Modules/Adapters/GdalAdapters/include/otbOGRDataSourceWrapper.h @@ -45,7 +45,6 @@ #include "itkObjectFactory.h" // that should have been included by itkMacro.h #include "otbOGRLayerWrapper.h" -#include "otbOGRVersionProxy.h" #include "otbOGRExtendedFilenameToOptions.h" class OGRLayer; @@ -164,7 +163,7 @@ public: * \note No condition is assumed on the non-nullity of \c source. * \see \c DataSource(GDALDataset *) */ - static Pointer New(ogr::version_proxy::GDALDatasetType * sourcemode, Modes::type mode = Modes::Read , const std::vector< std::string > & layerOptions = std::vector< std::string >() ); + static Pointer New(GDALDataset * sourcemode, Modes::type mode = Modes::Read , const std::vector< std::string > & layerOptions = std::vector< std::string >() ); //@} /**\name Projection Reference property */ @@ -301,7 +300,7 @@ public: * \throw None * \post Assumes ownership of the \c source. */ - void Reset(ogr::version_proxy::GDALDatasetType * source); + void Reset(GDALDataset * source); /**\name Layers modification */ //@{ @@ -477,8 +476,6 @@ public: } /** Flushes all changes to disk. - * \throw itd::ExceptionObject in case the flush operation failed. - * \sa \c GDALDataset::SyncToDisk() */ void SyncToDisk(); @@ -497,7 +494,7 @@ public: * \warning You must under no circumstance try to delete the \c GDALDataset * obtained this way. */ - ogr::version_proxy::GDALDatasetType & ogr(); + GDALDataset & ogr(); void SetLayerCreationOptions( const std::vector< std::string > & options ); void AddLayerCreationOptions( std::vector< std::string > options ); @@ -517,7 +514,7 @@ protected: /** Init constructor. * \post The newly constructed object owns the \c source parameter. */ - DataSource(ogr::version_proxy::GDALDatasetType * source, Modes::type mode , const std::vector< std::string > & layerOption = std::vector< std::string >() ); + DataSource(GDALDataset * source, Modes::type mode , const std::vector< std::string > & layerOption = std::vector< std::string >() ); /** Destructor. * \post The \c GDALDataset owned is released (if not null). */ @@ -554,7 +551,7 @@ private: std::string GetDatasetDescription() const; private: - ogr::version_proxy::GDALDatasetType *m_DataSource; + GDALDataset *m_DataSource; std::vector< std::string > m_LayerOptions; Modes::type m_OpenMode; int m_FirstModifiableLayerID; diff --git a/Modules/Adapters/GdalAdapters/include/otbOGRDataSourceWrapper.hxx b/Modules/Adapters/GdalAdapters/include/otbOGRDataSourceWrapper.hxx index e2990958c6d871df3e433ca66732cd5e77c0b760..acfea3a977c90c7c4738f1716e7a7c4be5cd37ef 100644 --- a/Modules/Adapters/GdalAdapters/include/otbOGRDataSourceWrapper.hxx +++ b/Modules/Adapters/GdalAdapters/include/otbOGRDataSourceWrapper.hxx @@ -43,7 +43,7 @@ // to the compilation mode of the client code. inline -otb::ogr::version_proxy::GDALDatasetType & otb::ogr::DataSource::ogr() +GDALDataset & otb::ogr::DataSource::ogr() { assert(m_DataSource && "GDALDataset not initialized"); return *m_DataSource; diff --git a/Modules/Adapters/GdalAdapters/include/otbOGRFieldWrapper.hxx b/Modules/Adapters/GdalAdapters/include/otbOGRFieldWrapper.hxx index 258db5172ef7632fa454444bababb233abae9129..2ac3137985b80832f7db3ba60b7d0f1d68d059af 100644 --- a/Modules/Adapters/GdalAdapters/include/otbOGRFieldWrapper.hxx +++ b/Modules/Adapters/GdalAdapters/include/otbOGRFieldWrapper.hxx @@ -97,10 +97,9 @@ typedef mpl::map , mpl::pair<char* , mpl::int_<OFTString> > , mpl::pair<char const* , mpl::int_<OFTString> > , mpl::pair<std::vector<std::string>, mpl::int_<OFTStringList> > - #ifdef OTB_USE_GDAL_20 - , mpl::pair<GIntBig, mpl::int_<OFTInteger64> > - , mpl::pair<std::vector<GIntBig>, mpl::int_<OFTInteger64List> > - #endif + , mpl::pair<GIntBig, mpl::int_<OFTInteger64> > + , mpl::pair<std::vector<GIntBig>, mpl::int_<OFTInteger64List> > + // OFTBinary // OFTDate // OFTTime @@ -341,10 +340,8 @@ typedef mpl::map , mpl::pair<mpl::int_<OFTRealList>, MemberContainerGetterPtr<double, &OGRFeature::GetFieldAsDoubleList> > , mpl::pair<mpl::int_<OFTString>, MemberGetterPtr<char const*, &OGRFeature::GetFieldAsString, std::string> > , mpl::pair<mpl::int_<OFTStringList>, StringListMemberGetterPtr<std::vector<std::string> > > - #ifdef OTB_USE_GDAL_20 , mpl::pair<mpl::int_<OFTInteger64>, MemberGetterPtr<GIntBig, &OGRFeature::GetFieldAsInteger64> > , mpl::pair<mpl::int_<OFTInteger64List>, MemberContainerGetterPtr<GIntBig, &OGRFeature::GetFieldAsInteger64List> > - #endif > FieldGetters_Map; /**\ingroup GeometryInternals @@ -360,10 +357,8 @@ typedef mpl::map , mpl::pair<mpl::int_<OFTRealList>, MemberContainerSetterPtr<double, &OGRFeature::SetField> > , mpl::pair<mpl::int_<OFTString>, MemberSetterPtr<char const*, &OGRFeature::SetField/*, std::string*/> > , mpl::pair<mpl::int_<OFTStringList>, StringListMemberSetterPtr<std::vector<std::string> > > - #ifdef OTB_USE_GDAL_20 , mpl::pair<mpl::int_<OFTInteger64>, MemberSetterPtr<GIntBig, &OGRFeature::SetField> > , mpl::pair<mpl::int_<OFTInteger64List>, MemberContainerSetterPtr<const GIntBig, &OGRFeature::SetField> > - #endif > FieldSetters_Map; /**\ingroup GeometryInternals diff --git a/Modules/Adapters/GdalAdapters/include/otbOGRHelpers.h b/Modules/Adapters/GdalAdapters/include/otbOGRHelpers.h index e693c942805efa8abfaed49e6cf12c77240e86a2..c490e9ce62204b80440594294c129ccaf5a9691b 100644 --- a/Modules/Adapters/GdalAdapters/include/otbOGRHelpers.h +++ b/Modules/Adapters/GdalAdapters/include/otbOGRHelpers.h @@ -27,6 +27,7 @@ #include <cassert> #include <boost/range/begin.hpp> #include <boost/range/end.hpp> +#include "ogr_feature.h" #if defined(__GNUC__) || defined(__clang__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-local-typedefs" @@ -43,6 +44,8 @@ #include "OTBGdalAdaptersExport.h" +class GDALDataset; + namespace otb { namespace ogr @@ -105,6 +108,35 @@ private: std::vector<char const*> m_raw; }; +/** + * Return the list of available drivers. + * + * \return A vector of string containing the list of available drivers. +*/ +OTBGdalAdapters_EXPORT +std::vector<std::string> GetAvailableDriversAsStringVector(); + +/** + * Return the list of files composing the dataset. + * + * \param dataset Pointer to the dataset to get the file list from. Will not be + * checked for null pointer. + * + * \return A vector of string containing the list of files. +*/ + +OTBGdalAdapters_EXPORT +std::vector<std::string> GetFileListAsStringVector(GDALDataset * dataset); + +/** + * Returns true if the field 'index' is set and not-null in the given feature + * + * Before gdal 2.2, it calls OGRFeature::IsFieldSet(). + * After gdal 2.2, it calls OGRFeature::IsFieldSetAndNotNull() +*/ +OTBGdalAdapters_EXPORT +bool IsFieldSetAndNotNull(OGRFeature *feat, int index); + } // ogr namespace } // end namespace otb diff --git a/Modules/Adapters/GdalAdapters/include/otbOGRLayerWrapper.h b/Modules/Adapters/GdalAdapters/include/otbOGRLayerWrapper.h index 880832a3dace41a2eb827857479fa9c23517d1da..7cce53313186f56794aef3ccec545542dbba5722 100644 --- a/Modules/Adapters/GdalAdapters/include/otbOGRLayerWrapper.h +++ b/Modules/Adapters/GdalAdapters/include/otbOGRLayerWrapper.h @@ -36,7 +36,6 @@ #endif // #include "itkIndent.h", included from field #include "otbOGRFeatureWrapper.h" -#include "otbOGRVersionProxy.h" #include <string> // #include "ogr_core.h" // OGRwkbGeometryType, included from feature -> field @@ -119,7 +118,7 @@ public: * OGRDataSource::ExecuteSQL(). It's actually the constructor called by \c * DataSource::ExecuteSQL(). */ - Layer(OGRLayer* layer, otb::ogr::version_proxy::GDALDatasetType& sourceInChargeOfLifeTime, bool modifiable); + Layer(OGRLayer* layer, GDALDataset& sourceInChargeOfLifeTime, bool modifiable); //@} /**\name Features collection */ diff --git a/Modules/Adapters/GdalAdapters/include/otbOGRVersionProxy.h b/Modules/Adapters/GdalAdapters/include/otbOGRVersionProxy.h deleted file mode 100644 index 7cae3f6dba4cf94203bfcb7e3cd52f431a5309c9..0000000000000000000000000000000000000000 --- a/Modules/Adapters/GdalAdapters/include/otbOGRVersionProxy.h +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES) - * - * This file is part of Orfeo Toolbox - * - * https://www.orfeo-toolbox.org/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef otbOGRVersionProxy_h -#define otbOGRVersionProxy_h - -#include <string> -#include <vector> -#include "otbConfigure.h" -#include "itkMacro.h" - -#if defined(_MSC_VER) -#pragma warning ( push ) -#pragma warning ( disable: 4251 ) -#include "ogr_core.h" // OGR enums -#pragma warning ( pop ) -#else -#include "ogr_core.h" // OGR enums -#endif - - -#ifdef OTB_USE_GDAL_20 -class GDALDataset; -class GDALDriver; -#else -class OGRDataSource; -class OGRSFDriver; -#endif - -class OGRFeature; - -#include "OTBGdalAdaptersExport.h" - -namespace otb -{ -namespace ogr -{ -namespace version_proxy -{ - -/** -* With Gdal >= 2.0, this function will test equality between type and -* OFTInteger64 enum. Otherwise, it returns false. -*/ -OTBGdalAdapters_EXPORT bool IsOFTInteger64(OGRFieldType type); - -/** - * This namespace holds proxy functions hiding interface changes in gdal 2.0 - * - * This namespace holds proxy functions hiding interface changes in OGR - * dataset between gdal 1.x (x>10) and gdal 2.x. It defines a common - * interface that should be used in place of calling directly the - * wrapped gdal functions. - * - * Whenever GDALDataset and GDALDriver have to be used to open a - * vector dataset (or OGRDataSource an OGRSFDriver for gdal 1.x), one - * should use ogr::version_proxy types GDALDatasetType and - * GDALDriverType. - * - * See function documentation for details. - */ - - #ifdef OTB_USE_GDAL_20 - typedef GDALDataset GDALDatasetType; - typedef GDALDriver GDALDriverType; - #else - typedef OGRDataSource GDALDatasetType; - typedef OGRSFDriver GDALDriverType; -#endif - - /** - * This function opens a file, possibly in read-only mode, and returns - * a dataset. - * - * Calls OGRSFDriverRegistrar::Open for gdal 1.x implementation and GDALopenEx for - * gdal 2.x implementation. - - * \param filename Filename of the file to open - * \param readOnly: If true, dataset is open in read-only mode. - * \return NULL if file could not be open. - */ - OTBGdalAdapters_EXPORT - GDALDatasetType * Open(const char * filename, bool readOnly = true , std::vector< std::string > const & options = std::vector< std::string >() ); - - /** - * This function closes a dataset. - * - * Calls OGRDataSource::DestroyDataSource for gdal 1.x - * implementation and GDALClose for gdal 2.x implementation. - * - * \param dataset Pointer to the dataset to close. Will not be - * checked for null pointer. - */ - OTBGdalAdapters_EXPORT - void Close(GDALDatasetType * dataset); - - /** - * This function creates a new dataset. - * - * Calls OGRSFDriver::CreateDataSource for gdal 1.x implementation - * and GDALDriver::Create with (0,0) raster size for gdal 2.x - * implementation - * - * \param driver Pointer to the driver used for creation. Will not - * be checked for null pointer. - * - * \param name Name of the dataset to create. - * - * \return NULL if dataset could not be created. - */ - OTBGdalAdapters_EXPORT - GDALDatasetType * Create(GDALDriverType * driver, const char * name , std::vector< std::string > const & options = std::vector< std::string >() ); - - - /** - * This function physically deletes an existing dataset. - * - * Calls OGRDataSource::DeleteDataSource for gdal 1.x implementation - * and GDALDriver::Delete for gdal 2.x implementation. - * - * \param name Name of the dataset to destroy. - */ - OTBGdalAdapters_EXPORT - bool Delete(const char * name); - - /** - * This function returns a pointer to the driver from its name. - * - * Calls OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName() for - * gdal 1.x implementation and - * GetGDALDriverManager()->GetDriverByName() for gdal 2.x - * implementation. - * - * \param name Name of the driver to retrieve - * - * \return NULL if no driver could be retrieved. - */ - OTBGdalAdapters_EXPORT - GDALDriverType * GetDriverByName(const char * name); - - OTBGdalAdapters_EXPORT - std::string GetDriverNameFromDataSource(const GDALDatasetType * ds); - - /** - * Sync dataset to disk. - * - * Calls OGRDataSource::SyncToDisk() for gdal 1.x implementation and - * GDALDataset::FlushCache() for gdal 2.x implementation. - * - * \param dataset Pointer to the dataset to sync. Will not be - * checked for null pointer. - * - * \return True if sync went on without any error. - */ - OTBGdalAdapters_EXPORT - bool SyncToDisk(GDALDatasetType * dataset); - - /** - * \return The name of the dataset class behind the implementation - * (OGRDataSource for gdal 1.x and GdalDataset for gdal 2.x) - */ - OTBGdalAdapters_EXPORT - std::string GetDatasetClassName(); - - /** - * \return The name of the driver class behind the implementation - * (OGRSFDriver for gdal 1.x and GDALDriver for gdal 2.x) - */ - OTBGdalAdapters_EXPORT - std::string GetDriverClassName(); - - /** - * Return the list of files composing the dataset. - * - * Calls OGRDataSource::GetName() and wrap in string vector for gdal - * 1.x implementation, and GDALDataset::GetFileList and wrap in - * string vector for gdal 2.x implementation. - * - * \param dataset Pointer to the dataset to get the file list from. Will not be - * checked for null pointer. - * - * \return A vector of string containing the list of files. - */ - - OTBGdalAdapters_EXPORT - std::vector<std::string> GetFileListAsStringVector(GDALDatasetType * dataset); - - /** - * Return the list of available drivers. - * - * Calls OGRSFDriverRegistrar::GetRegistrar() for gdal 1.x - * implementation and GetGDALDriverManager() for gdal 2.x - * implementation. - * - * \return A vector of string containing the list of available drivers. - */ - OTBGdalAdapters_EXPORT - std::vector<std::string> GetAvailableDriversAsStringVector(); - - /** - * Returns true if the field 'index' is set and not-null in the given feature - * - * Before gdal 2.2, it calls OGRFeature::IsFieldSet(). - * After gdal 2.2, it calls OGRFeature::IsFieldSetAndNotNull() - */ - OTBGdalAdapters_EXPORT - bool IsFieldSetAndNotNull(OGRFeature *feat, int index); - -} -} -} // end namespace otb - -#endif diff --git a/Modules/Adapters/GdalAdapters/src/CMakeLists.txt b/Modules/Adapters/GdalAdapters/src/CMakeLists.txt index 0f73c07a03e044b6c89d6a19b5df6fc6b9ae4851..b5d09907dbcbf31712526d4547566d76496c2595 100644 --- a/Modules/Adapters/GdalAdapters/src/CMakeLists.txt +++ b/Modules/Adapters/GdalAdapters/src/CMakeLists.txt @@ -28,8 +28,8 @@ set(OTBGdalAdapters_SRC otbOGRDriversInit.cxx otbGeometriesToGeometriesFilter.cxx otbOGRDataSourceWrapper.cxx - otbOGRVersionProxy.cxx otbOGRExtendedFilenameToOptions.cxx + otbOGRHelpers.cxx ) add_library(OTBGdalAdapters ${OTBGdalAdapters_SRC}) diff --git a/Modules/Adapters/GdalAdapters/src/otbOGRDataSourceWrapper.cxx b/Modules/Adapters/GdalAdapters/src/otbOGRDataSourceWrapper.cxx index ea65a5c2c577a97ed2f967418816ac2b1a17a6d0..d60378e47920a41d5ffa567902fb3d06e7e7c6e0 100644 --- a/Modules/Adapters/GdalAdapters/src/otbOGRDataSourceWrapper.cxx +++ b/Modules/Adapters/GdalAdapters/src/otbOGRDataSourceWrapper.cxx @@ -48,13 +48,13 @@ bool otb::ogr::DataSource::Clear() return true; } -void otb::ogr::DataSource::Reset(otb::ogr::version_proxy::GDALDatasetType * source) +void otb::ogr::DataSource::Reset(GDALDataset * source) { if (m_DataSource) { // OGR makes a pointless check for non-nullity in // GDALDataset::DestroyDataSource (pointless because "delete 0" is // perfectly valid -> it's a no-op) - ogr::version_proxy::Close(m_DataSource); // void, noexcept + GDALClose(m_DataSource); // void, noexcept } m_DataSource = source; } @@ -108,7 +108,7 @@ char const* DeduceDriverName(std::string filename) ExtensionDriverAssociation const* whichIt = std::find_if( boost::begin(k_ExtensionDriverMap), boost::end(k_ExtensionDriverMap), - boost::bind(&ExtensionDriverAssociation::Matches, _1, extension)); + [&](auto const & x) { return x.Matches(extension); } ); if (whichIt == boost::end(k_ExtensionDriverMap)) { return nullptr; // nothing found @@ -126,10 +126,16 @@ otb::ogr::DataSource::DataSource() { Drivers::Init(); - ogr::version_proxy::GDALDriverType * d = - ogr::version_proxy::GetDriverByName("Memory"); + GDALDriver * d = + GetGDALDriverManager()->GetDriverByName("Memory"); assert(d && "OGR Memory driver not found"); - m_DataSource = ogr::version_proxy::Create(d,"in-memory"); + m_DataSource = d->Create( "in-memory" , + 0 , + 0 , + 0 , + GDT_Unknown , + 0 ); + if (!m_DataSource) { itkExceptionMacro(<< "Failed to create OGRMemDataSource: " << CPLGetLastErrorMsg()); @@ -137,7 +143,7 @@ otb::ogr::DataSource::DataSource() } otb::ogr::DataSource::DataSource( - otb::ogr::version_proxy::GDALDatasetType * source , + GDALDataset * source , Modes::type mode , const std::vector< std::string > & options /*NULL*/ ) : m_DataSource(source) , @@ -155,10 +161,12 @@ otb::ogr::DataSource::Pointer otb::ogr::DataSource::OpenDataSource(std::string c std::string simpleFileName = fileNameHelper->GetSimpleFileName(); bool update = (mode != Modes::Read); - ogr::version_proxy::GDALDatasetType * source = - ogr::version_proxy::Open( simpleFileName.c_str() , - !update , - fileNameHelper->GetGDALOpenOptions() ); + GDALDataset * source = (GDALDataset *)GDALOpenEx( + simpleFileName.c_str(), + (update? GDAL_OF_UPDATE: GDAL_OF_READONLY) | GDAL_OF_VECTOR, + NULL, + otb::ogr::StringListConverter( fileNameHelper->GetGDALOpenOptions() ).to_ogr(), + NULL); if (!source) { // In read mode, this is a failure @@ -178,8 +186,8 @@ otb::ogr::DataSource::Pointer otb::ogr::DataSource::OpenDataSource(std::string c <<simpleFileName<<">."); } - ogr::version_proxy::GDALDriverType * d = - ogr::version_proxy::GetDriverByName( driverName ); + GDALDriver * d = + GetGDALDriverManager()->GetDriverByName( driverName ); if(!d) { @@ -187,10 +195,13 @@ otb::ogr::DataSource::Pointer otb::ogr::DataSource::OpenDataSource(std::string c << ", check your OGR configuration for available drivers." ); } - source = ogr::version_proxy::Create( - d , - simpleFileName.c_str() , - fileNameHelper->GetGDALCreationOptions() ); + source = d->Create( simpleFileName.c_str() , + 0 , + 0 , + 0 , + GDT_Unknown , + otb::ogr::StringListConverter( + fileNameHelper->GetGDALCreationOptions() ).to_ogr() ); if (!source) { itkGenericExceptionMacro(<< "Failed to create GDALDataset <" << simpleFileName << "> (driver name: <" << driverName @@ -207,12 +218,40 @@ void DeleteDataSource(std::string const& datasourceName) fileNameHelper->SetExtendedFileName( datasourceName.c_str() ); std::string simpleFileName = fileNameHelper->GetSimpleFileName(); - bool ret = otb::ogr::version_proxy::Delete(simpleFileName.c_str()); - if (!ret) + // Open dataset + GDALDataset * poDS = (GDALDataset *)GDALOpenEx( + simpleFileName.c_str(), + GDAL_OF_UPDATE | GDAL_OF_VECTOR, + NULL, + NULL, + NULL); + + GDALDriver * poDriver = NULL; + if(poDS) { - itkGenericExceptionMacro(<< "Deletion of data source " << simpleFileName + poDriver = poDS->GetDriver(); + GDALClose(poDS); + } + else + { + itkGenericExceptionMacro(<< "Cannot open data source " << simpleFileName + << ": " << CPLGetLastErrorMsg()); + } + if(poDriver) + { + OGRErr ret = poDriver->Delete(simpleFileName.c_str()); + if (ret != OGRERR_NONE) + { + itkGenericExceptionMacro(<< "Deletion of data source " << simpleFileName << " failed: " << CPLGetLastErrorMsg()); + } } + else + { + itkGenericExceptionMacro(<< "Cannot get driver associated with data source " << simpleFileName + << ": " << CPLGetLastErrorMsg()); + } + } otb::ogr::DataSource::Pointer @@ -228,12 +267,15 @@ otb::ogr::DataSource::New(std::string const& datasourceName, Modes::type mode) } Drivers::Init(); - ogr::version_proxy::GDALDatasetType * ds = - ogr::version_proxy::Open( simpleFileName.c_str() , true ); - + GDALDataset * ds = (GDALDataset *)GDALOpenEx( + simpleFileName.c_str(), + GDAL_OF_READONLY | GDAL_OF_VECTOR, + NULL, + NULL, + NULL); bool ds_exists = (ds!=nullptr); - ogr::version_proxy::Close(ds); + GDALClose(ds); if (ds_exists && mode == Modes::Overwrite) @@ -246,7 +288,7 @@ otb::ogr::DataSource::New(std::string const& datasourceName, Modes::type mode) /*static*/ otb::ogr::DataSource::Pointer -otb::ogr::DataSource::New(otb::ogr::version_proxy::GDALDatasetType * source , Modes::type mode , const std::vector< std::string > & layerOptions ) +otb::ogr::DataSource::New(GDALDataset * source , Modes::type mode , const std::vector< std::string > & layerOptions ) { Pointer res = new DataSource( source , mode , layerOptions ); res->UnRegister(); @@ -727,12 +769,7 @@ OGREnvelope otb::ogr::DataSource::GetGlobalExtent(bool force/* = false */, std:: cExtent.MaxX = real_maxx; cExtent.MaxY = real_maxy; -#if GDAL_VERSION_NUM >= 1700 OGRCoordinateTransformation::DestroyCT(coordTransformation); -#else -#warning the following resource release may crash, please update your version of GDAL - delete coordTransformation; // note there is no garanty -#endif } // else: If srs are invalid, we assume that extent are coherent @@ -785,20 +822,14 @@ bool otb::ogr::DataSource::HasCapability(std::string const& capabilityName) cons void otb::ogr::DataSource::SyncToDisk() { assert(m_DataSource && "Datasource not initialized"); - bool ret = otb::ogr::version_proxy::SyncToDisk(m_DataSource); - - if(!ret) - { - itkExceptionMacro( << "Cannot flush the pending of the OGRDataSource <" - << GetDatasetDescription() << ">: " << CPLGetLastErrorMsg()); - } + m_DataSource->FlushCache(); } std::string otb::ogr::DataSource::GetDatasetDescription() const { std::vector<std::string> files = - otb::ogr::version_proxy::GetFileListAsStringVector( m_DataSource ); + otb::ogr::GetFileListAsStringVector( m_DataSource ); std::string description = ""; for( std::vector<std::string>::const_iterator it = files.begin() ; it!=files.end() ; ++it ) diff --git a/Modules/Adapters/GdalAdapters/src/otbOGRFeatureWrapper.cxx b/Modules/Adapters/GdalAdapters/src/otbOGRFeatureWrapper.cxx index 8c4abc16a33d819ed4c700221fd8007972eb887e..20cb96ce876236d6b1384daf42a7b9659ddd7c47 100644 --- a/Modules/Adapters/GdalAdapters/src/otbOGRFeatureWrapper.cxx +++ b/Modules/Adapters/GdalAdapters/src/otbOGRFeatureWrapper.cxx @@ -43,7 +43,7 @@ otb::ogr::Feature::Feature(OGRFeatureDefn & definition) : m_Feature( OGRFeature::CreateFeature(&definition), - boost::bind(&OGRFeature::DestroyFeature, _1)) + [&](auto const & x) {return OGRFeature::DestroyFeature(x);}) { CheckInvariants(); } @@ -52,7 +52,7 @@ otb::ogr::Feature::Feature(OGRFeature * feature) { if (feature) { - m_Feature.reset(feature, boost::bind(&OGRFeature::DestroyFeature, _1)); + m_Feature.reset(feature, [&](auto const & x) {return OGRFeature::DestroyFeature(x);}); } // else default is perfect -> delete null } @@ -78,16 +78,11 @@ void otb::ogr::Feature::UncheckedSetFrom(Feature const& rhs, bool mustForgive) void otb::ogr::Feature::UncheckedSetFrom(Feature const& rhs, int * map, bool mustForgive) { -#if GDAL_VERSION_NUM >= 1900 const OGRErr res = m_Feature->SetFrom(&rhs.ogr(), map, mustForgive); if (res != OGRERR_NONE) { itkGenericExceptionMacro(<<"Cannot assign from another feature: " << CPLGetLastErrorMsg()); } -#else - itkGenericExceptionMacro("OGRLayer::SetFrom(feature, fieldmap, forgive) is not supported by OGR v" - << GDAL_VERSION_NUM << ". Upgrade to a version >= 1.9.0, and recompile OTB.") -#endif } /*===========================================================================*/ diff --git a/Modules/Adapters/GdalAdapters/src/otbOGRFieldWrapper.cxx b/Modules/Adapters/GdalAdapters/src/otbOGRFieldWrapper.cxx index 49f95f053546c6f59190ef88ae6d28cee0f19110..7bf292e9015bb3de1c4d51f109840300014a0acc 100644 --- a/Modules/Adapters/GdalAdapters/src/otbOGRFieldWrapper.cxx +++ b/Modules/Adapters/GdalAdapters/src/otbOGRFieldWrapper.cxx @@ -37,7 +37,6 @@ #endif #include "otbOGRFeatureWrapper.h" #include "otbJoinContainer.h" -#include "otbOGRVersionProxy.h" #include <boost/array.hpp> /*===========================================================================*/ /*===========================[ Static Assertions ]===========================*/ @@ -167,7 +166,7 @@ std::ostream & otb::ogr::Field::UncheckedPrintSelf( bool otb::ogr::Field::UncheckedHasBeenSet() const { - return otb::ogr::version_proxy::IsFieldSetAndNotNull(m_Feature.get(), m_index); + return otb::ogr::IsFieldSetAndNotNull(m_Feature.get(), m_index); } void otb::ogr::Field::UncheckedUnset() const diff --git a/Modules/Adapters/GdalAdapters/src/otbOGRGeometryWrapper.cxx b/Modules/Adapters/GdalAdapters/src/otbOGRGeometryWrapper.cxx index 740aaa766a3f496fde86fc59d33a780d089494a9..ad03e5a2be515641a45ee6c0e1c247d55bebd8e8 100644 --- a/Modules/Adapters/GdalAdapters/src/otbOGRGeometryWrapper.cxx +++ b/Modules/Adapters/GdalAdapters/src/otbOGRGeometryWrapper.cxx @@ -25,10 +25,6 @@ #include "otbOGRGeometryWrapper.h" #include "ogr_geometry.h" -#if GDAL_VERSION_NUM < 1900 -# include "itkMacro.h" -#endif - #ifdef _MSC_VER // warning conversion int -> bool #pragma warning ( disable : 4800 ) @@ -105,12 +101,7 @@ otb::ogr::UniqueGeometryPtr otb::ogr::Union(OGRGeometry const& lhs, OGRGeometry otb::ogr::UniqueGeometryPtr otb::ogr::UnionCascaded(OGRGeometry const& this_) { -#if GDAL_VERSION_NUM >= 1800 return UniqueGeometryPtr(this_.UnionCascaded()); -#else - itkGenericExceptionMacro("OGRGeometry::UnionCascaded is not supported by OGR v" - << GDAL_VERSION_NUM << ". Upgrade to a version >= 1.8.0, and recompile OTB."); -#endif } otb::ogr::UniqueGeometryPtr otb::ogr::Difference(OGRGeometry const& lhs, OGRGeometry const& rhs) @@ -120,41 +111,20 @@ otb::ogr::UniqueGeometryPtr otb::ogr::Difference(OGRGeometry const& lhs, OGRGeom otb::ogr::UniqueGeometryPtr otb::ogr::SymDifference(OGRGeometry const& lhs, OGRGeometry const& rhs) { -#if GDAL_VERSION_NUM >= 1800 return UniqueGeometryPtr(lhs.SymDifference(&rhs)); -#else - return UniqueGeometryPtr(lhs.SymmetricDifference(&rhs)); -#endif } otb::ogr::UniqueGeometryPtr otb::ogr::SimplifyDontPreserveTopology(OGRGeometry const& g, double tolerance) { -#if GDAL_VERSION_NUM >= 1800 return UniqueGeometryPtr(g.Simplify(tolerance)); -#else - itkGenericExceptionMacro("OGRGeometry::Simplify is not supported by OGR v" - << GDAL_VERSION_NUM << ". Upgrade to a version >= 1.8.0, and recompile OTB."); -#endif } otb::ogr::UniqueGeometryPtr otb::ogr::SimplifyPreserveTopology(OGRGeometry const& g, double tolerance) { -#if GDAL_VERSION_NUM >= 1900 return UniqueGeometryPtr(g.SimplifyPreserveTopology(tolerance)); -#else - itkGenericExceptionMacro("OGRGeometry::Simplify is not supported by OGR v" - << GDAL_VERSION_NUM << ". Upgrade to a version >= 1.9.0, and recompile OTB."); -#endif } otb::ogr::UniqueGeometryPtr otb::ogr::Simplify(OGRGeometry const& g, double tolerance) { -#if GDAL_VERSION_NUM >= 1900 return UniqueGeometryPtr(g.SimplifyPreserveTopology(tolerance)); -#elif GDAL_VERSION_NUM >= 1800 - return UniqueGeometryPtr(g.Simplify(tolerance)); -#else - itkGenericExceptionMacro("OGRGeometry::Simplify(PreserveTopology) is not supported by OGR v" - << GDAL_VERSION_NUM << ". Upgrade to a version >= 1.9.0, and recompile OTB."); -#endif } diff --git a/Modules/Adapters/GdalAdapters/src/otbOGRHelpers.cxx b/Modules/Adapters/GdalAdapters/src/otbOGRHelpers.cxx new file mode 100644 index 0000000000000000000000000000000000000000..8bb2e064520c19b355cf76f6f4d787b0ff5e8031 --- /dev/null +++ b/Modules/Adapters/GdalAdapters/src/otbOGRHelpers.cxx @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES) + * + * This file is part of Orfeo Toolbox + * + * https://www.orfeo-toolbox.org/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "otbOGRHelpers.h" + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wshadow" +#include "gdal_priv.h" +#include "ogr_feature.h" +#pragma GCC diagnostic pop +#else +#include "gdal_priv.h" +#include "ogr_feature.h" +#endif // __GNUC__ || __clang__ + +namespace otb +{ +namespace ogr +{ + +std::vector<std::string> GetAvailableDriversAsStringVector() +{ + std::vector<std::string> ret; + + int nbDrivers = GetGDALDriverManager()->GetDriverCount(); + + for(int i = 0; i < nbDrivers;++i) + { + ret.push_back(GDALGetDriverShortName(GetGDALDriverManager()->GetDriver(i))); + } + return ret; +} + +namespace raii +{ +// This class is used in the next function, so as to prevent any +// resource leak on char ** returned by dataset->GetFileList() +class CharPPCapsule +{ +public: + CharPPCapsule(char ** in) + : m_P(in) + {} + + const char ** P() const + { + return const_cast<const char **>(m_P); + } + + ~CharPPCapsule() + { + if(m_P) + CSLDestroy(m_P); + } + +private: + char ** m_P; +}; +} + +std::vector<std::string> GetFileListAsStringVector(GDALDataset * dataset) +{ + std::vector<std::string> ret; + raii::CharPPCapsule capsule(dataset->GetFileList()); + std::string files_str=""; + + if(capsule.P()) + { + unsigned int i = 0; + while(capsule.P()[i]!=NULL) + { + ret.push_back(std::string(capsule.P()[i])); + ++i; + } + } + return ret; +} + +/*----------------------[GDAL 2.2 change on IsFieldSet()]---------------------*/ +bool IsFieldSetAndNotNull(OGRFeature *feat, int index) +{ +#if GDAL_VERSION_NUM<2020000 + return feat->IsFieldSet(index); +#else + return feat->IsFieldSetAndNotNull(index); +#endif +} + +} +} // end namespaces \ No newline at end of file diff --git a/Modules/Adapters/GdalAdapters/src/otbOGRLayerWrapper.cxx b/Modules/Adapters/GdalAdapters/src/otbOGRLayerWrapper.cxx index 4a9596a021a1fc4eb876508084a13a77e2a3722b..ff0d528171aceda6bb2164576e62ab7316d0437e 100644 --- a/Modules/Adapters/GdalAdapters/src/otbOGRLayerWrapper.cxx +++ b/Modules/Adapters/GdalAdapters/src/otbOGRLayerWrapper.cxx @@ -69,8 +69,8 @@ otb::ogr::Layer::Layer(OGRLayer* layer, bool modifiable) { } -otb::ogr::Layer::Layer(OGRLayer* layer, otb::ogr::version_proxy::GDALDatasetType& sourceInChargeOfLifeTime, bool modifiable) -: m_Layer(layer, boost::bind(&otb::ogr::version_proxy::GDALDatasetType::ReleaseResultSet, boost::ref(sourceInChargeOfLifeTime), _1)) +otb::ogr::Layer::Layer(OGRLayer* layer, GDALDataset& sourceInChargeOfLifeTime, bool modifiable) +: m_Layer(layer, [&](auto const& x) { return sourceInChargeOfLifeTime.ReleaseResultSet(x); }) , m_Modifiable(modifiable) { assert(layer && "A null OGRlayer cannot belong to an OGRDataSource" ); @@ -192,11 +192,7 @@ void otb::ogr::Layer::SetFeature(Feature feature) std::string otb::ogr::Layer::GetName() const { assert(m_Layer && "null layer"); -#if GDAL_VERSION_NUM >= 1800 return m_Layer->GetName(); -#else - return GetLayerDefn().GetName(); -#endif } OGREnvelope otb::ogr::Layer::GetExtent(bool force/* = false */) const @@ -339,17 +335,12 @@ void otb::ogr::Layer::DeleteField(int fieldIndex) <<GetName()<<">: layer is not modifiable"); } -#if GDAL_VERSION_NUM < 1900 - itkGenericExceptionMacro("OGRLayer::DeleteField is not supported by OGR v" - << GDAL_VERSION_NUM << ". Upgrade to a version >= 1.9.0, and recompile OTB.") -#else const OGRErr res = m_Layer->DeleteField(fieldIndex); if (res != OGRERR_NONE) { itkGenericExceptionMacro(<< "Cannot delete the "<<fieldIndex << "th field in the layer <" <<GetName() <<">: " << CPLGetLastErrorMsg()); } -#endif } void otb::ogr::Layer::AlterFieldDefn( @@ -363,10 +354,6 @@ void otb::ogr::Layer::AlterFieldDefn( <<GetName()<<">: layer is not modifiable"); } -#if GDAL_VERSION_NUM < 1900 - itkGenericExceptionMacro("OGRLayer::AlterFieldDefn is not supported by OGR v" - << GDAL_VERSION_NUM << ". Upgrade to a version >= 1.9.0, and recompile OTB.") -#else const OGRErr res = m_Layer->AlterFieldDefn( int(fieldIndex), &newFieldDefn.ogr(), @@ -376,7 +363,6 @@ void otb::ogr::Layer::AlterFieldDefn( itkGenericExceptionMacro(<< "Cannot alter the "<<fieldIndex << "th field in the layer <" <<GetName() <<">: " << CPLGetLastErrorMsg()); } -#endif } void otb::ogr::Layer::ReorderField(size_t oldPos, size_t newPos) @@ -389,17 +375,12 @@ void otb::ogr::Layer::ReorderField(size_t oldPos, size_t newPos) <<GetName()<<">: layer is not modifiable"); } -#if GDAL_VERSION_NUM < 1900 - itkGenericExceptionMacro("OGRLayer::ReorderField is not supported by OGR v" - << GDAL_VERSION_NUM << ". Upgrade to a version >= 1.9.0, and recompile OTB.") -#else const OGRErr res = m_Layer->ReorderField(int(oldPos), int(newPos)); if (res != OGRERR_NONE) { itkGenericExceptionMacro(<< "Cannot move the "<<oldPos << "th field to the " << newPos << "th position in the layer <" <<GetName() <<">: " << CPLGetLastErrorMsg()); } -#endif } void otb::ogr::Layer::ReorderFields(int * map) @@ -412,42 +393,28 @@ void otb::ogr::Layer::ReorderFields(int * map) <<GetName()<<">: layer is not modifiable"); } -#if GDAL_VERSION_NUM < 1900 - itkGenericExceptionMacro("OGRLayer::ReorderField is not supported by OGR v" - << GDAL_VERSION_NUM << ". Upgrade to a version >= 1.9.0, and recompile OTB.") -#else const OGRErr res = m_Layer->ReorderFields(map); if (res != OGRERR_NONE) { itkGenericExceptionMacro(<< "Cannot reorder the fields of the layer <" <<GetName() <<">: " << CPLGetLastErrorMsg()); } -#endif } void otb::ogr::Layer::SetIgnoredFields(char const** fieldNames) { assert(m_Layer && "OGRLayer not initialized"); -#if GDAL_VERSION_NUM >= 1900 const OGRErr res = m_Layer->SetIgnoredFields(fieldNames); if (res != OGRERR_NONE) { itkGenericExceptionMacro(<< "Cannot set fields to ignore on the layer <" <<GetName() <<">: " << CPLGetLastErrorMsg()); } -#else - itkGenericExceptionMacro("OGRLayer::SetIgnoredFields is not supported by OGR v" - << GDAL_VERSION_NUM << ". Upgrade to a version >= 1.9.0, and recompile OTB.") -#endif } OGRwkbGeometryType otb::ogr::Layer::GetGeomType() const { assert(m_Layer && "OGRLayer not initialized"); -#if GDAL_VERSION_NUM < 1800 - return GetLayerDefn().GetGeomType(); -#else return m_Layer->GetGeomType(); -#endif } diff --git a/Modules/Adapters/GdalAdapters/src/otbOGRVersionProxy.cxx b/Modules/Adapters/GdalAdapters/src/otbOGRVersionProxy.cxx deleted file mode 100644 index b616fe752698e68c3731b5ef6bf822802468a33c..0000000000000000000000000000000000000000 --- a/Modules/Adapters/GdalAdapters/src/otbOGRVersionProxy.cxx +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES) - * - * This file is part of Orfeo Toolbox - * - * https://www.orfeo-toolbox.org/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "otbOGRVersionProxy.h" -#include "otbOGRHelpers.h" - -#include "itkMacro.h" - -#if defined(__GNUC__) || defined(__clang__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wshadow" -#if GDAL_VERSION_NUM<2000000 -#include "ogrsf_frmts.h" -#else -#include "gdal_priv.h" -#endif -#include "ogr_feature.h" -#pragma GCC diagnostic pop -#else -#if GDAL_VERSION_NUM<2000000 -#include "ogrsf_frmts.h" -#else -#include "gdal_priv.h" -#endif -#include "ogr_feature.h" -#endif // __GNUC__ || __clang__ - -namespace otb -{ -namespace ogr -{ -namespace version_proxy -{ - -/*-------------------------[GDAL v2 API change]-------------------------------*/ -OTBGdalAdapters_EXPORT bool IsOFTInteger64(OGRFieldType type) -{ -#if GDAL_VERSION_NUM<2000000 - (void)type; - return false; -#else - return type == OFTInteger64; -#endif -} - - -GDALDatasetType * Open(const char * filename, bool readOnly , std::vector< std::string > const & options ) -{ -#if GDAL_VERSION_NUM<2000000 - (void)options; - return OGRSFDriverRegistrar::Open(filename,!readOnly); -#else - return (GDALDatasetType *)GDALOpenEx( - filename, - (readOnly? GDAL_OF_READONLY : GDAL_OF_UPDATE) | GDAL_OF_VECTOR, - NULL, - otb::ogr::StringListConverter( options ).to_ogr(), - NULL); -#endif -} - -void Close(GDALDatasetType * dataset) -{ -#if GDAL_VERSION_NUM<2000000 - OGRDataSource::DestroyDataSource(dataset); -#else - GDALClose(dataset); -#endif -} - -GDALDatasetType * Create(GDALDriverType * driver, const char * name , std::vector< std::string > const & options ) -{ -#if GDAL_VERSION_NUM<2000000 - (void)options; - GDALDatasetType * ds = driver->CreateDataSource(name); - - if(ds) - ds->SetDriver(driver); - - return ds; -#else - return driver->Create( name , - 0 , - 0 , - 0 , - GDT_Unknown , - otb::ogr::StringListConverter( options ).to_ogr() ); -#endif -} - -bool Delete(const char * name) -{ - // Open dataset - GDALDatasetType * poDS = otb::ogr::version_proxy::Open(name,false); - GDALDriverType * poDriver = NULL; - if(poDS) - { - poDriver = poDS->GetDriver(); - Close(poDS); - } -#if GDAL_VERSION_NUM<2000000 - if(poDriver && poDriver->TestCapability(ODrCDeleteDataSource)) - { - OGRErr ret = poDriver->DeleteDataSource(name); - return (ret == OGRERR_NONE); - } -#else - if(poDriver) - { - OGRErr ret = poDriver->Delete(name); - return (ret == OGRERR_NONE); - } -#endif - return false; -} - -GDALDriverType * GetDriverByName(const char * name) -{ -#if GDAL_VERSION_NUM<2000000 - return OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(name); -#else - return GetGDALDriverManager()->GetDriverByName(name); -#endif -} - -std::string GetDatasetClassName() -{ -#if GDAL_VERSION_NUM<2000000 - return std::string("OGRDataSource"); -#else - return std::string("GDALDataset"); -#endif -} - -std::string GetDriverClassName() -{ -#if GDAL_VERSION_NUM<2000000 - return std::string("OGRSFDriver"); -#else - return std::string("GDALDriver"); -#endif -} - -#if GDAL_VERSION_NUM>=2000000 -namespace raii -{ -// This class is used in the next function, so as to prevent any -// resource leak on char ** returned by dataset->GetFileList() -class CharPPCapsule -{ -public: - CharPPCapsule(char ** in) - : m_P(in) - {} - - const char ** P() const - { - return const_cast<const char **>(m_P); - } - - ~CharPPCapsule() - { - if(m_P) - CSLDestroy(m_P); - } - -private: - char ** m_P; -}; -} -#endif - -std::vector<std::string> GetFileListAsStringVector(GDALDatasetType * dataset) -{ - std::vector<std::string> ret; -#if GDAL_VERSION_NUM<2000000 - ret.push_back(std::string(dataset->GetName())); -#else - raii::CharPPCapsule capsule(dataset->GetFileList()); - - std::string files_str=""; - - if(capsule.P()) - { - unsigned int i = 0; - while(capsule.P()[i]!=NULL) - { - ret.push_back(std::string(capsule.P()[i])); - ++i; - } - } -#endif - return ret; -} - -bool SyncToDisk(GDALDatasetType * dataset) -{ -#if GDAL_VERSION_NUM<2000000 - const OGRErr res= dataset->SyncToDisk(); - return (res == OGRERR_NONE); -#else - dataset->FlushCache(); - return true; -#endif -} - -std::vector<std::string> GetAvailableDriversAsStringVector() -{ - std::vector<std::string> ret; -#if GDAL_VERSION_NUM<2000000 - int nbDrivers = OGRSFDriverRegistrar::GetRegistrar()->GetDriverCount(); - - for(int i = 0; i < nbDrivers;++i) - { - ret.push_back(OGRSFDriverRegistrar::GetRegistrar()->GetDriver(i)->GetName()); - } -#else - int nbDrivers = GetGDALDriverManager()->GetDriverCount(); - - for(int i = 0; i < nbDrivers;++i) - { - ret.push_back(GDALGetDriverShortName(GetGDALDriverManager()->GetDriver(i))); - } -#endif - return ret; -} - -std::string GetDriverNameFromDataSource(const GDALDatasetType * ds) -{ -#if GDAL_VERSION_NUM<2000000 - return std::string(const_cast<GDALDatasetType *>(ds)->GetDriver()->GetName()); -#else - return std::string(const_cast<GDALDatasetType *>(ds)->GetDriverName()); -#endif -} - -/*----------------------[GDAL 2.2 change on IsFieldSet()]---------------------*/ -bool IsFieldSetAndNotNull(OGRFeature *feat, int index) -{ -#if GDAL_VERSION_NUM<2020000 - return feat->IsFieldSet(index); -#else - return feat->IsFieldSetAndNotNull(index); -#endif -} - -} -} -} // end namespace - diff --git a/Modules/Adapters/GdalAdapters/test/otbOGRDataSourceWrapperNew.cxx b/Modules/Adapters/GdalAdapters/test/otbOGRDataSourceWrapperNew.cxx index 791733d41d40d2e558831a4b04b3c18d91d4badc..4dccbdd0b96d0a43c18937b8af73785ca6595f98 100644 --- a/Modules/Adapters/GdalAdapters/test/otbOGRDataSourceWrapperNew.cxx +++ b/Modules/Adapters/GdalAdapters/test/otbOGRDataSourceWrapperNew.cxx @@ -681,7 +681,6 @@ BOOST_AUTO_TEST_CASE(Add_n_Del_Fields) BOOST_CHECK_EQUAL(defn.GetFieldDefn(6), (void*)nullptr); } -#if GDAL_VERSION_NUM >= 1900 l.DeleteField(1); BOOST_CHECK_EQUAL(defn.GetFieldCount(), 5); @@ -697,7 +696,6 @@ BOOST_AUTO_TEST_CASE(Add_n_Del_Fields) ogr::FieldDefn f4(*defn.GetFieldDefn(4)); BOOST_CHECK_EQUAL(f4, k_f5); } -#endif // todo: add reoder tests } @@ -725,9 +723,7 @@ BOOST_AUTO_TEST_CASE(Add_n_Read_Fields) // ----[ int ogr::Field f0 = g0[0]; -#if GDAL_VERSION_NUM >= 1800 BOOST_CHECK_EQUAL(f0.GetName(), k_f0.GetName()); -#endif f0.SetValue(42); BOOST_ASSERT(f0.HasBeenSet()); BOOST_CHECK_EQUAL(f0.GetValue<int>(), 42); @@ -737,9 +733,7 @@ BOOST_AUTO_TEST_CASE(Add_n_Read_Fields) // ----[ double ogr::Field f1 = g0["OFTReal"]; -#if GDAL_VERSION_NUM >= 1800 BOOST_CHECK_EQUAL(f1.GetName(), k_f1.GetName()); -#endif // f1.SetValue(42); // need to support types promotion f1.SetValue(42.0); // need to support types promotion BOOST_ASSERT(f1.HasBeenSet()); @@ -747,9 +741,7 @@ BOOST_AUTO_TEST_CASE(Add_n_Read_Fields) // ----[ string ogr::Field f2 = g0["OFTString"]; -#if GDAL_VERSION_NUM >= 1800 BOOST_CHECK_EQUAL(f2.GetName(), k_f2.GetName()); -#endif f2.SetValue(("foobar")); // need to support types promotion BOOST_ASSERT(f2.HasBeenSet()); BOOST_CHECK_EQUAL(f2.GetValue<std::string>(), "foobar"); diff --git a/Modules/Adapters/OSSIMAdapters/include/otbSarSensorModelAdapter.h b/Modules/Adapters/OSSIMAdapters/include/otbSarSensorModelAdapter.h index 3c1321e04a0de9af05693b0c78a7252be5b33303..f96615cc11cc4634991727f00fedd2c4d2533126 100644 --- a/Modules/Adapters/OSSIMAdapters/include/otbSarSensorModelAdapter.h +++ b/Modules/Adapters/OSSIMAdapters/include/otbSarSensorModelAdapter.h @@ -82,7 +82,18 @@ public: bool IsValidSensorModel() const; /** Deburst metadata if possible and return lines to keep in image file */ - bool Deburst(std::vector<std::pair<unsigned long, unsigned long> > & lines); + bool Deburst(std::vector<std::pair<unsigned long, unsigned long> > & lines, + std::pair<unsigned long,unsigned long> & samples, bool onlyValidSample=false); + + /** Burst extraction and return lines/samples to keep into image file (the required burst) */ + bool BurstExtraction(const unsigned int burst_index, std::pair<unsigned long,unsigned long> & lines, + std::pair<unsigned long,unsigned long> & samples, bool allPixels=false); + + + /** Deburst metadata if possible and prepare the burst concatenation */ + bool DeburstAndConcatenate(std::vector<std::pair<unsigned long, unsigned long> > & linesBursts, + std::vector<std::pair<unsigned long,unsigned long> > & samplesBursts); + /** Transform world point (lat,lon,hgt) to input image point (col,row) and YZ frame */ diff --git a/Modules/Adapters/OSSIMAdapters/src/otbSarSensorModelAdapter.cxx b/Modules/Adapters/OSSIMAdapters/src/otbSarSensorModelAdapter.cxx index 5e351bea4b17591fcb9a55966878836dabf46c2e..35517a83805cc9eb4f29dc8d2b629905f247d874 100644 --- a/Modules/Adapters/OSSIMAdapters/src/otbSarSensorModelAdapter.cxx +++ b/Modules/Adapters/OSSIMAdapters/src/otbSarSensorModelAdapter.cxx @@ -89,11 +89,37 @@ bool SarSensorModelAdapter::IsValidSensorModel() const return m_SensorModel.get() != nullptr; } -bool SarSensorModelAdapter::Deburst(std::vector<std::pair<unsigned long, unsigned long> > & lines) +bool SarSensorModelAdapter::Deburst(std::vector<std::pair<unsigned long, unsigned long> > & lines, + std::pair<unsigned long,unsigned long> & samples, + bool onlyValidSample) { if(m_SensorModel.get() != nullptr) { - return m_SensorModel->deburst(lines); + return m_SensorModel->deburst(lines, samples, onlyValidSample); + } + + return false; +} + +bool SarSensorModelAdapter::BurstExtraction(const unsigned int burst_index, + std::pair<unsigned long,unsigned long> & lines, + std::pair<unsigned long,unsigned long> & samples, bool allPixels) +{ + if(m_SensorModel.get()) + { + return m_SensorModel->burstExtraction(burst_index, lines, samples, allPixels); + } + + return false; +} + +bool +SarSensorModelAdapter::DeburstAndConcatenate(std::vector<std::pair<unsigned long, unsigned long> > & linesBursts, + std::vector<std::pair<unsigned long,unsigned long> >& samplesBursts) +{ + if(m_SensorModel.get()) + { + return m_SensorModel->deburstAndConcatenate(linesBursts, samplesBursts); } return false; diff --git a/Modules/Adapters/OSSIMAdapters/test/otbSarSensorModelAdapterTest.cxx b/Modules/Adapters/OSSIMAdapters/test/otbSarSensorModelAdapterTest.cxx index 6f29a60ef2f2c5d19f41e5683ecbf4faff8a7484..734c55ce3b98d9e50a4631547e24edda0783083c 100644 --- a/Modules/Adapters/OSSIMAdapters/test/otbSarSensorModelAdapterTest.cxx +++ b/Modules/Adapters/OSSIMAdapters/test/otbSarSensorModelAdapterTest.cxx @@ -43,7 +43,8 @@ int otbSarSensorModelAdapterTest(int itkNotUsed(argc), char* argv[]) } std::vector<std::pair<unsigned long, unsigned long> > lines; - success = sensorModel->Deburst(lines); + std::pair<unsigned long, unsigned long> samples; + success = sensorModel->Deburst(lines, samples); if(!success) { diff --git a/Modules/Applications/AppClassification/app/otbComputeConfusionMatrix.cxx b/Modules/Applications/AppClassification/app/otbComputeConfusionMatrix.cxx index da9a2e3c48c9d2f36d40fdca08f05bcb26dd27f5..f2a87a11617a8d47812153f7285047b133eb7094 100644 --- a/Modules/Applications/AppClassification/app/otbComputeConfusionMatrix.cxx +++ b/Modules/Applications/AppClassification/app/otbComputeConfusionMatrix.cxx @@ -204,7 +204,7 @@ private: OGRFieldType fieldType = feature.ogr().GetFieldDefnRef(iField)->GetType(); - if(fieldType == OFTString || fieldType == OFTInteger || ogr::version_proxy::IsOFTInteger64(fieldType)) + if(fieldType == OFTString || fieldType == OFTInteger || fieldType == OFTInteger64) { std::string tmpKey="ref.vector.field."+key.substr(0, end - key.begin()); AddChoice(tmpKey,item); diff --git a/Modules/Applications/AppClassification/app/otbImageClassifier.cxx b/Modules/Applications/AppClassification/app/otbImageClassifier.cxx index e05dcc1964584268ebe1b6318b907cd6188462db..49bae7fd69dcbb466437cef0c0f86c2bc1b9f4bf 100644 --- a/Modules/Applications/AppClassification/app/otbImageClassifier.cxx +++ b/Modules/Applications/AppClassification/app/otbImageClassifier.cxx @@ -64,6 +64,7 @@ public: typedef ClassificationFilterType::LabelType LabelType; typedef otb::MachineLearningModelFactory<ValueType, LabelType> MachineLearningModelFactoryType; typedef ClassificationFilterType::ConfidenceImageType ConfidenceImageType; + typedef ClassificationFilterType::ProbaImageType ProbaImageType; protected: @@ -111,6 +112,7 @@ private: SetDefaultParameterInt("nodatalabel", 0); MandatoryOff("nodatalabel"); + AddParameter(ParameterType_OutputImage, "out", "Output Image"); SetParameterDescription( "out", "Output image containing class labels"); SetDefaultOutputPixelType( "out", ImagePixelType_uint8); @@ -129,8 +131,16 @@ private: SetDefaultOutputPixelType( "confmap", ImagePixelType_double); MandatoryOff("confmap"); + AddParameter(ParameterType_OutputImage,"probamap", "Probability map"); + SetParameterDescription("probamap","Probability of each class for each pixel. This is an image having a number of bands equal to the number of classes in the model. This is only implemented for the Shark Random Forest classifier at this point."); + SetDefaultOutputPixelType("probamap",ImagePixelType_uint16); + MandatoryOff("probamap"); AddRAMParameter(); + AddParameter(ParameterType_Int, "nbclasses", "Number of classes in the model"); + SetDefaultParameterInt("nbclasses", 20); + SetParameterDescription("nbclasses","The number of classes is needed for the probamap output in order to set the number of output bands."); + // Doc example parameter settings SetDocExampleParameterValue("in", "QB_1_ortho.tif"); SetDocExampleParameterValue("imstat", "EstimateImageStatisticsQB1.xml"); @@ -173,7 +183,7 @@ private: // Classify m_ClassificationFilter = ClassificationFilterType::New(); m_ClassificationFilter->SetModel(m_Model); - + m_ClassificationFilter->SetDefaultLabel(GetParameterInt("nodatalabel")); // Normalize input image if asked @@ -208,9 +218,9 @@ private: m_ClassificationFilter->SetInputMask(inMask); } - SetParameterOutputImage<OutputImageType>("out", m_ClassificationFilter->GetOutput()); - + + // output confidence map if (IsParameterEnabled("confmap") && HasValue("confmap")) { @@ -225,6 +235,21 @@ private: this->DisableParameter("confmap"); } } + if(IsParameterEnabled("probamap") && HasValue("probamap")) + { + m_ClassificationFilter->SetUseProbaMap(true); + if(m_Model->HasProbaIndex()) + { + m_ClassificationFilter->SetNumberOfClasses(GetParameterInt("nbclasses")); + SetParameterOutputImage<ProbaImageType>("probamap",m_ClassificationFilter->GetOutputProba()); + } + else + { + otbAppLogWARNING("Probability map requested but the classifier doesn't support it!"); + this->DisableParameter("probamap"); + } + } + } ClassificationFilterType::Pointer m_ClassificationFilter; diff --git a/Modules/Applications/AppClassification/app/otbPolygonClassStatistics.cxx b/Modules/Applications/AppClassification/app/otbPolygonClassStatistics.cxx index 4dd494df258f41328bd48fa0b959a40923670fb9..2134db123a5fbff6425004aec2bb19aba0722dca 100644 --- a/Modules/Applications/AppClassification/app/otbPolygonClassStatistics.cxx +++ b/Modules/Applications/AppClassification/app/otbPolygonClassStatistics.cxx @@ -148,7 +148,7 @@ private: OGRFieldType fieldType = feature.ogr().GetFieldDefnRef(iField)->GetType(); - if(fieldType == OFTString || fieldType == OFTInteger || ogr::version_proxy::IsOFTInteger64(fieldType)) + if(fieldType == OFTString || fieldType == OFTInteger || fieldType == OFTInteger64) { std::string tmpKey="field."+key.substr(0, end - key.begin()); AddChoice(tmpKey,item); diff --git a/Modules/Applications/AppClassification/app/otbSampleAugmentation.cxx b/Modules/Applications/AppClassification/app/otbSampleAugmentation.cxx index e36e22b8b2e97f0291559ef5a1a2d6b7a2fcaafb..dd6e4b67a9fe04dab5679965cde7b6df5a42d4aa 100644 --- a/Modules/Applications/AppClassification/app/otbSampleAugmentation.cxx +++ b/Modules/Applications/AppClassification/app/otbSampleAugmentation.cxx @@ -167,7 +167,7 @@ private: OGRFieldType fieldType = feature.ogr().GetFieldDefnRef(iField)->GetType(); - if(fieldType == OFTString || fieldType == OFTInteger || ogr::version_proxy::IsOFTInteger64(fieldType)) + if(fieldType == OFTString || fieldType == OFTInteger || fieldType == OFTInteger64) { std::string tmpKey="field."+key.substr(0, end - key.begin()); AddChoice(tmpKey,item); diff --git a/Modules/Applications/AppClassification/app/otbSampleExtraction.cxx b/Modules/Applications/AppClassification/app/otbSampleExtraction.cxx index 2c48308344b02b27744c3c362a07603ceb348c47..9a0741d46cbc81ed060d9d8a06d3dad85a32a6c9 100644 --- a/Modules/Applications/AppClassification/app/otbSampleExtraction.cxx +++ b/Modules/Applications/AppClassification/app/otbSampleExtraction.cxx @@ -140,7 +140,7 @@ private: OGRFieldType fieldType = feature.ogr().GetFieldDefnRef(iField)->GetType(); - if(fieldType == OFTString || fieldType == OFTInteger || ogr::version_proxy::IsOFTInteger64(fieldType)) + if(fieldType == OFTString || fieldType == OFTInteger || fieldType == OFTInteger64) { std::string tmpKey="field."+key.substr(0, end - key.begin()); AddChoice(tmpKey,item); diff --git a/Modules/Applications/AppClassification/app/otbSampleSelection.cxx b/Modules/Applications/AppClassification/app/otbSampleSelection.cxx index 531203f01ad2bb64c651c860831728e496193bdd..823a95d70eba2ba067437e777bafe420eaefa946 100644 --- a/Modules/Applications/AppClassification/app/otbSampleSelection.cxx +++ b/Modules/Applications/AppClassification/app/otbSampleSelection.cxx @@ -248,7 +248,7 @@ private: OGRFieldType fieldType = feature.ogr().GetFieldDefnRef(iField)->GetType(); - if(fieldType == OFTString || fieldType == OFTInteger || ogr::version_proxy::IsOFTInteger64(fieldType)) + if(fieldType == OFTString || fieldType == OFTInteger || fieldType == OFTInteger64) { std::string tmpKey="field."+key.substr(0, end - key.begin()); AddChoice(tmpKey,item); diff --git a/Modules/Applications/AppClassification/app/otbVectorClassifier.cxx b/Modules/Applications/AppClassification/app/otbVectorClassifier.cxx index 286b6b0dd7d6cf89f55e9c942d73df988dbe7114..d101d983de3410bb1d347e9f03888ff30fe995dd 100644 --- a/Modules/Applications/AppClassification/app/otbVectorClassifier.cxx +++ b/Modules/Applications/AppClassification/app/otbVectorClassifier.cxx @@ -183,7 +183,7 @@ private: std::transform(key.begin(), key.end(), key.begin(), tolower); OGRFieldType fieldType = layerDefn.GetFieldDefn(iField)->GetType(); - if(fieldType == OFTInteger || ogr::version_proxy::IsOFTInteger64(fieldType) || fieldType == OFTReal) + if(fieldType == OFTInteger || fieldType == OFTInteger64 || fieldType == OFTReal) { std::string tmpKey="feat."+key; AddChoice(tmpKey,item); diff --git a/Modules/Applications/AppClassification/include/otbTrainVectorBase.hxx b/Modules/Applications/AppClassification/include/otbTrainVectorBase.hxx index 588e07ae8a51d609aedd7f9834ca10ff029c26a5..3b4fcd115491e0ffd231e0f809cc624cbea949c7 100644 --- a/Modules/Applications/AppClassification/include/otbTrainVectorBase.hxx +++ b/Modules/Applications/AppClassification/include/otbTrainVectorBase.hxx @@ -131,12 +131,12 @@ void TrainVectorBase::DoUpdateParameters() OGRFieldType fieldType = feature.ogr().GetFieldDefnRef( iField )->GetType(); - if( fieldType == OFTInteger || ogr::version_proxy::IsOFTInteger64( fieldType ) || fieldType == OFTReal ) + if( fieldType == OFTInteger || fieldType == OFTInteger64 || fieldType == OFTReal ) { std::string tmpKey = "feat." + key.substr( 0, static_cast<unsigned long>( end - key.begin() ) ); AddChoice( tmpKey, item ); } - if( fieldType == OFTString || fieldType == OFTInteger || ogr::version_proxy::IsOFTInteger64( fieldType ) ) + if( fieldType == OFTString || fieldType == OFTInteger || fieldType == OFTInteger64 ) { std::string tmpKey = "cfield." + key.substr( 0, static_cast<unsigned long>( end - key.begin() ) ); AddChoice( tmpKey, item ); diff --git a/Modules/Applications/AppClassification/test/CMakeLists.txt b/Modules/Applications/AppClassification/test/CMakeLists.txt index 46f4e82dcf3142883cd94d7508458647dd02c47a..13db483c00d9fe033a0b7b7f531abdb1df5a6fe7 100644 --- a/Modules/Applications/AppClassification/test/CMakeLists.txt +++ b/Modules/Applications/AppClassification/test/CMakeLists.txt @@ -115,6 +115,7 @@ set(sharkkm_parameters "") set(ascii_comparison --compare-ascii ${EPSILON_6}) set(raster_comparison --compare-image ${NOTOL}) set(raster_comparison_two --compare-n-images ${NOTOL} 2) +set(raster_comparison_three --compare-n-images ${NOTOL} 3) # Reference ffiles depending on modes set(ascii_ref_path ${OTBAPP_BASELINE_FILES}) @@ -136,6 +137,7 @@ if(OTB_USE_SHARK) endif() set(classifier_with_confmap "LIBSVM" "BOOST" "KNN" "ANN" "RF") +set(classifier_with_probamap "SHARKRF") # This is a black list for classifier that can not have a baseline # because they are using randomness and seed can not be set @@ -156,6 +158,7 @@ foreach(classifier ${classifierList}) set(OUTRASTER cl${classifier}LabeledImageQB1${raster_output_format}) set(OUTCONFMAP cl${classifier}ConfidenceMapQB1${raster_output_format}) + set(OUTPROBAMAP cl${classifier}ProbabilityMapQB1${raster_output_format}) list(FIND classifier_without_baseline ${classifier} _classifier_has_baseline) if(${_classifier_has_baseline} EQUAL -1) @@ -198,6 +201,7 @@ foreach(classifier ${classifierList}) set_tests_properties(apTvClTrainMethod${classifier}ImagesClassifierQB1_InXML1 PROPERTIES DEPENDS apTvClTrainMethod${classifier}ImagesClassifierQB1) list(FIND classifier_with_confmap ${classifier} _classifier_has_confmap) + list(FIND classifier_with_probamap ${classifier} _classifier_has_probamap) if(${_classifier_has_confmap} EQUAL -1) otb_test_application( NAME apTvClMethod${classifier}ImageClassifierQB1 @@ -212,21 +216,44 @@ foreach(classifier ${classifierList}) ${TEMP}/${OUTRASTER} ) else() - otb_test_application( - NAME apTvClMethod${classifier}ImageClassifierQB1 - APP ImageClassifier - OPTIONS -in ${INPUTDATA}/Classification/QB_1_ortho${raster_input_format} - -model ${INPUTDATA}/Classification/${OUTMODELFILE} - -imstat ${INPUTDATA}/Classification/clImageStatisticsQB1${stat_input_format} - -out ${TEMP}/${OUTRASTER} ${raster_output_option} - -confmap ${TEMP}/${OUTCONFMAP} - - VALID ${raster_comparison_two} - ${raster_ref_path}/${OUTRASTER} - ${TEMP}/${OUTRASTER} - ${raster_ref_path}/${OUTCONFMAP} - ${TEMP}/${OUTCONFMAP} - ) + if(${_classifier_has_probamap} EQUAL -1) + otb_test_application( + NAME apTvClMethod${classifier}ImageClassifierQB1 + APP ImageClassifier + OPTIONS -in ${INPUTDATA}/Classification/QB_1_ortho${raster_input_format} + -model ${INPUTDATA}/Classification/${OUTMODELFILE} + -imstat ${INPUTDATA}/Classification/clImageStatisticsQB1${stat_input_format} + -out ${TEMP}/${OUTRASTER} ${raster_output_option} + -confmap ${TEMP}/${OUTCONFMAP} + + VALID ${raster_comparison_two} + ${raster_ref_path}/${OUTRASTER} + ${TEMP}/${OUTRASTER} + ${raster_ref_path}/${OUTCONFMAP} + ${TEMP}/${OUTCONFMAP} + ) + else() + message(${classifier}) + otb_test_application( + NAME apTvClMethod${classifier}ImageClassifierQB1 + APP ImageClassifier + OPTIONS -in ${INPUTDATA}/Classification/QB_1_ortho${raster_input_format} + -model ${INPUTDATA}/Classification/${OUTMODELFILE} + -imstat ${INPUTDATA}/Classification/clImageStatisticsQB1${stat_input_format} + -out ${TEMP}/${OUTRASTER} ${raster_output_option} + -confmap ${TEMP}/${OUTCONFMAP} + -nbclasses 4 + -probamap ${TEMP}/${OUTPROBAMAP} + + VALID ${raster_comparison_three} + ${raster_ref_path}/${OUTRASTER} + ${TEMP}/${OUTRASTER} + ${raster_ref_path}/${OUTCONFMAP} + ${TEMP}/${OUTCONFMAP} + ${raster_ref_path}/${OUTPROBAMAP} + ${TEMP}/${OUTPROBAMAP} + ) + endif() endif() endforeach() diff --git a/Modules/Applications/AppFusion/app/otbPansharpening.cxx b/Modules/Applications/AppFusion/app/otbPansharpening.cxx index fda0827b4f9b2e1ce06b91c22de6607540572aed..8e6cf20f0cd8cf8f2325ec2c9169caaf7bdaf25f 100644 --- a/Modules/Applications/AppFusion/app/otbPansharpening.cxx +++ b/Modules/Applications/AppFusion/app/otbPansharpening.cxx @@ -53,8 +53,6 @@ public: typedef itk::SmartPointer<Self> Pointer; typedef itk::SmartPointer<const Self> ConstPointer; - typedef itk::ImageToImageFilter<FloatVectorImageType, FloatVectorImageType> FusionFilterType; - typedef otb::SimpleRcsPanSharpeningFusionImageFilter<FloatImageType, FloatVectorImageType, FloatVectorImageType> SimpleRCSFilterType; typedef otb::LmvmPanSharpeningFusionImageFilter @@ -176,7 +174,9 @@ private: filter->UpdateOutputInformation(); otbAppLogINFO( << "Simple RCS algorithm" ); - m_FusionFilter = filter; + m_Ref.push_back(filter.GetPointer()); + SetParameterOutputImage("out", filter->GetOutput()); + break; } case 1: @@ -203,8 +203,9 @@ private: filter->UpdateOutputInformation(); otbAppLogINFO( << "Lmvm algorithm" ); + m_Ref.push_back(filter.GetPointer()); + SetParameterOutputImage("out", filter->GetOutput()); - m_FusionFilter = filter; break; } case 2: @@ -224,7 +225,9 @@ private: filter->UpdateOutputInformation(); otbAppLogINFO( << "Bayesian fusion algorithm" ); - m_FusionFilter = filter; + + m_Ref.push_back(filter.GetPointer()); + SetParameterOutputImage("out", filter->GetOutput()); break; } @@ -236,12 +239,9 @@ private: } return; } - - SetParameterOutputImage("out", m_FusionFilter->GetOutput()); } std::vector<itk::ProcessObject::Pointer> m_Ref; - FusionFilterType::Pointer m_FusionFilter; }; } } diff --git a/Modules/Applications/AppMorphology/app/otbMorphologicalProfilesAnalysis.cxx b/Modules/Applications/AppMorphology/app/otbMorphologicalProfilesAnalysis.cxx index ae3c31abac736608f76fd892662613504159dfb8..6946103d3c926b7d564994f494691714575e7032 100644 --- a/Modules/Applications/AppMorphology/app/otbMorphologicalProfilesAnalysis.cxx +++ b/Modules/Applications/AppMorphology/app/otbMorphologicalProfilesAnalysis.cxx @@ -270,12 +270,13 @@ private: } classificationFilter = MultiScaleClassificationFilterType::New(); - classificationFilter->SetOpeningProfileDerivativeMaxima( omsCharFilter->GetOutput() ); - classificationFilter->SetOpeningProfileCharacteristics( omsCharFilter->GetOutputCharacteristics() ); - classificationFilter->SetClosingProfileDerivativeMaxima( cmsCharFilter->GetOutput() ); - classificationFilter->SetClosingProfileCharacteristics( cmsCharFilter->GetOutputCharacteristics() ); - classificationFilter->SetSigma( sigma ); - classificationFilter->SetLabelSeparator( static_cast<unsigned short>(initValue + profileSize * step) ); + using namespace Functor::MultiScaleConvexOrConcaveDecisionRule_tags; + classificationFilter->SetVariadicNamedInput<max_opening_profile_derivative>( omsCharFilter->GetOutput() ); + classificationFilter->SetVariadicNamedInput<opening_profile_characteristics>( omsCharFilter->GetOutputCharacteristics() ); + classificationFilter->SetVariadicNamedInput<max_closing_profile_derivative>( cmsCharFilter->GetOutput() ); + classificationFilter->SetVariadicNamedInput<closing_profile_characteristics>( cmsCharFilter->GetOutputCharacteristics() ); + classificationFilter->GetModifiableFunctor().SetSigma( sigma ); + classificationFilter->GetModifiableFunctor().SetLabelSeparator( static_cast<unsigned short>(initValue + profileSize * step) ); AddProcess(classificationFilter, "Classification"); classificationFilter->Update(); SetParameterOutputImage( "out", classificationFilter->GetOutput() ); diff --git a/Modules/Applications/AppSARCalibration/app/CMakeLists.txt b/Modules/Applications/AppSARCalibration/app/CMakeLists.txt index 4360104d2a87f0b4995f15c2a36fde004f786096..5e518e169a3da8497098a5a68716b8746f7d0312 100644 --- a/Modules/Applications/AppSARCalibration/app/CMakeLists.txt +++ b/Modules/Applications/AppSARCalibration/app/CMakeLists.txt @@ -27,3 +27,13 @@ otb_create_application( NAME SARDeburst SOURCES otbSARDeburst.cxx LINK_LIBRARIES ${${otb-module}_LIBRARIES}) + +otb_create_application( + NAME SARBurstExtraction + SOURCES otbSARBurstExtraction.cxx + LINK_LIBRARIES ${${otb-module}_LIBRARIES}) + +otb_create_application( + NAME SARConcatenateBursts + SOURCES otbSARConcatenateBursts.cxx + LINK_LIBRARIES ${${otb-module}_LIBRARIES}) diff --git a/Modules/Applications/AppSARCalibration/app/otbSARBurstExtraction.cxx b/Modules/Applications/AppSARCalibration/app/otbSARBurstExtraction.cxx new file mode 100644 index 0000000000000000000000000000000000000000..36082b796fe59fa58e353cc0ad057c2280f99fb1 --- /dev/null +++ b/Modules/Applications/AppSARCalibration/app/otbSARBurstExtraction.cxx @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES) + * + * This file is part of Orfeo Toolbox + * + * https://www.orfeo-toolbox.org/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "otbWrapperApplication.h" +#include "otbWrapperApplicationFactory.h" + +#include "otbSarBurstExtractionImageFilter.h" + +namespace otb +{ +namespace Wrapper +{ +class SARBurstExtraction : public Application +{ +public: + /** Standard class typedefs. */ + typedef SARBurstExtraction Self; + typedef Application Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; + + /** Standard macro */ + itkNewMacro(Self); + + itkTypeMacro(SARBurstExtraction, otb::Application); + + typedef otb::SarBurstExtractionImageFilter<FloatVectorImageType> BurstExtractionFilterType; + +private: + void DoInit() override + { + SetName("SARBurstExtraction"); + SetDescription("This application performs a burst extraction by keeping only lines and samples of a required burst."); + + // Documentation + SetDocName("SAR Burst Extraction"); + SetDocLongDescription("Sentinel1 IW SLC products are composed of several burst overlapping in" + " azimuth time for each subswath, separated by black lines [1]. The burst" + " extraction consist in extracting a single burst, by selecting only lines" + " and samples of the wanted burst.\n\n" + + "Note that the output sensor model is updated accordingly. This burst" + " extraction is the perfect preprocessing step for S1 IW SLC" + " product with OTB without suffering from artifacts caused by" + " bursts separation\n." + + "Two modes are available for the output image : with all pixels and" + "with only valid pixels "); + + SetDocLimitations("Only Sentinel1 IW SLC products are supported for now. Processing of" + " other Sentinel1 modes or TerrasarX images will result in no changes in" + " the image and metadata. Images from other sensors will lead to an" + " error." + " Burst extraction needs as inputs a image composed of several Bursts. A burst has to " + " contain all its lines in order to have a correct extraction. " + " ie : Careful with ROI."); + + SetDocAuthors("OTB-Team"); + SetDocSeeAlso("[1] Sentinel1 User Handbook, p. 52: https://sentinel.esa.int/documents/247904/685163/Sentinel-1_User_Handbook\n"); + + AddDocTag(Tags::SAR); + AddDocTag(Tags::Calibration); + + AddParameter(ParameterType_InputImage, "in", "Input Sentinel1 IW SLC Image"); + SetParameterDescription("in", "Raw Sentinel1 IW SLC image, or any extract of such made by OTB (geom file needed)"); + + AddParameter(ParameterType_Int, "burstindex", "Index of Burst"); + SetParameterDescription("burstindex", "Index for the required Burst (By default -1). If this parameter remains at -1, all bursts will be extracted"); + MandatoryOff("burstindex"); + SetDefaultParameterInt("burstindex", -1); + + AddParameter(ParameterType_OutputImage, "out", "Output Image"); + SetParameterDescription("out", "The output filename will be used to get the prefix " + "and the extension of thise output written's image. For example with outimage.tif as" + "output filename, the generated images will had an indice (corresponding at each " + "burst) between the prefix and the extension, such as: outimage_Burst0.tif and " + "outimage_Burst1.tif (if 2 bursts)."); + + AddParameter(ParameterType_Bool, "allpixels", "Select the modes for output image"); + SetParameterDescription("allpixels", "If true, all pixels of the current burst are selected."); + + AddRAMParameter(); + + SetDocExampleParameterValue("in","s1_iw_slc.tif"); + SetDocExampleParameterValue("out","s1_iw_slc_burst0.tif"); + + SetOfficialDocLink(); + } + + void DoUpdateParameters() override + {} + + void DoExecute() override + { + // Get the input complex image + FloatVectorImageType* in = GetParameterImage("in"); + + // Get the Burst index + int burst_index = GetParameterInt("burstindex"); // If -1 or > nb_Bursts => all bursts will be extracted + + + // Get the path/fileWithoutextension/extension of the output images filename + std::string ofname = GetParameterString("out"); + + // Get the extension and the prefix of the filename + const std::string path = itksys::SystemTools::GetFilenamePath(ofname); + const std::string fname = itksys::SystemTools::GetFilenameWithoutExtension(ofname); + const std::string ext = itksys::SystemTools::GetFilenameExtension(ofname); + + // Set the filer input + m_BurstExtractionFilter = BurstExtractionFilterType::New(); + m_BurstExtractionFilter->SetInput(in); + + if (IsParameterEnabled("allpixels")) + { + m_BurstExtractionFilter->SetAllPixels(true); + } + + // Get the number of Bursts + unsigned int nbBursts = 1; + try + { + nbBursts = std::stoi(in->GetImageKeywordlist().GetMetadataByKey("support_data.geom.bursts.number")); + } + catch( ... ) + { + // Throw an execption + otbAppLogFATAL(<<"Failed to retrieve bursts.number value from .geom file."); + } + + const bool extractAll = burst_index <= -1 || burst_index >= static_cast<int>(nbBursts); + + // Extract burst index only + if (! extractAll) + { + // Set the burst index + m_BurstExtractionFilter->SetBurstIndex(burst_index); + + SetParameterOutputImage("out", m_BurstExtractionFilter->GetOutput()); + + } + // Extract all bursts + else + { + for (unsigned int i = 0; i < nbBursts; ++i) + { + // Set the burst index + m_BurstExtractionFilter->SetBurstIndex(i); + + // Build the current output filename + std::ostringstream oss; + if (!path.empty()) + { + oss <<path<<"/"; + } + oss <<fname<<"_burst"<<i<<ext; + + // Create an output parameter to write the current output image + OutputImageParameter::Pointer paramOut = OutputImageParameter::New(); + + // Writer label + std::ostringstream osswriter; + osswriter<< "writer (Burst : "<< i<<")"; + + // Set the filename of the current output image + paramOut->SetFileName(oss.str()); + otbAppLogINFO(<< "File: "<<paramOut->GetFileName() << " will be written."); + paramOut->SetValue(m_BurstExtractionFilter->GetOutput()); + paramOut->SetPixelType(this->GetParameterOutputImagePixelType("out")); + // Add the current level to be written + paramOut->InitializeWriters(); + AddProcess(paramOut->GetWriter(), osswriter.str()); + paramOut->Write(); + } + + // Disable the output Image parameter to avoid writing + // the last image (Application::ExecuteAndWriteOutput method) + DisableParameter("out"); + } + RegisterPipeline(); + } + + BurstExtractionFilterType::Pointer m_BurstExtractionFilter; + +}; +} +} + +OTB_APPLICATION_EXPORT(otb::Wrapper::SARBurstExtraction) diff --git a/Modules/Applications/AppSARCalibration/app/otbSARConcatenateBursts.cxx b/Modules/Applications/AppSARCalibration/app/otbSARConcatenateBursts.cxx new file mode 100644 index 0000000000000000000000000000000000000000..580311fb41493b401c76c68c7a2f8e2157a128c4 --- /dev/null +++ b/Modules/Applications/AppSARCalibration/app/otbSARConcatenateBursts.cxx @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES) + * + * This file is part of Orfeo Toolbox + * + * https://www.orfeo-toolbox.org/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "otbWrapperApplication.h" +#include "otbWrapperApplicationFactory.h" + +#include "otbMultiChannelExtractROI.h" +#include "otbImageList.h" + +#include "otbSarConcatenateBurstsImageFilter.h" + +namespace otb +{ +namespace Wrapper +{ +class SARConcatenateBursts : public Application +{ +public: + /** Standard class typedefs. */ + typedef SARConcatenateBursts Self; + typedef Application Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; + + /** Standard macro */ + itkNewMacro(Self); + + itkTypeMacro(SARConcatenateBursts, otb::Application); + + typedef otb::ImageList<FloatVectorImageType> ImageListType; + typedef MultiChannelExtractROI<FloatVectorImageType::InternalPixelType, + FloatVectorImageType::InternalPixelType> ExtractROIFilterType; + typedef ObjectList<ExtractROIFilterType> ExtractROIFilterListType; + + typedef otb::SarConcatenateBurstsImageFilter<FloatVectorImageType> BurstFusionFilterType; + +private: + void DoInit() override + { + SetName("SARConcatenateBursts"); + SetDescription("Concatenate a list of Bursts to provide a whole SAR Deburst Image."); + + // Documentation + SetDocName("SAR Concatenate Bursts"); + SetDocLongDescription("This application performs a burst concatenation and provides a SAR Deburst Image. " + "It reads the input image list (single bursts) " + "and generates a whole SAR image with deburst operations."); + SetDocLimitations("Only Sentinel1 IW SLC products are supported for now. In order to concatenate several" + " bursts, all valid lines of each burst are required as inputs." + "ie : Careful with ROI extraction inside a Burst."); + SetDocAuthors("OTB-Team"); + + AddDocTag(Tags::SAR); + AddDocTag(Tags::Calibration); + + AddParameter(ParameterType_InputImageList, "il", "Input bursts list"); + SetParameterDescription("il", "The list of bursts to concatenate."); + + AddParameter(ParameterType_InputImage, "insar", "Input Sentinel1 IW SLC Image (only metadata used)"); + SetParameterDescription("insar", "Raw Sentinel1 IW SLC image, or any extract of such made by OTB (geom file needed)."); + + AddParameter(ParameterType_OutputImage, "out", "Output Image"); + SetParameterDescription("out", "The concatenated and debursted output image."); + + AddRAMParameter(); + + // Doc example parameter settings + SetDocExampleParameterValue("in","s1_iw_slc.tif"); + SetDocExampleParameterValue("il", "Burst0.png Burst1.png"); + SetDocExampleParameterValue("out", "otbConcatenateBursts.tif"); + + SetOfficialDocLink(); + } + + void DoUpdateParameters() override + {} + + void DoExecute() override + { + // Instanciate filters + ExtractROIFilterListType::Pointer m_ExtractorList = ExtractROIFilterListType::New(); + ImageListType::Pointer m_ImageList = ImageListType::New(); + BurstFusionFilterType::Pointer fusionFilter = BurstFusionFilterType::New(); + + // Get the input complex image list + FloatVectorImageListType* inList = GetParameterImageList("il"); + // Get the input complex image + FloatVectorImageType* in = GetParameterImage("insar"); + in->UpdateOutputInformation(); + + std::vector<std::pair<unsigned long,unsigned long> > lines; + std::vector<std::pair<unsigned long,unsigned long> > samples; + + // Check number of inputs with number of bursts into SLC image (must be the same) + unsigned int nbBursts = 1; + try + { + nbBursts = std::stoi(in->GetImageKeywordlist().GetMetadataByKey("support_data.geom.bursts.number")); + } + catch( ... ) + { + // Throw an execption + throw std::runtime_error("Failed to retrieve bursts.number value from .geom file."); + } + + nbBursts = inList->Size(); + + /*if (inList->Size() != nbBursts) + { + throw std::runtime_error("Failed to concatenate bursts. Some bursts are missing."); + }*/ + + // Coniguration for fusion filter + fusionFilter->SetSLCImageKeyWorList(in->GetImageKeywordlist()); + fusionFilter->getDeburstLinesAndSamples(lines, samples); + + // Split each input burst to keep only interested region + for( unsigned int i=0; i<inList->Size(); i++ ) + { + FloatVectorImageType::Pointer vectIm = inList->GetNthElement(i); + vectIm->UpdateOutputInformation(); + + unsigned long originOffset_samples = static_cast<long>(vectIm->GetOrigin()[0]-0.5); + unsigned long originOffset_lines = static_cast<long>(vectIm->GetOrigin()[1]-0.5); + + // Retrieve start and size for each burst + std::pair<unsigned long,unsigned long> line = lines[i]; + std::pair<unsigned long,unsigned long> sample = samples[i]; + + unsigned long minSamples = std::min(sample.second, static_cast<unsigned long>(vectIm->GetLargestPossibleRegion().GetSize()[0]-1)); + unsigned long minLines = std::min(line.second, static_cast<unsigned long>(vectIm->GetLargestPossibleRegion().GetSize()[1]-1)); + + unsigned long startL = line.first - originOffset_lines; + unsigned long sizeL = minLines - line.first + 1; + unsigned long startS = sample.first - originOffset_samples; + unsigned long sizeS = minSamples - sample.first + 1; + // Readjust if origin is superior to the first selected line/sample for the current burst + if (line.first < originOffset_lines) + { + startL = 0; + sizeL = minLines - line.first - originOffset_lines + 1; + } + if (sample.first < originOffset_samples) + { + startS = 0; + sizeS = minSamples - sample.first - originOffset_samples + 1; + } + + ExtractROIFilterType::Pointer extractor = ExtractROIFilterType::New(); + extractor->SetInput(vectIm); + extractor->SetStartX(startS); + extractor->SetStartY(startL); + extractor->SetSizeX(sizeS); + extractor->SetSizeY(sizeL); + extractor->UpdateOutputInformation(); + + m_ExtractorList->PushBack( extractor ); + m_ImageList->PushBack( extractor->GetOutput() ); + + } + + BurstFusionFilterType::SizeType layout; + layout[0] = 1; + layout[1] = nbBursts; + fusionFilter->SetLayout(layout); + + for (unsigned int i=0; i<(layout[0]*layout[1]); i++) + { + fusionFilter->SetInput(i,m_ImageList->GetNthElement(i)); + } + + SetParameterOutputImage("out", fusionFilter->GetOutput()); + + RegisterPipeline(); + } + + +}; +} +} + +OTB_APPLICATION_EXPORT(otb::Wrapper::SARConcatenateBursts) diff --git a/Modules/Applications/AppSARCalibration/app/otbSARDeburst.cxx b/Modules/Applications/AppSARCalibration/app/otbSARDeburst.cxx index 0858e7e7146997530a067cb32929850e749e06f9..849f91de97313dabacb4533fcd18354c23c7e567 100644 --- a/Modules/Applications/AppSARCalibration/app/otbSARDeburst.cxx +++ b/Modules/Applications/AppSARCalibration/app/otbSARDeburst.cxx @@ -60,7 +60,10 @@ private: "Note that the output sensor model is updated accordingly. This deburst" " operation is the perfect preprocessing step to orthorectify S1 IW SLC" " product with OTB [2] without suffering from artifacts caused by" - " bursts separation."); + " bursts separation.\n" + + "Two modes are available for the output image : with all samples and" + "with only valid samples "); SetDocLimitations("Only Sentinel1 IW SLC products are supported for now. Processing of" " other Sentinel1 modes or TerrasarX images will result in no changes in" @@ -80,6 +83,9 @@ private: AddParameter(ParameterType_OutputImage, "out", "Output Image"); SetParameterDescription("out", "Deburst image, with updated geom file that can be further used by Orthorectification application. If the input image is a raw Sentinel1 product, uint16 output type should be used (encoding of S1 product). Otherwise, output type should match type of input image."); + AddParameter(ParameterType_Bool, "onlyvalidsamples", "Select the modes for output image"); + SetParameterDescription("onlyvalidsamples", "If true, the selected mode is with only valid samples."); + AddRAMParameter(); SetDocExampleParameterValue("in","s1_iw_slc.tif"); @@ -100,6 +106,12 @@ private: m_DeburstFilter = DeburstFilterType::New(); m_DeburstFilter->SetInput(in); + if (IsParameterEnabled("onlyvalidsamples")) + { + m_DeburstFilter->SetOnlyValidSample(true); + } + + // Set the output image SetParameterOutputImage("out", m_DeburstFilter->GetOutput()); } diff --git a/Modules/Applications/AppSARCalibration/test/CMakeLists.txt b/Modules/Applications/AppSARCalibration/test/CMakeLists.txt index 1ca0afb569f058654d1df161432d920c8eb66df2..eabd2ace9d092b6dea7faf1551f371b78fe67e8d 100644 --- a/Modules/Applications/AppSARCalibration/test/CMakeLists.txt +++ b/Modules/Applications/AppSARCalibration/test/CMakeLists.txt @@ -54,3 +54,23 @@ otb_test_application(NAME apTvRaSarDeburst_SENTINEL1 # Same baseline as filter test ${BASELINE}/saTvSarDeburstImageFilterTestOutput.tif ${TEMP}/apTvRaSarDeburst_SENTINEL1_output.tif) + +otb_test_application(NAME apTvRaSarBurstExtraction_SENTINEL1 + APP SARBurstExtraction + OPTIONS -in ${INPUTDATA}/s1a-iw1-slc-vv-20170111_Burst01_amp.tiff + -out ${TEMP}/apTvRaSarBurstExtraction_SENTINEL1_output.tif uint16 + -burstindex 0 + VALID --compare-image ${NOTOL} + # Same baseline as filter test + ${BASELINE}/apTvRaSarBurstExtraction_SENTINEL1_output.tif + ${TEMP}/apTvRaSarBurstExtraction_SENTINEL1_output.tif) + +otb_test_application(NAME apTvRaSarConcatenateBursts_SENTINEL1 + APP SARConcatenateBursts + OPTIONS -il ${INPUTDATA}/s1a-iw1-slc-vv-20170111_Burst0_amp.tif ${INPUTDATA}/s1a-iw1-slc-vv-20170111_Burst1_amp.tif + -insar ${INPUTDATA}/s1a-iw1-slc-vv-20170111_Burst01_amp.tiff + -out ${TEMP}/apTvRaSarConcatenateBursts_SENTINEL1_output.tif uint16 + VALID --compare-image ${NOTOL} + # Same baseline as filter test + ${BASELINE}/apTvRaSarConcatenateBursts_SENTINEL1_output.tif + ${TEMP}/apTvRaSarConcatenateBursts_SENTINEL1_output.tif) diff --git a/Modules/Applications/AppSegmentation/app/otbSegmentation.cxx b/Modules/Applications/AppSegmentation/app/otbSegmentation.cxx index cbb87ed79d6194b36da369c69a8d7f7548088026..b49467c19ba962aa1c5d97730bd75600084cbf91 100644 --- a/Modules/Applications/AppSegmentation/app/otbSegmentation.cxx +++ b/Modules/Applications/AppSegmentation/app/otbSegmentation.cxx @@ -689,7 +689,7 @@ private: //Note : the GetDriver() Method has not been encapsulated in otb::ogr::DataSource, //so we must access the OGR pointer by using .ogr() - std::string driverName(otb::ogr::version_proxy::GetDriverNameFromDataSource(&ogrDS->ogr())); + std::string driverName(ogrDS->ogr().GetDriverName()); if ( driverName.find("ESRI Shapefile") != std::string::npos) { otbAppLogINFO(<<"REPACK the Shapefile ..."<<std::endl); diff --git a/Modules/Core/Common/otb-module.cmake b/Modules/Core/Common/otb-module.cmake index b3276d69422b566872290eba6a5d817cb2b45be1..7f1468126675bea77c61e159711239a1a7be2f2d 100644 --- a/Modules/Core/Common/otb-module.cmake +++ b/Modules/Core/Common/otb-module.cmake @@ -25,7 +25,6 @@ ENABLE_SHARED DEPENDS OTBBoost OTBITK - #Add dependency to OTBGDAL as GDAL module need to set OTB_USE_GDAL_20 before configuring otbConfigure.h OTBGDAL #Add dependency for extended filename helper class OTBBoostAdapters diff --git a/Modules/Core/Common/src/otbConfigure.h.in b/Modules/Core/Common/src/otbConfigure.h.in index 2146cf15bffa6fdb90e30c766a9f3f483263944e..f93fa266c56946791f42aa09e7d8bb63a14fe62a 100644 --- a/Modules/Core/Common/src/otbConfigure.h.in +++ b/Modules/Core/Common/src/otbConfigure.h.in @@ -27,8 +27,6 @@ #cmakedefine OTB_BUILD_SHARED_LIBS -#cmakedefine OTB_USE_GDAL_20 - #cmakedefine OTB_USE_OPENMP #cmakedefine OTB_USE_SSE_FLAGS diff --git a/Modules/Core/ComplexImage/otb-module.cmake b/Modules/Core/ComplexImage/otb-module.cmake index e80b01956289abbc6985352d0443a940be8f02eb..6b31ea5c698119698c90a82ed83688f24c432a2c 100644 --- a/Modules/Core/ComplexImage/otb-module.cmake +++ b/Modules/Core/ComplexImage/otb-module.cmake @@ -27,6 +27,7 @@ otb_module(OTBComplexImage TEST_DEPENDS OTBITK + OTBFunctor OTBImageBase OTBImageIO OTBTestKernel diff --git a/Modules/Core/ComplexImage/test/otbAmplitudePhaseToRGBFunctor.cxx b/Modules/Core/ComplexImage/test/otbAmplitudePhaseToRGBFunctor.cxx index 4861e5ec1665fd46bd06b8929aae92090178e512..ddfe7bf1e79474f75d77152f3db895839b00d8f4 100644 --- a/Modules/Core/ComplexImage/test/otbAmplitudePhaseToRGBFunctor.cxx +++ b/Modules/Core/ComplexImage/test/otbAmplitudePhaseToRGBFunctor.cxx @@ -24,9 +24,8 @@ #include "otbImage.h" #include "otbImageFileReader.h" #include "otbImageFileWriter.h" -#include "itkUnaryFunctorImageFilter.h" -#include "itkTernaryFunctorImageFilter.h" #include "otbAmplitudePhaseToRGBFunctor.h" +#include "otbFunctorImageFilter.h" #include "itkComplexToModulusImageFilter.h" #include "itkComplexToPhaseImageFilter.h" #include "itkShiftScaleImageFilter.h" @@ -65,11 +64,10 @@ int otbAmplitudePhaseToRGBFunctor(int itkNotUsed(argc), char * argv[]) typedef otb::Functor::AmplitudePhaseToRGBFunctor <PixelType, PixelType, PixelType, RGBPixelType> ColorMapFunctorType; - typedef itk::TernaryFunctorImageFilter - <ImageType, ImageType, ImageType, RGBImageType, ColorMapFunctorType> ColorMapFilterType; + typedef otb::FunctorImageFilter<ColorMapFunctorType> ColorMapFilterType; ColorMapFilterType::Pointer colormapper = ColorMapFilterType::New(); - colormapper->GetFunctor().SetMaximum(4000); - colormapper->GetFunctor().SetMinimum(0); + colormapper->GetModifiableFunctor().SetMaximum(4000); + colormapper->GetModifiableFunctor().SetMinimum(0); colormapper->SetInput1(modulusFilter->GetOutput()); colormapper->SetInput2(constFilter->GetOutput()); diff --git a/Modules/Core/Functor/include/otbFunctorImageFilter.hxx b/Modules/Core/Functor/include/otbFunctorImageFilter.hxx index add3fadcc4e18acef2bd4acb837fa2c93b3567e1..cda6bb6c63c8d47a6653b9bbaffe7ad05b53bb33 100644 --- a/Modules/Core/Functor/include/otbFunctorImageFilter.hxx +++ b/Modules/Core/Functor/include/otbFunctorImageFilter.hxx @@ -26,6 +26,7 @@ #include "itkConstNeighborhoodIterator.h" #include "itkImageRegionConstIterator.h" #include "itkImageScanlineIterator.h" +#include <array> namespace otb { diff --git a/Modules/Core/VectorDataBase/src/otbVectorDataKeywordlist.cxx b/Modules/Core/VectorDataBase/src/otbVectorDataKeywordlist.cxx index 39c3623e1a122bb187ab1f8b7c198af3d8098610..c14f3dda5a992d70dc68e4bfa6a62a56103cdf88 100644 --- a/Modules/Core/VectorDataBase/src/otbVectorDataKeywordlist.cxx +++ b/Modules/Core/VectorDataBase/src/otbVectorDataKeywordlist.cxx @@ -106,14 +106,12 @@ VectorDataKeywordlist ss << std::setprecision(15) << m_FieldList[i].second.Integer; return ss.str(); } -#ifdef OTB_USE_GDAL_20 case OFTInteger64: { std::ostringstream ss; ss << std::setprecision(15) << m_FieldList[i].second.Integer64; return ss.str(); } -#endif case OFTReal: { std::ostringstream ss; @@ -183,7 +181,6 @@ VectorDataKeywordlist { return (int)(m_FieldList[i].second.Integer); } -#ifdef OTB_USE_GDAL_20 // Some fields that were OFTInteger with gdal 1.x are now // exposed as OFTInteger64. So as to make the old code still // work with the same data, here we downcast to Integer (if @@ -197,7 +194,6 @@ VectorDataKeywordlist return static_cast<int>(m_FieldList[i].second.Integer64); } -#endif case OFTReal: { return (int)(m_FieldList[i].second.Real); @@ -483,13 +479,11 @@ VectorDataKeywordlist << field.second.Date.Hour << field.second.Date.Minute << field.second.Date.Second; break; } -#ifdef OTB_USE_GDAL_20 case OFTInteger64: { output << std::setprecision(15)<<field.second.Integer64; break; } -#endif default: output << "Type not handled for printing"; break; @@ -511,13 +505,11 @@ VectorDataKeywordlist outField.second.Integer = field.second.Integer; break; } -#ifdef OTB_USE_GDAL_20 case OFTInteger64: { outField.second.Integer64 = field.second.Integer64; break; } -#endif case OFTReal: { outField.second.Real = field.second.Real; diff --git a/Modules/Fusion/PanSharpening/include/otbBayesianFusionFilter.h b/Modules/Fusion/PanSharpening/include/otbBayesianFusionFilter.h index eb0b4a6389f69aaf1cb06cf9b94c534897cd7863..b8389e8463389e18c0dce4ff7ee6b90ac472c733 100644 --- a/Modules/Fusion/PanSharpening/include/otbBayesianFusionFilter.h +++ b/Modules/Fusion/PanSharpening/include/otbBayesianFusionFilter.h @@ -24,7 +24,7 @@ #include "itkImageToImageFilter.h" #include "otbVectorImage.h" #include "otbStreamingStatisticsVectorImageFilter.h" -#include "otbFusionImageBase.h" +#include "otbFunctorImageFilter.h" #include "otbStreamingMatrixTransposeMatrixImageFilter.h" #include "otbImageToVectorImageCastFilter.h" @@ -100,12 +100,11 @@ public: return m_Vcondopt; } - inline TOutput operator ()(const TInputMultiSpectral& itkNotUsed(ms), - const TInputMultiSpectralInterp& msi, - const TInputPanchro& p) + void operator ()(TOutput & obs, + const TInputMultiSpectral& itkNotUsed(ms), + const TInputMultiSpectralInterp& msi, + const TInputPanchro& p) { - TOutput obs; - obs.SetSize(msi.GetSize()); MatrixType obsMat, msiVect; obsMat.SetSize(1, obs.GetSize()); msiVect.SetSize(1, msi.GetSize()); @@ -145,7 +144,11 @@ public: { obs[i] = static_cast<typename TOutput::ValueType>(obsMat(0U, i)); } - return obs; + } + + constexpr size_t OutputSize(const std::array<size_t, 3> inputsNbBands) const + { + return inputsNbBands[1]; } private: @@ -193,14 +196,10 @@ template <class TInputMultiSpectralImage, class TInputPanchroImage, class TOutputImage> class ITK_EXPORT BayesianFusionFilter - : public FusionImageBase<TInputMultiSpectralImage, - TInputMultiSpectralInterpImage, - TInputPanchroImage, - TOutputImage, - Functor::BayesianFunctor<typename TInputMultiSpectralImage::PixelType, - typename TInputMultiSpectralInterpImage::PixelType, - typename TInputPanchroImage::PixelType, - typename TOutputImage::PixelType> > + : public FunctorImageFilter<Functor::BayesianFunctor<typename TInputMultiSpectralImage::PixelType, + typename TInputMultiSpectralInterpImage::PixelType, + typename TInputPanchroImage::PixelType, + typename TOutputImage::PixelType> > { public: /** Extract input and output images dimensions.*/ @@ -215,14 +214,11 @@ public: /** "typedef" for standard classes. */ typedef BayesianFusionFilter Self; - typedef FusionImageBase<InputMultiSpectralImageType, - InputMultiSpectralInterpImageType, - InputPanchroImageType, - OutputImageType, - Functor::BayesianFunctor<typename InputMultiSpectralImageType::PixelType, - typename InputMultiSpectralInterpImageType::PixelType, - typename InputPanchroImageType::PixelType, - typename OutputImageType::PixelType> > Superclass; + using BayesianFunctorType = Functor::BayesianFunctor<typename TInputMultiSpectralImage::PixelType, + typename TInputMultiSpectralInterpImage::PixelType, + typename TInputPanchroImage::PixelType, + typename TOutputImage::PixelType>; + typedef FunctorImageFilter<BayesianFunctorType> Superclass; typedef itk::SmartPointer<Self> Pointer; typedef itk::SmartPointer<const Self> ConstPointer; @@ -230,7 +226,7 @@ public: itkNewMacro(Self); /** return class name. */ - itkTypeMacro(BayesianFusionFilter, FusionImageBase); + itkTypeMacro(BayesianFusionFilter, FunctorImageFilter); /** Supported images definition. */ typedef typename InputMultiSpectralImageType::PixelType InputMultiSpectralPixelType; @@ -266,6 +262,36 @@ public: typedef ImageToVectorImageCastFilter<InputPanchroImageType, InputMultiSpectralImageType> CasterType; + void SetMultiSpect(const InputMultiSpectralImageType *multiSpect) + { + this->template SetVariadicInput<0>(multiSpect); + } + + void SetMultiSpectInterp(const InputMultiSpectralInterpImageType *multiSpectInterp) + { + this->template SetVariadicInput<1>(multiSpectInterp); + } + + void SetPanchro(const InputPanchroImageType *panchro) + { + this->template SetVariadicInput<2>(panchro); + } + + const InputMultiSpectralImageType* GetMultiSpect() + { + return this->template GetVariadicInput<0>(); + } + + const InputMultiSpectralInterpImageType* GetMultiSpectInterp() + { + return this->template GetVariadicInput<1>(); + } + + const InputPanchroImageType* GetPanchro() + { + return this->template GetVariadicInput<2>(); + } + /** Set the ponderation value. */ itkSetMacro(Lambda, float); /** Give the ponderation value. */ @@ -297,8 +323,14 @@ public: itkGetConstReferenceMacro(S, float); protected: - BayesianFusionFilter(); - ~BayesianFusionFilter() override; + BayesianFusionFilter() : Superclass(BayesianFunctorType{},{{0,0}}) + { + m_Lambda = 0.9999; + m_S = 1; + m_StatisticsHaveBeenGenerated = false; + }; + + ~BayesianFusionFilter() override {}; /** Check if internal statistics need to be computed, and do so */ void BeforeThreadedGenerateData() override; /** Compute internal statistics required for fusion */ diff --git a/Modules/Fusion/PanSharpening/include/otbBayesianFusionFilter.hxx b/Modules/Fusion/PanSharpening/include/otbBayesianFusionFilter.hxx index ca718c967e6c973c0c6b8944171991eddc8ab44e..0fe25b3875632b9d3694cb74b54999b18d94d6f5 100644 --- a/Modules/Fusion/PanSharpening/include/otbBayesianFusionFilter.hxx +++ b/Modules/Fusion/PanSharpening/include/otbBayesianFusionFilter.hxx @@ -27,33 +27,6 @@ namespace otb { -template <class TInputMultiSpectralImage, - class TInputMultiSpectralInterpImage, - class TInputPanchroImage, - class TOutputImage> -BayesianFusionFilter<TInputMultiSpectralImage, - TInputMultiSpectralInterpImage, - TInputPanchroImage, - TOutputImage> -::BayesianFusionFilter() -{ - m_Lambda = 0.9999; - m_S = 1; - m_StatisticsHaveBeenGenerated = false; -} - -template <class TInputMultiSpectralImage, - class TInputMultiSpectralInterpImage, - class TInputPanchroImage, - class TOutputImage> -BayesianFusionFilter<TInputMultiSpectralImage, - TInputMultiSpectralInterpImage, - TInputPanchroImage, - TOutputImage> -::~BayesianFusionFilter() -{ - -} template <class TInputMultiSpectralImage, class TInputMultiSpectralInterpImage, class TInputPanchroImage, @@ -302,12 +275,12 @@ BayesianFusionFilter<TInputMultiSpectralImage, //**** END TODO ****/ m_Vcondopt = m_Vcondopt.GetInverse(); // Functor initialization - this->GetFunctor().SetVcondopt(m_Vcondopt); - this->GetFunctor().SetBeta(cutBeta); - this->GetFunctor().SetAlpha(m_Beta(0, 0)); - this->GetFunctor().SetCovarianceInvMatrix(m_CovarianceInvMatrix); - this->GetFunctor().SetLambda(m_Lambda); - this->GetFunctor().SetS(m_S); + this->GetModifiableFunctor().SetVcondopt(m_Vcondopt); + this->GetModifiableFunctor().SetBeta(cutBeta); + this->GetModifiableFunctor().SetAlpha(m_Beta(0, 0)); + this->GetModifiableFunctor().SetCovarianceInvMatrix(m_CovarianceInvMatrix); + this->GetModifiableFunctor().SetLambda(m_Lambda); + this->GetModifiableFunctor().SetS(m_S); // Restore the previous buffered data multiSpecInterp->SetRequestedRegion(msiRequestedRegion); diff --git a/Modules/Fusion/PanSharpening/include/otbFusionImageBase.h b/Modules/Fusion/PanSharpening/include/otbFusionImageBase.h deleted file mode 100644 index 2e7429281c3bec78addc71aaa18d1cc0ac2685bf..0000000000000000000000000000000000000000 --- a/Modules/Fusion/PanSharpening/include/otbFusionImageBase.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES) - * - * This file is part of Orfeo Toolbox - * - * https://www.orfeo-toolbox.org/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef otbFusionImageBase_h -#define otbFusionImageBase_h - -#include "itkTernaryFunctorImageFilter.h" -#include "itkNumericTraits.h" - -namespace otb -{ -/** \class FusionImageBase - * Basic class for every Fusion classes. - * \sa TernaryFunctorImageFilter - * - * \ingroup OTBPanSharpening - */ -template <class TInputMultiSpectralImage, class TInputMultiSpectralInterpImage, class TInputPanchroImage, - class TOutputImage, class TFunctor> -class ITK_EXPORT FusionImageBase : public itk::TernaryFunctorImageFilter<TInputMultiSpectralImage, - TInputMultiSpectralInterpImage, - TInputPanchroImage, TOutputImage, TFunctor> -{ -public: - /** Extract input and output images dimensions.*/ - itkStaticConstMacro(InputImageDimension, unsigned int, TInputMultiSpectralImage::ImageDimension); - itkStaticConstMacro(OutputImageDimension, unsigned int, TOutputImage::ImageDimension); - - /** "typedef" to simplify the variables definition and the declaration. */ - typedef TInputMultiSpectralImage InputMultiSpectralImageType; - typedef TInputMultiSpectralInterpImage InputMultiSpectralInterpImageType; - typedef TInputPanchroImage InputPanchroImageType; - typedef TOutputImage OutputImageType; - typedef TFunctor FunctorType; - - /** "typedef" for standard classes. */ - typedef FusionImageBase Self; - typedef itk::TernaryFunctorImageFilter<InputMultiSpectralImageType, - InputMultiSpectralInterpImageType, - InputPanchroImageType, - OutputImageType, - FunctorType> Superclass; - typedef itk::SmartPointer<Self> Pointer; - typedef itk::SmartPointer<const Self> ConstPointer; - - /** object factory method. */ - itkNewMacro(Self); - - /** return class name. */ - itkTypeMacro(FusionImageBase, TernaryFunctorImageFilter); - - /** Supported images definition. */ - typedef typename InputMultiSpectralImageType::PixelType InputMultiSpectralPixelType; - typedef typename InputMultiSpectralInterpImageType::PixelType InputMultiSpectralInterpPixelType; - typedef typename InputPanchroImageType::PixelType InputPanchroPixelType; - typedef typename OutputImageType::PixelType OutputPixelType; - /** Real class typedef definition. */ - typedef typename itk::NumericTraits<InputMultiSpectralPixelType>::RealType InputMultiSpectralRealType; - typedef typename itk::NumericTraits<InputMultiSpectralInterpPixelType>::RealType InputMultiSpectralInterpRealType; - typedef typename itk::NumericTraits<InputPanchroPixelType>::RealType InputPanchroRealType; - typedef typename InputMultiSpectralImageType::RegionType InputMultiSpectralImageRegionType; - typedef typename InputMultiSpectralInterpImageType::RegionType - InputMultiSpectralInterpImageRegionType; - typedef typename InputPanchroImageType::RegionType InputPanchroImageRegionType; - typedef typename OutputImageType::RegionType OutputImageRegionType; - - /** Image size "typedef" definition. */ - typedef typename InputMultiSpectralImageType::SizeType SizeType; - - void SetMultiSpect(const InputMultiSpectralImageType *multiSpect) - { - this->SetInput1(multiSpect); - } - void SetMultiSpectInterp(const InputMultiSpectralInterpImageType *multiSpectInterp) - { - this->SetInput2(multiSpectInterp); - } - void SetPanchro(const InputPanchroImageType *panchro) - { - this->SetInput3(panchro); - } - - const InputMultiSpectralImageType* GetMultiSpect() - { - if (this->GetNumberOfInputs() < 1) - { - return nullptr; - } - else return (static_cast<const InputMultiSpectralImageType *>(this->itk::ProcessObject::GetInput(0))); - } - - const InputMultiSpectralInterpImageType* GetMultiSpectInterp() - { - if (this->GetNumberOfInputs() < 2) - { - return nullptr; - } - else return (static_cast<const InputMultiSpectralInterpImageType *>(this->itk::ProcessObject::GetInput(1))); - } - - const InputPanchroImageType* GetPanchro() - { - if (this->GetNumberOfInputs() < 3) - { - return nullptr; - } - else return (static_cast<const InputPanchroImageType *>(this->itk::ProcessObject::GetInput(2))); - } - -}; - -} // end namespace otb - -#endif diff --git a/Modules/Fusion/PanSharpening/include/otbLmvmPanSharpeningFusionImageFilter.h b/Modules/Fusion/PanSharpening/include/otbLmvmPanSharpeningFusionImageFilter.h index 74d85336699d1def707944156b84873e772c68f2..345a7bcb959c97b7177b5b87451d0b7a3480517c 100644 --- a/Modules/Fusion/PanSharpening/include/otbLmvmPanSharpeningFusionImageFilter.h +++ b/Modules/Fusion/PanSharpening/include/otbLmvmPanSharpeningFusionImageFilter.h @@ -23,8 +23,7 @@ #define otbLmvmPanSharpeningFusionImageFilter_h #include "otbConvolutionImageFilter.h" -#include "itkUnaryFunctorImageFilter.h" -#include "itkTernaryFunctorImageFilter.h" +#include "otbFunctorImageFilter.h" #include "otbPerBandVectorImageFilter.h" #include "itkNoiseImageFilter.h" #include "otbVectorImage.h" @@ -132,36 +131,34 @@ private: { public: // Implement the fusion as a six arguments operator - typename TOutputImageType::PixelType operator()( - const typename InternalVectorImageType::PixelType& stdXsPixel, - const TInternalPrecision& smoothPanchroPixel, - const typename TPanImageType::PixelType& sharpPanchroPixel) const + void operator()(typename TOutputImageType::PixelType& output, + const typename InternalVectorImageType::PixelType& stdXsPixel, + const TInternalPrecision& smoothPanchroPixel, + const typename TPanImageType::PixelType& sharpPanchroPixel) const { - // Build output pixel - typename TOutputImageType::PixelType output(stdXsPixel.Size()); - // Perform fusion for each band with appropriate casting for(unsigned int i = 0; i < stdXsPixel.Size(); ++i) { output[i] = static_cast<typename TOutputImageType::InternalPixelType>( ((sharpPanchroPixel - smoothPanchroPixel) * stdXsPixel[i])); } - // Returns the output pixel - return output; } + constexpr size_t OutputSize(const std::array<size_t, 3> inputsNbBands) const + { + return inputsNbBands[0]; + } + }; class FusionFunctor2 { public: // Implement the fusion as a six arguments operator - typename TOutputImageType::PixelType operator()(const typename TOutputImageType::PixelType& functor1Pixel, - const typename InternalVectorImageType::PixelType& smoothXsPixel, - const TInternalPrecision& stdPanchroPixel) const + void operator()(typename TOutputImageType::PixelType & output, + const typename TOutputImageType::PixelType& functor1Pixel, + const typename InternalVectorImageType::PixelType& smoothXsPixel, + const TInternalPrecision& stdPanchroPixel) const { - // Build output pixel - typename TOutputImageType::PixelType output(smoothXsPixel.Size()); - TInternalPrecision scale = 1.; if(std::abs(stdPanchroPixel) > 1e-10) @@ -175,8 +172,11 @@ private: output[i] = static_cast<typename TOutputImageType::InternalPixelType>( ((functor1Pixel[i] * scale) + smoothXsPixel[i])); } - // Returns the output pixel - return output; + } + + constexpr size_t OutputSize(const std::array<size_t, 3> inputsNbBands) const + { + return inputsNbBands[0]; } }; @@ -184,24 +184,16 @@ private: * Typedef of the TernaryFunctorImageFilter applying the fusion functor to * p, p_smooth, p_std, xs_smooth, xs_std and xs. */ - typedef itk::TernaryFunctorImageFilter<InternalVectorImageType, - InternalImageType, - TPanImageType, - TOutputImageType, - FusionFunctor1> FusionStep1FilterType; + typedef FunctorImageFilter<FusionFunctor1> FusionStep1FilterType; /** Pointer to the fusion filter */ - typename FusionStep1FilterType::Pointer m_FusionStep1Filter; + typename FusionStep1FilterType::Pointer m_FusionStep1Filter; - typedef itk::TernaryFunctorImageFilter<TOutputImageType, - InternalVectorImageType, - InternalImageType, - TOutputImageType, - FusionFunctor2> FusionStep2FilterType; + typedef FunctorImageFilter<FusionFunctor2> FusionStep2FilterType; /** Pointer to the fusion filter */ - typename FusionStep2FilterType::Pointer m_FusionStep2Filter; + typename FusionStep2FilterType::Pointer m_FusionStep2Filter; /** Typedef of the convolution filter performing Pan smoothing */ diff --git a/Modules/Fusion/PanSharpening/include/otbSimpleRcsPanSharpeningFusionImageFilter.h b/Modules/Fusion/PanSharpening/include/otbSimpleRcsPanSharpeningFusionImageFilter.h index ab0d4de8ca5d2dfaa1bf53787176a67367be2aff..2fe474c54361b798153c37c4564a5420a3f7dae7 100644 --- a/Modules/Fusion/PanSharpening/include/otbSimpleRcsPanSharpeningFusionImageFilter.h +++ b/Modules/Fusion/PanSharpening/include/otbSimpleRcsPanSharpeningFusionImageFilter.h @@ -24,7 +24,7 @@ #include "otbConvolutionImageFilter.h" #include "otbImage.h" -#include "itkTernaryFunctorImageFilter.h" +#include "otbFunctorImageFilter.h" #include "itkProgressAccumulator.h" @@ -118,13 +118,11 @@ private: { public: // Implement the fusion as a three arguments operator - typename TOutputImageType::PixelType operator()(const typename TXsImageType::PixelType& xsPixel, + void operator()(typename TOutputImageType::PixelType & output, + const typename TXsImageType::PixelType& xsPixel, const TInternalPrecision& smoothPanchroPixel, const typename TPanImageType::PixelType& sharpPanchroPixel) const { - // Build output pixel - typename TOutputImageType::PixelType output(xsPixel.Size()); - TInternalPrecision scale = 1.; if(std::abs(smoothPanchroPixel) > 1e-10) @@ -138,8 +136,11 @@ private: output[i] = static_cast<typename TOutputImageType::InternalPixelType>( xsPixel[i] * scale); } - // Returns the output pixel - return output; + } + + constexpr size_t OutputSize(const std::array<size_t, 3> & inputsNbBands) const + { + return inputsNbBands[0]; } }; @@ -155,13 +156,11 @@ private: { public: // Implement the fusion as a three arguments operator - typename TOutputImageType::PixelType operator()(const typename TXsImageType::PixelType& xsPixel, - const TInternalPrecision& smoothPanchroPixel, - const typename TPanImageType::PixelType& sharpPanchroPixel) const + void operator()(typename TOutputImageType::PixelType & output, + const typename TXsImageType::PixelType& xsPixel, + const TInternalPrecision& smoothPanchroPixel, + const typename TPanImageType::PixelType& sharpPanchroPixel) const { - // Build output pixel - typename TOutputImageType::PixelType output(xsPixel.Size()); - // Check for no data Pan value if( m_NoDataValuePanAvailable && sharpPanchroPixel == m_NoDataValuePan ) { @@ -169,7 +168,7 @@ private: { output[i] = static_cast<typename TOutputImageType::InternalPixelType>( m_NoDataValuesXs[i] ); } - return output; + return; } TInternalPrecision scale = 1.; @@ -186,8 +185,6 @@ private: static_cast<typename TOutputImageType::InternalPixelType>( xsPixel[i] ) : static_cast<typename TOutputImageType::InternalPixelType>( xsPixel[i] * scale ); } - // Returns the output pixel - return output; } void SetNoDataValuePanAvailable(bool noDataAvailable) { @@ -206,6 +203,12 @@ private: m_NoDataValuesXs = noDataValues; } + constexpr size_t OutputSize(const std::array<size_t, 3> inputsNbBands) const + { + return inputsNbBands[0]; + } + + NoDataFusionFunctor() : m_NoDataValuePanAvailable(false), m_NoDataValuePan(0),m_NoDataValuesXsAvailable(false), m_NoDataValuesXs() {} private: /** No data flags and values for APN image */ @@ -221,24 +224,16 @@ private: /** - * Typedef of the TernaryFunctorImageFilter applying the fusion functor to + * Typedef of the FunctorImageFilter applying the fusion functor to * p, p_smooth and xs. */ - typedef itk::TernaryFunctorImageFilter<TXsImageType, - InternalImageType, - TPanImageType, - TOutputImageType, - FusionFunctor> FusionFilterType; + typedef FunctorImageFilter<FusionFunctor> FusionFilterType; /** - * Typedef of the TernaryFunctorImageFilter applying the no data fusion functor to + * Typedef of the FunctorImageFilter applying the no data fusion functor to * p, p_smooth and xs. */ - typedef itk::TernaryFunctorImageFilter<TXsImageType, - InternalImageType, - TPanImageType, - TOutputImageType, - NoDataFusionFunctor> NoDataFusionFilterType; + typedef FunctorImageFilter<NoDataFusionFunctor> NoDataFusionFilterType; /** Typedef of the convolution filter performing smoothing */ typedef otb::ConvolutionImageFilter diff --git a/Modules/Fusion/PanSharpening/include/otbSimpleRcsPanSharpeningFusionImageFilter.hxx b/Modules/Fusion/PanSharpening/include/otbSimpleRcsPanSharpeningFusionImageFilter.hxx index e8a5c642fe8e9c9e557a0cde4f68a7f788fbeff4..eb7624829796ae1879897845c9e2472c7d16f295 100644 --- a/Modules/Fusion/PanSharpening/include/otbSimpleRcsPanSharpeningFusionImageFilter.hxx +++ b/Modules/Fusion/PanSharpening/include/otbSimpleRcsPanSharpeningFusionImageFilter.hxx @@ -174,10 +174,10 @@ SimpleRcsPanSharpeningFusionImageFilter m_ProgressAccumulator->RegisterInternalFilter( m_NoDataFusionFilter, 0.1 ); m_NoDataFusionFilter->SetInput2( m_ConvolutionFilter->GetOutput() ); - m_NoDataFusionFilter->GetFunctor().SetNoDataValuesXsAvailable( noDataValuesXsAvailable ); - m_NoDataFusionFilter->GetFunctor().SetNoDataValuePanAvailable( noDataValuePanAvailable ); - m_NoDataFusionFilter->GetFunctor().SetNoDataValuePan( noDataValuePan ); - m_NoDataFusionFilter->GetFunctor().SetNoDataValuesXs( noDataValuesXs ); + m_NoDataFusionFilter->GetModifiableFunctor().SetNoDataValuesXsAvailable( noDataValuesXsAvailable ); + m_NoDataFusionFilter->GetModifiableFunctor().SetNoDataValuePanAvailable( noDataValuePanAvailable ); + m_NoDataFusionFilter->GetModifiableFunctor().SetNoDataValuePan( noDataValuePan ); + m_NoDataFusionFilter->GetModifiableFunctor().SetNoDataValuesXs( noDataValuesXs ); m_NoDataFusionFilter->SetInput1( this->GetXsInput() ); m_NoDataFusionFilter->SetInput2( m_ConvolutionFilter->GetOutput() ); diff --git a/Modules/Fusion/PanSharpening/otb-module.cmake b/Modules/Fusion/PanSharpening/otb-module.cmake index d53c37af34f75ea5120980b48308194ac24682c1..e8444f8661dd66783286cdc19e1200fad32ea07f 100644 --- a/Modules/Fusion/PanSharpening/otb-module.cmake +++ b/Modules/Fusion/PanSharpening/otb-module.cmake @@ -32,7 +32,7 @@ otb_module(OTBPanSharpening OTBITK OTBConvolution OTBImageManipulation - + OTBFunctor TEST_DEPENDS OTBTestKernel OTBImageIO diff --git a/Modules/IO/IOGDAL/include/otbOGRIOHelper.h b/Modules/IO/IOGDAL/include/otbOGRIOHelper.h index 67b5e19778378afc4ed1a95e26a809f13c84358a..5427f030c6cbd786a3cd283635852e176dbed1fa 100644 --- a/Modules/IO/IOGDAL/include/otbOGRIOHelper.h +++ b/Modules/IO/IOGDAL/include/otbOGRIOHelper.h @@ -24,7 +24,6 @@ #include <vector> #include "otbVectorData.h" -#include "otbOGRVersionProxy.h" #include "OTBIOGDALExport.h" @@ -74,14 +73,14 @@ public: unsigned int ProcessNodeWrite(InternalTreeNodeType * source, - ogr::version_proxy::GDALDatasetType * m_DataSource, + GDALDataset * m_DataSource, OGRGeometryCollection * ogrCollection, OGRLayer * ogrCurrentLayer, OGRSpatialReference * oSRS); /** Return a list of OGRLayer * */ std::vector<OGRLayer*> ConvertDataTreeNodeToOGRLayers(InternalTreeNodeType * source, - ogr::version_proxy::GDALDatasetType * dummyDatasource, + GDALDataset * dummyDatasource, OGRLayer* ogrCurrentLayer, OGRSpatialReference * oSRS); diff --git a/Modules/IO/IOGDAL/include/otbOGRVectorDataIO.h b/Modules/IO/IOGDAL/include/otbOGRVectorDataIO.h index dbff89e1b3dd6448dd2d7ad57950c2e9e2f190ca..d743bfa2b5e3b0736edcfaac8ae9b70b1801f786 100644 --- a/Modules/IO/IOGDAL/include/otbOGRVectorDataIO.h +++ b/Modules/IO/IOGDAL/include/otbOGRVectorDataIO.h @@ -26,7 +26,6 @@ #include "otbVectorDataIOBase.h" #include "otbVectorData.h" -#include "otbOGRVersionProxy.h" #include "OTBIOGDALExport.h" @@ -123,7 +122,7 @@ private: void CloseInternalDataSource(); - ogr::version_proxy::GDALDatasetType * m_DataSource; + GDALDataset * m_DataSource; }; diff --git a/Modules/IO/IOGDAL/src/otbGDALImageIO.cxx b/Modules/IO/IOGDAL/src/otbGDALImageIO.cxx index 22cdc92cd695dbba7937858a4d994bc9ea0ceba5..5a8f62ce70387bd3b372b02747aca18c056663d0 100644 --- a/Modules/IO/IOGDAL/src/otbGDALImageIO.cxx +++ b/Modules/IO/IOGDAL/src/otbGDALImageIO.cxx @@ -1508,7 +1508,6 @@ void GDALImageIO::InternalWriteImageInformation(const void* buffer) /* -------------------------------------------------------------------- */ /* Set the RPC coeffs if no projection available (since GDAL 1.10.0) */ /* -------------------------------------------------------------------- */ -#if GDAL_VERSION_NUM >= 1100000 ImageKeywordlist otb_kwl; itk::ExposeMetaData<ImageKeywordlist>(dict, MetaDataKey::OSSIMKeywordlistKey, @@ -1523,7 +1522,6 @@ void GDALImageIO::InternalWriteImageInformation(const void* buffer) CSLDestroy( rpcMetadata ); } } -#endif } /* -------------------------------------------------------------------- */ diff --git a/Modules/IO/IOGDAL/src/otbOGRIOHelper.cxx b/Modules/IO/IOGDAL/src/otbOGRIOHelper.cxx index c27c1525025ef3f118cfac387e636e60ad55d584..0bf6f0644d9536a302cc54d191e4de4bf27d90fa 100644 --- a/Modules/IO/IOGDAL/src/otbOGRIOHelper.cxx +++ b/Modules/IO/IOGDAL/src/otbOGRIOHelper.cxx @@ -209,7 +209,7 @@ void OGRIOHelper otb::VectorDataKeywordlist kwl; for (int fieldNum = 0; fieldNum < feature->GetFieldCount(); ++fieldNum) { - if (ogr::version_proxy::IsFieldSetAndNotNull(feature, fieldNum)) + if (ogr::IsFieldSetAndNotNull(feature, fieldNum)) { kwl.AddField(feature->GetFieldDefnRef(fieldNum), feature->GetRawFieldRef(fieldNum)); } @@ -651,7 +651,7 @@ void OGRIOHelper unsigned int OGRIOHelper ::ProcessNodeWrite(InternalTreeNodeType * source, - ogr::version_proxy::GDALDatasetType * m_DataSource, + GDALDataset * m_DataSource, OGRGeometryCollection * ogrCollection, OGRLayer * ogrCurrentLayer, OGRSpatialReference * oSRS) @@ -1027,7 +1027,7 @@ unsigned int OGRIOHelper **/ std::vector<OGRLayer*> OGRIOHelper ::ConvertDataTreeNodeToOGRLayers(InternalTreeNodeType * source, - ogr::version_proxy::GDALDatasetType * inMemoryDataSource, + GDALDataset * inMemoryDataSource, OGRLayer* ogrCurrentLayer, OGRSpatialReference * oSRS) { @@ -1036,8 +1036,13 @@ std::vector<OGRLayer*> OGRIOHelper if (inMemoryDataSource == nullptr) { const char * driverName = "Memory"; - ogr::version_proxy::GDALDriverType * ogrDriver = ogr::version_proxy::GetDriverByName(driverName); - inMemoryDataSource = ogr::version_proxy::Create(ogrDriver,"tempDataSource"); + GDALDriver * ogrDriver = GetGDALDriverManager()->GetDriverByName(driverName); + inMemoryDataSource = ogrDriver->Create( "tempDataSource", + 0, + 0, + 0, + GDT_Unknown, + 0); } std::vector<OGRLayer*> ogrLayerVector; diff --git a/Modules/IO/IOGDAL/src/otbOGRVectorDataIO.cxx b/Modules/IO/IOGDAL/src/otbOGRVectorDataIO.cxx index f47b192d7ea916632d00f880722f7d7304f1a1b4..2d280b1af1d253995429407f559406cac20e142c 100644 --- a/Modules/IO/IOGDAL/src/otbOGRVectorDataIO.cxx +++ b/Modules/IO/IOGDAL/src/otbOGRVectorDataIO.cxx @@ -54,15 +54,19 @@ OGRVectorDataIO::~OGRVectorDataIO() bool OGRVectorDataIO::CanReadFile(const char* filename) const { - otb::ogr::version_proxy::GDALDatasetType * poDS = ogr::version_proxy::Open(filename, true); - + GDALDataset * poDS = (GDALDataset *)GDALOpenEx( + filename, + GDAL_OF_READONLY | GDAL_OF_VECTOR, + NULL, + NULL, + NULL); if (poDS == nullptr) { std::cerr<<"Can not read file "<<filename<<" with GDALOpen"<<std::endl; return false; } // std::cout << poDS->GetDriver()->GetName() << std::endl; - ogr::version_proxy::Close(poDS); + GDALClose(poDS); return true; } @@ -93,8 +97,12 @@ OGRVectorDataIO this->CloseInternalDataSource(); } - m_DataSource = ogr::version_proxy::Open(this->m_FileName.c_str(),true); - + m_DataSource = (GDALDataset *)GDALOpenEx( + this->m_FileName.c_str(), + GDAL_OF_READONLY | GDAL_OF_VECTOR, + NULL, + NULL, + NULL); if (m_DataSource == nullptr) { itkExceptionMacro(<< "Failed to open data file " << this->m_FileName); @@ -184,7 +192,7 @@ OGRVectorDataIO void OGRVectorDataIO::CloseInternalDataSource() { assert(m_DataSource != NULL && "m_DataSource cannot be NULL"); - ogr::version_proxy::Close(m_DataSource); + GDALClose(m_DataSource); m_DataSource = nullptr; } @@ -215,8 +223,8 @@ void OGRVectorDataIO::Write(const itk::DataObject* datag, char ** /** unused */) //Find first the OGR driver - ogr::version_proxy::GDALDriverType * ogrDriver = - ogr::version_proxy::GetDriverByName(this->GetOGRDriverName(this->m_FileName).data()); + GDALDriver * ogrDriver = + GetGDALDriverManager()->GetDriverByName(this->GetOGRDriverName(this->m_FileName).data()); if (ogrDriver == nullptr) { @@ -226,15 +234,34 @@ void OGRVectorDataIO::Write(const itk::DataObject* datag, char ** /** unused */) // free an existing previous data source, if any if (m_DataSource != nullptr) { - ogr::version_proxy::Close(m_DataSource); + GDALClose(m_DataSource); } // Erase the dataSource if already exist - ogr::version_proxy::Delete(this->m_FileName.c_str()); - - // m_DataSource = OGRSFDriverRegistrar::Open(this->m_FileName.c_str(), TRUE); - m_DataSource = ogr::version_proxy::Create(ogrDriver,this->m_FileName.c_str()); + GDALDataset * poDS = (GDALDataset *)GDALOpenEx( + this->m_FileName.c_str(), + GDAL_OF_UPDATE | GDAL_OF_VECTOR, + NULL, + NULL, + NULL); + + GDALDriver * poDriver = NULL; + if(poDS) + { + poDriver = poDS->GetDriver(); + GDALClose(poDS); + } + if(poDriver) + { + poDriver->Delete(this->m_FileName.c_str()); + } + m_DataSource = ogrDriver->Create( this->m_FileName.c_str(), + 0, + 0, + 0, + GDT_Unknown, + 0); // check the created data source if (m_DataSource == nullptr) { @@ -288,7 +315,7 @@ void OGRVectorDataIO::Write(const itk::DataObject* datag, char ** /** unused */) otbMsgDevMacro( << "layerKept " << layerKept ); (void)layerKept; // keep compiler happy - otb::ogr::version_proxy::Close(m_DataSource); + GDALClose(m_DataSource); m_DataSource = nullptr; if (oSRS != nullptr) diff --git a/Modules/IO/TestKernel/src/otbTestHelper.cxx b/Modules/IO/TestKernel/src/otbTestHelper.cxx index fae2a40dfe64a70447af91c8ade41eb539f20fb5..e849b0129510644ac3d9c856d570f7931b5cbb04 100644 --- a/Modules/IO/TestKernel/src/otbTestHelper.cxx +++ b/Modules/IO/TestKernel/src/otbTestHelper.cxx @@ -48,7 +48,7 @@ #include "otbDifferenceImageFilter.h" #include "otbPrintableImageFilter.h" #include "otbStreamingShrinkImageFilter.h" -#include "otbOGRVersionProxy.h" +#include "otbOGRHelpers.h" #include "otbConfigure.h" @@ -1727,28 +1727,48 @@ int TestHelper::RegressionTestOgrFile(const char *testOgrFilename, const char *b /* -------------------------------------------------------------------- */ /* Open data source. */ /* -------------------------------------------------------------------- */ - otb::ogr::version_proxy::GDALDatasetType *ref_poDS = nullptr; - otb::ogr::version_proxy::GDALDriverType * ref_poDriver = nullptr; + GDALDataset *ref_poDS = nullptr; + GDALDriver * ref_poDriver = nullptr; //OGRGeometry * ref_poSpatialFilter = NULL; - otb::ogr::version_proxy::GDALDatasetType *test_poDS = nullptr; - otb::ogr::version_proxy::GDALDriverType * test_poDriver = nullptr; + GDALDataset *test_poDS = nullptr; + GDALDriver * test_poDriver = nullptr; //OGRGeometry * test_poSpatialFilter = NULL; - ref_poDS = otb::ogr::version_proxy::Open(ref_pszDataSource, false); + ref_poDS = (GDALDataset *)GDALOpenEx( + ref_pszDataSource, + GDAL_OF_UPDATE | GDAL_OF_VECTOR, + NULL, + NULL, + NULL); + if (ref_poDS == nullptr && !bReadOnly) { - ref_poDS = otb::ogr::version_proxy::Open(ref_pszDataSource, true); + ref_poDS = (GDALDataset *)GDALOpenEx( + ref_pszDataSource, + GDAL_OF_READONLY | GDAL_OF_VECTOR, + NULL, + NULL, + NULL); bReadOnly = TRUE; if (ref_poDS != nullptr && m_ReportErrors) { std::cout << "Had to open REF data source read-only."<<std::endl; } } - test_poDS = otb::ogr::version_proxy::Open(ref_pszDataSource, bReadOnly); + test_poDS = (GDALDataset *)GDALOpenEx( + ref_pszDataSource, + (bReadOnly? GDAL_OF_READONLY : GDAL_OF_UPDATE) | GDAL_OF_VECTOR, + NULL, + NULL, + NULL); if (test_poDS == nullptr && !bReadOnly) { - test_poDS = otb::ogr::version_proxy::Open(ref_pszDataSource, bReadOnly); - + test_poDS = (GDALDataset *)GDALOpenEx( + ref_pszDataSource, + (bReadOnly? GDAL_OF_READONLY : GDAL_OF_UPDATE) | GDAL_OF_VECTOR, + NULL, + NULL, + NULL); bReadOnly = TRUE; if (test_poDS != nullptr && m_ReportErrors) @@ -1766,7 +1786,7 @@ int TestHelper::RegressionTestOgrFile(const char *testOgrFilename, const char *b { std::cout << "FAILURE:\n" "Unable to open REF datasource `" << ref_pszDataSource << "' with the following drivers." << std::endl; - std::vector<std::string> drivers = ogr::version_proxy::GetAvailableDriversAsStringVector(); + std::vector<std::string> drivers = ogr::GetAvailableDriversAsStringVector(); for (std::vector<std::string>::const_iterator it = drivers.begin();it!=drivers.end();++it) { @@ -1784,7 +1804,7 @@ int TestHelper::RegressionTestOgrFile(const char *testOgrFilename, const char *b { std::cout << "FAILURE:\n""Unable to open TEST datasource `" << test_pszDataSource << "' with the following drivers." << std::endl; - std::vector<std::string> drivers = ogr::version_proxy::GetAvailableDriversAsStringVector(); + std::vector<std::string> drivers = ogr::GetAvailableDriversAsStringVector(); for (std::vector<std::string>::const_iterator it = drivers.begin();it!=drivers.end();++it) { @@ -1803,8 +1823,8 @@ int TestHelper::RegressionTestOgrFile(const char *testOgrFilename, const char *b // TODO: Improve this check as it will stop as soon as one of the // list ends (i.e. it does not guarantee that all files are present) - std::vector<std::string> refFileList = otb::ogr::version_proxy::GetFileListAsStringVector(ref_poDS); - std::vector<std::string> testFileList = otb::ogr::version_proxy::GetFileListAsStringVector(test_poDS); + std::vector<std::string> refFileList = otb::ogr::GetFileListAsStringVector(ref_poDS); + std::vector<std::string> testFileList = otb::ogr::GetFileListAsStringVector(test_poDS); unsigned int fileId = 0; @@ -1941,7 +1961,7 @@ void TestHelper::DumpOGRFeature(FILE* fpOut, OGRFeature* feature, char** papszOp poFDefn->GetNameRef(), OGRFieldDefn::GetFieldTypeName(poFDefn->GetType())); - if (ogr::version_proxy::IsFieldSetAndNotNull(feature, iField)) fprintf(fpOut, "%s\n", feature->GetFieldAsString(iField)); + if (ogr::IsFieldSetAndNotNull(feature, iField)) fprintf(fpOut, "%s\n", feature->GetFieldAsString(iField)); else fprintf(fpOut, "(null)\n"); } diff --git a/Modules/Learning/DimensionalityReductionLearning/include/otbAutoencoderModel.h b/Modules/Learning/DimensionalityReductionLearning/include/otbAutoencoderModel.h index 71ed7482073a8090e7ef854436707cca60a88528..1c133864de36de022b2b1a1104cdb22cef7de949 100644 --- a/Modules/Learning/DimensionalityReductionLearning/include/otbAutoencoderModel.h +++ b/Modules/Learning/DimensionalityReductionLearning/include/otbAutoencoderModel.h @@ -84,6 +84,8 @@ public: typedef typename Superclass::ConfidenceSampleType ConfidenceSampleType; typedef typename Superclass::ConfidenceListSampleType ConfidenceListSampleType; + typedef typename Superclass::ProbaSampleType ProbaSampleType; + typedef typename Superclass::ProbaListSampleType ProbaListSampleType; /// Neural network related typedefs typedef shark::ConcatenatedModel<shark::RealVector> ModelType; typedef shark::LinearModel<shark::RealVector,NeuronType> LayerType; @@ -162,14 +164,16 @@ protected: virtual TargetSampleType DoPredict( const InputSampleType& input, - ConfidenceValueType * quality = nullptr) const override; + ConfidenceValueType * quality = nullptr, + ProbaSampleType * proba = nullptr) const override; virtual void DoPredictBatch( const InputListSampleType *, const unsigned int & startIndex, const unsigned int & size, TargetListSampleType *, - ConfidenceListSampleType * quality = nullptr) const override; + ConfidenceListSampleType * quality = nullptr, + ProbaListSampleType * proba = nullptr) const override; private: /** Internal Network */ diff --git a/Modules/Learning/DimensionalityReductionLearning/include/otbAutoencoderModel.hxx b/Modules/Learning/DimensionalityReductionLearning/include/otbAutoencoderModel.hxx index 636f62cfd22ec339da109a2a7a7fea75832481bf..695f7e29e97502d96bd5a8cee8440913941fb1cb 100644 --- a/Modules/Learning/DimensionalityReductionLearning/include/otbAutoencoderModel.hxx +++ b/Modules/Learning/DimensionalityReductionLearning/include/otbAutoencoderModel.hxx @@ -375,7 +375,7 @@ AutoencoderModel<TInputValue,NeuronType> template <class TInputValue, class NeuronType> typename AutoencoderModel<TInputValue,NeuronType>::TargetSampleType AutoencoderModel<TInputValue,NeuronType> -::DoPredict(const InputSampleType & value, ConfidenceValueType * /*quality*/) const +::DoPredict(const InputSampleType & value, ConfidenceValueType * /*quality*/, ProbaSampleType * /*proba*/) const { shark::RealVector samples(value.Size()); for(size_t i = 0; i < value.Size();i++) @@ -408,7 +408,8 @@ AutoencoderModel<TInputValue,NeuronType> const unsigned int & startIndex, const unsigned int & size, TargetListSampleType * targets, - ConfidenceListSampleType * /*quality*/) const + ConfidenceListSampleType * /*quality*/, + ProbaListSampleType * /*proba*/) const { std::vector<shark::RealVector> features; Shark::ListSampleRangeToSharkVector(input, features,startIndex,size); diff --git a/Modules/Learning/DimensionalityReductionLearning/include/otbPCAModel.h b/Modules/Learning/DimensionalityReductionLearning/include/otbPCAModel.h index c1aa97b938b350824da50b0d2886537fed3828f4..cc3971fe001e6cda8f8c84158e2b82ecad546394 100644 --- a/Modules/Learning/DimensionalityReductionLearning/include/otbPCAModel.h +++ b/Modules/Learning/DimensionalityReductionLearning/include/otbPCAModel.h @@ -79,6 +79,9 @@ public: typedef typename Superclass::ConfidenceSampleType ConfidenceSampleType; typedef typename Superclass::ConfidenceListSampleType ConfidenceListSampleType; + typedef typename Superclass::ProbaSampleType ProbaSampleType; + typedef typename Superclass::ProbaListSampleType ProbaListSampleType; + itkNewMacro(Self); itkTypeMacro(PCAModel, DimensionalityReductionModel); @@ -101,14 +104,16 @@ protected: virtual TargetSampleType DoPredict( const InputSampleType& input, - ConfidenceValueType * quality = nullptr) const override; + ConfidenceValueType * quality = nullptr, + ProbaSampleType * proba = nullptr) const override; virtual void DoPredictBatch( const InputListSampleType *, const unsigned int & startIndex, const unsigned int & size, TargetListSampleType *, - ConfidenceListSampleType * quality = nullptr) const override; + ConfidenceListSampleType * quality = nullptr, + ProbaListSampleType* proba = nullptr) const override; private: shark::LinearModel<> m_Encoder; diff --git a/Modules/Learning/DimensionalityReductionLearning/include/otbPCAModel.hxx b/Modules/Learning/DimensionalityReductionLearning/include/otbPCAModel.hxx index 85601662729a23d931b2b5d841494b7633b8728a..9c6973367242ec77ecad2240a215dabaee36369f 100644 --- a/Modules/Learning/DimensionalityReductionLearning/include/otbPCAModel.hxx +++ b/Modules/Learning/DimensionalityReductionLearning/include/otbPCAModel.hxx @@ -148,7 +148,7 @@ PCAModel<TInputValue>::Load(const std::string & filename, const std::string & /* template <class TInputValue> typename PCAModel<TInputValue>::TargetSampleType -PCAModel<TInputValue>::DoPredict(const InputSampleType & value, ConfidenceValueType * /*quality*/) const +PCAModel<TInputValue>::DoPredict(const InputSampleType & value, ConfidenceValueType * /*quality*/, ProbaSampleType * /*proba*/) const { shark::RealVector samples(value.Size()); for(size_t i = 0; i < value.Size();i++) @@ -173,7 +173,7 @@ PCAModel<TInputValue>::DoPredict(const InputSampleType & value, ConfidenceValueT template <class TInputValue> void PCAModel<TInputValue> -::DoPredictBatch(const InputListSampleType *input, const unsigned int & startIndex, const unsigned int & size, TargetListSampleType * targets, ConfidenceListSampleType * /*quality*/) const +::DoPredictBatch(const InputListSampleType *input, const unsigned int & startIndex, const unsigned int & size, TargetListSampleType * targets, ConfidenceListSampleType * /*quality*/,ProbaListSampleType * /*proba*/) const { std::vector<shark::RealVector> features; Shark::ListSampleRangeToSharkVector(input, features,startIndex,size); diff --git a/Modules/Learning/DimensionalityReductionLearning/include/otbSOMModel.h b/Modules/Learning/DimensionalityReductionLearning/include/otbSOMModel.h index 11c5fe592a7b56ca04a6ca81c55edfdfb4ec0f7e..304fdac23d293d8e7d3275ab9f76e9e921875955 100644 --- a/Modules/Learning/DimensionalityReductionLearning/include/otbSOMModel.h +++ b/Modules/Learning/DimensionalityReductionLearning/include/otbSOMModel.h @@ -64,7 +64,8 @@ public: typedef typename Superclass::ConfidenceValueType ConfidenceValueType; typedef typename Superclass::ConfidenceSampleType ConfidenceSampleType; typedef typename Superclass::ConfidenceListSampleType ConfidenceListSampleType; - + typedef typename Superclass::ProbaSampleType ProbaSampleType; + typedef typename Superclass::ProbaListSampleType ProbaListSampleType; typedef SOMMap< itk::VariableLengthVector<TInputValue>, itk::Statistics::EuclideanDistanceMetric< @@ -118,7 +119,8 @@ private: virtual TargetSampleType DoPredict( const InputSampleType& input, - ConfidenceValueType * quality = nullptr) const override; + ConfidenceValueType * quality = nullptr, + ProbaSampleType * proba = nullptr) const override; /** Map size (width, height) */ SizeType m_MapSize; diff --git a/Modules/Learning/DimensionalityReductionLearning/include/otbSOMModel.hxx b/Modules/Learning/DimensionalityReductionLearning/include/otbSOMModel.hxx index 2c2abca261bb0533745eaf55fad822f9d9397f03..a2f93184f4ae05f42fe8205355ec0863121a9ab7 100644 --- a/Modules/Learning/DimensionalityReductionLearning/include/otbSOMModel.hxx +++ b/Modules/Learning/DimensionalityReductionLearning/include/otbSOMModel.hxx @@ -212,7 +212,8 @@ template <class TInputValue, unsigned int MapDimension> typename SOMModel<TInputValue, MapDimension>::TargetSampleType SOMModel<TInputValue, MapDimension>::DoPredict( const InputSampleType & value, - ConfidenceValueType * /*quality*/) const + ConfidenceValueType * /*quality*/, + ProbaSampleType * /*proba*/) const { TargetSampleType target; target.SetSize(this->m_Dimension); diff --git a/Modules/Learning/LearningBase/include/otbImageClassificationFilter.h b/Modules/Learning/LearningBase/include/otbImageClassificationFilter.h index 4609ce047de79e67fcb7a5e09a1174579ba172a0..2ff458e7d4ff5935631b676d00d4142a2756d76b 100644 --- a/Modules/Learning/LearningBase/include/otbImageClassificationFilter.h +++ b/Modules/Learning/LearningBase/include/otbImageClassificationFilter.h @@ -24,6 +24,7 @@ #include "itkImageToImageFilter.h" #include "otbMachineLearningModel.h" #include "otbImage.h" +#include "otbVectorImage.h" namespace otb { @@ -75,6 +76,11 @@ public: typedef otb::Image<double> ConfidenceImageType; typedef typename ConfidenceImageType::Pointer ConfidenceImagePointerType; + /**Output type for Proba */ + typedef otb::VectorImage<double> ProbaImageType; + + typedef typename ProbaImageType::Pointer ProbaImagePointerType; + typedef itk::VariableLengthVector<double> ProbaSampleType; /** Set/Get the model */ itkSetObjectMacro(Model, ModelType); itkGetObjectMacro(Model, ModelType); @@ -87,10 +93,16 @@ public: itkSetMacro(UseConfidenceMap, bool); itkGetMacro(UseConfidenceMap, bool); + /** Set/Get the proba map flag */ + itkSetMacro(UseProbaMap, bool); + itkGetMacro(UseProbaMap, bool); + itkSetMacro(BatchMode, bool); itkGetMacro(BatchMode, bool); itkBooleanMacro(BatchMode); + itkSetMacro(NumberOfClasses, unsigned int); + itkGetMacro(NumberOfClasses, unsigned int); /** * If set, only pixels within the mask will be classified. * All pixels with a value greater than 0 in the mask, will be classified. @@ -108,7 +120,7 @@ public: * Get the output confidence map */ ConfidenceImageType * GetOutputConfidence(void); - + ProbaImageType * GetOutputProba(void); protected: /** Constructor */ ImageClassificationFilter(); @@ -124,6 +136,12 @@ protected: /**PrintSelf method */ void PrintSelf(std::ostream& os, itk::Indent indent) const override; + void GenerateOutputInformation() override + { + Superclass::GenerateOutputInformation(); + // Define the number of output bands + this->GetOutputProba()->SetNumberOfComponentsPerPixel(m_NumberOfClasses); + } private: ImageClassificationFilter(const Self &) = delete; void operator =(const Self&) = delete; @@ -134,7 +152,9 @@ private: LabelType m_DefaultLabel; /** Flag to produce the confidence map (if the model supports it) */ bool m_UseConfidenceMap; + bool m_UseProbaMap; bool m_BatchMode; + unsigned int m_NumberOfClasses; }; } // End namespace otb #ifndef OTB_MANUAL_INSTANTIATION diff --git a/Modules/Learning/LearningBase/include/otbImageClassificationFilter.hxx b/Modules/Learning/LearningBase/include/otbImageClassificationFilter.hxx index fda4ab00349481e59c459257999737dd6b744b27..4aea60a2dade1cfa0a281d19573e8a6084da0918 100644 --- a/Modules/Learning/LearningBase/include/otbImageClassificationFilter.hxx +++ b/Modules/Learning/LearningBase/include/otbImageClassificationFilter.hxx @@ -38,11 +38,14 @@ ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage> this->SetNumberOfRequiredInputs(1); m_DefaultLabel = itk::NumericTraits<LabelType>::ZeroValue(); - this->SetNumberOfRequiredOutputs(2); + this->SetNumberOfRequiredOutputs(3); this->SetNthOutput(0,TOutputImage::New()); this->SetNthOutput(1,ConfidenceImageType::New()); + this->SetNthOutput(2,ProbaImageType::New()); m_UseConfidenceMap = false; + m_UseProbaMap = false; m_BatchMode = true; + m_NumberOfClasses = 1; } template <class TInputImage, class TOutputImage, class TMaskImage> @@ -79,6 +82,19 @@ ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage> return static_cast<ConfidenceImageType *>(this->itk::ProcessObject::GetOutput(1)); } +template <class TInputImage, class TOutputImage, class TMaskImage> +typename ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage> +::ProbaImageType * +ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage> +::GetOutputProba() +{ + if (this->GetNumberOfOutputs() < 2) + { + return nullptr; + } + return static_cast<ProbaImageType *>(this->itk::ProcessObject::GetOutput(2)); +} + template <class TInputImage, class TOutputImage, class TMaskImage> void ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage> @@ -100,22 +116,25 @@ ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage> template <class TInputImage, class TOutputImage, class TMaskImage> void ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage> -::ClassicThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId) +::ClassicThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, + itk::ThreadIdType threadId) { // Get the input pointers InputImageConstPointerType inputPtr = this->GetInput(); MaskImageConstPointerType inputMaskPtr = this->GetInputMask(); OutputImagePointerType outputPtr = this->GetOutput(); ConfidenceImagePointerType confidencePtr = this->GetOutputConfidence(); - + ProbaImagePointerType probaPtr = this->GetOutputProba(); // Progress reporting - itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels()); + itk::ProgressReporter progress(this, threadId, + outputRegionForThread.GetNumberOfPixels()); // Define iterators typedef itk::ImageRegionConstIterator<InputImageType> InputIteratorType; typedef itk::ImageRegionConstIterator<MaskImageType> MaskIteratorType; typedef itk::ImageRegionIterator<OutputImageType> OutputIteratorType; typedef itk::ImageRegionIterator<ConfidenceImageType> ConfidenceMapIteratorType; + typedef itk::ImageRegionIterator<ProbaImageType> ProbaMapIteratorType; InputIteratorType inIt(inputPtr, outputRegionForThread); OutputIteratorType outIt(outputPtr, outputRegionForThread); @@ -129,7 +148,8 @@ ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage> } // setup iterator for confidence map - bool computeConfidenceMap(m_UseConfidenceMap && m_Model->HasConfidenceIndex() && !m_Model->GetRegressionMode()); + bool computeConfidenceMap(m_UseConfidenceMap && m_Model->HasConfidenceIndex() && + !m_Model->GetRegressionMode()); ConfidenceMapIteratorType confidenceIt; if (computeConfidenceMap) { @@ -137,11 +157,25 @@ ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage> confidenceIt.GoToBegin(); } + // setup iterator for proba map + bool computeProbaMap(m_UseProbaMap && m_Model->HasProbaIndex() && + !m_Model->GetRegressionMode()); + + ProbaMapIteratorType probaIt; + + if(computeProbaMap) + { + probaIt = ProbaMapIteratorType(probaPtr,outputRegionForThread); + probaIt.GoToBegin(); + } + bool validPoint = true; double confidenceIndex = 0.0; - + ProbaSampleType probaVector{m_NumberOfClasses}; + probaVector.Fill(0); // Walk the part of the image - for (inIt.GoToBegin(), outIt.GoToBegin(); !inIt.IsAtEnd() && !outIt.IsAtEnd(); ++inIt, ++outIt) + for (inIt.GoToBegin(), outIt.GoToBegin(); !inIt.IsAtEnd() && !outIt.IsAtEnd(); + ++inIt, ++outIt) { // Check pixel validity if (inputMaskPtr) @@ -151,17 +185,22 @@ ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage> } // If point is valid if (validPoint) - { + { // Classifify - if (computeConfidenceMap) - { + if (computeProbaMap) + { + outIt.Set(m_Model->Predict(inIt.Get(),&confidenceIndex, + &probaVector)[0]); + } + else if (computeConfidenceMap) + { outIt.Set(m_Model->Predict(inIt.Get(),&confidenceIndex)[0]); - } + } else - { + { outIt.Set(m_Model->Predict(inIt.Get())[0]); - } } + } else { // else, set default value @@ -173,6 +212,11 @@ ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage> confidenceIt.Set(confidenceIndex); ++confidenceIt; } + if (computeProbaMap) + { + probaIt.Set(probaVector); + ++probaIt; + } progress.CompletedPixel(); } @@ -181,24 +225,31 @@ ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage> template <class TInputImage, class TOutputImage, class TMaskImage> void ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage> -::BatchThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId) +::BatchThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, + itk::ThreadIdType threadId) { - bool computeConfidenceMap(m_UseConfidenceMap && m_Model->HasConfidenceIndex() + bool computeConfidenceMap(m_UseConfidenceMap && m_Model->HasConfidenceIndex() && !m_Model->GetRegressionMode()); + + bool computeProbaMap(m_UseProbaMap && m_Model->HasProbaIndex() + && !m_Model->GetRegressionMode()); // Get the input pointers InputImageConstPointerType inputPtr = this->GetInput(); MaskImageConstPointerType inputMaskPtr = this->GetInputMask(); OutputImagePointerType outputPtr = this->GetOutput(); ConfidenceImagePointerType confidencePtr = this->GetOutputConfidence(); - + ProbaImagePointerType probaPtr = this->GetOutputProba(); + // Progress reporting - itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels()); + itk::ProgressReporter progress(this, threadId, + outputRegionForThread.GetNumberOfPixels()); // Define iterators typedef itk::ImageRegionConstIterator<InputImageType> InputIteratorType; typedef itk::ImageRegionConstIterator<MaskImageType> MaskIteratorType; typedef itk::ImageRegionIterator<OutputImageType> OutputIteratorType; typedef itk::ImageRegionIterator<ConfidenceImageType> ConfidenceMapIteratorType; + typedef itk::ImageRegionIterator<ProbaImageType> ProbaMapIteratorType; InputIteratorType inIt(inputPtr, outputRegionForThread); OutputIteratorType outIt(outputPtr, outputRegionForThread); @@ -210,16 +261,12 @@ ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage> maskIt.GoToBegin(); } - // typedef typename ModelType::InputValueType InputValueType; typedef typename ModelType::InputSampleType InputSampleType; typedef typename ModelType::InputListSampleType InputListSampleType; typedef typename ModelType::TargetValueType TargetValueType; - // typedef typename ModelType::TargetSampleType TargetSampleType; typedef typename ModelType::TargetListSampleType TargetListSampleType; - // typedef typename ModelType::ConfidenceValueType ConfidenceValueType; - // typedef typename ModelType::ConfidenceSampleType ConfidenceSampleType; typedef typename ModelType::ConfidenceListSampleType ConfidenceListSampleType; - + typedef typename ModelType::ProbaListSampleType ProbaListSampleType; typename InputListSampleType::Pointer samples = InputListSampleType::New(); unsigned int num_features = inputPtr->GetNumberOfComponentsPerPixel(); samples->SetMeasurementVectorSize(num_features); @@ -247,11 +294,14 @@ ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage> //Make the batch prediction typename TargetListSampleType::Pointer labels; typename ConfidenceListSampleType::Pointer confidences; + typename ProbaListSampleType::Pointer probas; if(computeConfidenceMap) confidences = ConfidenceListSampleType::New(); + if(computeProbaMap) + probas = ProbaListSampleType::New(); // This call is threadsafe - labels = m_Model->PredictBatch(samples,confidences); + labels = m_Model->PredictBatch(samples,confidences,probas); // Set the output values ConfidenceMapIteratorType confidenceIt; @@ -261,12 +311,19 @@ ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage> confidenceIt.GoToBegin(); } + ProbaMapIteratorType probaIt; + if (computeProbaMap) + { + probaIt = ProbaMapIteratorType(probaPtr,outputRegionForThread); + probaIt.GoToBegin(); + } typename TargetListSampleType::ConstIterator labIt = labels->Begin(); maskIt.GoToBegin(); for (outIt.GoToBegin(); !outIt.IsAtEnd(); ++outIt) { double confidenceIndex = 0.0; TargetValueType labelValue(m_DefaultLabel); + ProbaSampleType probaValues{m_NumberOfClasses}; if (inputMaskPtr) { validPoint = maskIt.Get() > 0; @@ -278,16 +335,26 @@ ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage> if(computeConfidenceMap) { - confidenceIndex = confidences->GetMeasurementVector(labIt.GetInstanceIdentifier())[0]; + confidenceIndex = + confidences->GetMeasurementVector(labIt.GetInstanceIdentifier())[0]; } - - ++labIt; + if(computeProbaMap) + { + //The probas may have different size than the m_NumberOfClasses set by the user + auto tempProbaValues = probas->GetMeasurementVector(labIt.GetInstanceIdentifier()); + for(unsigned int i=0; i<m_NumberOfClasses; ++i) + { + if(i<tempProbaValues.Size()) probaValues[i] = tempProbaValues[i]; + else probaValues[i] = 0; + } + } + ++labIt; } else { labelValue = m_DefaultLabel; } - + outIt.Set(labelValue); if(computeConfidenceMap) @@ -295,14 +362,20 @@ ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage> confidenceIt.Set(confidenceIndex); ++confidenceIt; } - + if(computeProbaMap) + { + probaIt.Set(probaValues); + ++probaIt; + } progress.CompletedPixel(); } } template <class TInputImage, class TOutputImage, class TMaskImage> void -ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage> -::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId) +ImageClassificationFilter<TInputImage, TOutputImage, + TMaskImage>::ThreadedGenerateData( + const OutputImageRegionType& outputRegionForThread, + itk::ThreadIdType threadId) { if(m_BatchMode) { diff --git a/Modules/Learning/LearningBase/include/otbMachineLearningModel.h b/Modules/Learning/LearningBase/include/otbMachineLearningModel.h index 01f522a4feccf6afbc246c7f61f5b14aa0e0cea5..9eb583e08477c14b30d7348256e578cff6aa4643 100644 --- a/Modules/Learning/LearningBase/include/otbMachineLearningModel.h +++ b/Modules/Learning/LearningBase/include/otbMachineLearningModel.h @@ -99,6 +99,9 @@ public: typedef typename MLMTargetTraits<TConfidenceValue>::SampleType ConfidenceSampleType; typedef itk::Statistics::ListSample<ConfidenceSampleType> ConfidenceListSampleType; + + typedef itk::VariableLengthVector<double> ProbaSampleType; + typedef itk::Statistics::ListSample<ProbaSampleType> ProbaListSampleType; /**\name Standard macros */ //@{ /** Run-time type information (and related methods). */ @@ -114,7 +117,7 @@ public: * quality value, or NULL * \return The predicted label */ - TargetSampleType Predict(const InputSampleType& input, ConfidenceValueType *quality = nullptr) const; + TargetSampleType Predict(const InputSampleType& input, ConfidenceValueType *quality = nullptr, ProbaSampleType *proba = nullptr) const; /**\name Set and get the dimension of the model for dimensionality reduction models */ //@{ @@ -130,7 +133,7 @@ public: * Note that this method will be multi-threaded if OTB is built * with OpenMP. */ - typename TargetListSampleType::Pointer PredictBatch(const InputListSampleType * input, ConfidenceListSampleType * quality = nullptr) const; + typename TargetListSampleType::Pointer PredictBatch(const InputListSampleType * input, ConfidenceListSampleType * quality = nullptr, ProbaListSampleType * proba = nullptr) const; /**\name Classification model file manipulation */ //@{ @@ -152,6 +155,8 @@ public: /** Query capacity to produce a confidence index */ bool HasConfidenceIndex() const {return m_ConfidenceIndex;} + /** Query capacity to produce probability values */ + bool HasProbaIndex() const {return m_ProbaIndex;} /**\name Input list of samples accessors */ //@{ @@ -208,6 +213,9 @@ protected: /** flag that tells if the model support confidence index output */ bool m_ConfidenceIndex; + /** flag that tells if the model support probability output */ + bool m_ProbaIndex; + /** Is DoPredictBatch multi-threaded ? */ bool m_IsDoPredictBatchMultiThreaded; @@ -230,7 +238,7 @@ private: * Also set m_IsDoPredictBatchMultiThreaded to true if internal * implementation allows for parallel batch prediction. */ - virtual void DoPredictBatch(const InputListSampleType * input, const unsigned int & startIndex, const unsigned int & size, TargetListSampleType * target, ConfidenceListSampleType * quality = nullptr) const; + virtual void DoPredictBatch(const InputListSampleType * input, const unsigned int & startIndex, const unsigned int & size, TargetListSampleType * target, ConfidenceListSampleType * quality = nullptr, ProbaListSampleType * proba = nullptr) const; /** Actual implementation of single sample prediction * \param input sample to predict @@ -238,7 +246,7 @@ private: * or NULL * \return The predicted label */ - virtual TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType * quality= nullptr) const = 0; + virtual TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType * quality= nullptr, ProbaSampleType *proba=nullptr) const = 0; MachineLearningModel(const Self &) = delete; void operator =(const Self&) = delete; diff --git a/Modules/Learning/LearningBase/include/otbMachineLearningModel.hxx b/Modules/Learning/LearningBase/include/otbMachineLearningModel.hxx index a2c353a89a90865d2510eeafba9a75de2c18ee3d..c2956a76627b21c21540bdb45259e50efcbd9182 100644 --- a/Modules/Learning/LearningBase/include/otbMachineLearningModel.hxx +++ b/Modules/Learning/LearningBase/include/otbMachineLearningModel.hxx @@ -38,6 +38,7 @@ MachineLearningModel<TInputValue,TOutputValue,TConfidenceValue> m_RegressionMode(false), m_IsRegressionSupported(false), m_ConfidenceIndex(false), + m_ProbaIndex(false), m_IsDoPredictBatchMultiThreaded(false), m_Dimension(0) {} @@ -68,10 +69,10 @@ template <class TInputValue, class TOutputValue, class TConfidenceValue> typename MachineLearningModel<TInputValue,TOutputValue,TConfidenceValue> ::TargetSampleType MachineLearningModel<TInputValue,TOutputValue,TConfidenceValue> -::Predict(const InputSampleType& input, ConfidenceValueType *quality) const +::Predict(const InputSampleType& input, ConfidenceValueType *quality, ProbaSampleType *proba) const { // Call protected specialization entry point - return this->DoPredict(input,quality); + return this->DoPredict(input,quality,proba); } @@ -79,8 +80,9 @@ template <class TInputValue, class TOutputValue, class TConfidenceValue> typename MachineLearningModel<TInputValue,TOutputValue,TConfidenceValue> ::TargetListSampleType::Pointer MachineLearningModel<TInputValue,TOutputValue,TConfidenceValue> -::PredictBatch(const InputListSampleType * input, ConfidenceListSampleType * quality) const +::PredictBatch(const InputListSampleType * input, ConfidenceListSampleType * quality, ProbaListSampleType *proba) const { + //std::cout << "Enter batch predict" << std::endl; typename TargetListSampleType::Pointer targets = TargetListSampleType::New(); targets->Resize(input->Size()); @@ -89,16 +91,19 @@ MachineLearningModel<TInputValue,TOutputValue,TConfidenceValue> quality->Clear(); quality->Resize(input->Size()); } - + if(proba!=ITK_NULLPTR) + { + proba->Clear(); + proba->Resize(input->Size()); + } if(m_IsDoPredictBatchMultiThreaded) { // Simply calls DoPredictBatch - this->DoPredictBatch(input,0,input->Size(),targets,quality); - return targets; + this->DoPredictBatch(input,0,input->Size(),targets,quality,proba); + return targets; } else { - #ifdef _OPENMP // OpenMP threading here unsigned int nb_threads(0), threadId(0), nb_batches(0); @@ -120,11 +125,11 @@ MachineLearningModel<TInputValue,TOutputValue,TConfidenceValue> batch_size+=input->Size()%nb_batches; } - this->DoPredictBatch(input,batch_start,batch_size,targets,quality); + this->DoPredictBatch(input,batch_start,batch_size,targets,quality,proba); } } #else - this->DoPredictBatch(input,0,input->Size(),targets,quality); + this->DoPredictBatch(input,0,input->Size(),targets,quality,proba); #endif return targets; } @@ -135,29 +140,42 @@ MachineLearningModel<TInputValue,TOutputValue,TConfidenceValue> template <class TInputValue, class TOutputValue, class TConfidenceValue> void MachineLearningModel<TInputValue,TOutputValue,TConfidenceValue> -::DoPredictBatch(const InputListSampleType * input, const unsigned int & startIndex, const unsigned int & size, TargetListSampleType * targets, ConfidenceListSampleType * quality) const + ::DoPredictBatch(const InputListSampleType * input, const unsigned int & startIndex, const unsigned int & size, TargetListSampleType * targets, ConfidenceListSampleType * quality, ProbaListSampleType * proba) const { assert(input != nullptr); assert(targets != nullptr); assert(input->Size()==targets->Size()&&"Input sample list and target label list do not have the same size."); assert(((quality==nullptr)||(quality->Size()==input->Size()))&&"Quality samples list is not null and does not have the same size as input samples list"); + assert((proba==nullptr)||(input->Size()==proba->Size())&&"Proba sample list and target label list do not have the same size."); if(startIndex+size>input->Size()) { itkExceptionMacro(<<"requested range ["<<startIndex<<", "<<startIndex+size<<"[ partially outside input sample list range.[0,"<<input->Size()<<"["); } - if(quality != nullptr) + if (proba != nullptr) { for(unsigned int id = startIndex;id<startIndex+size;++id) { + ProbaSampleType prob; ConfidenceValueType confidence = 0; - const TargetSampleType target = this->DoPredict(input->GetMeasurementVector(id),&confidence); + const TargetSampleType target = this->DoPredict(input->GetMeasurementVector(id),&confidence, &prob); quality->SetMeasurementVector(id,confidence); + proba->SetMeasurementVector(id,prob); targets->SetMeasurementVector(id,target); } } + else if(quality != ITK_NULLPTR) + { + for(unsigned int id = startIndex;id<startIndex+size;++id) + { + ConfidenceValueType confidence = 0; + const TargetSampleType target = this->DoPredict(input->GetMeasurementVector(id),&confidence); + quality->SetMeasurementVector(id,confidence); + targets->SetMeasurementVector(id,target); + } + } else { for(unsigned int id = startIndex;id<startIndex+size;++id) @@ -176,6 +194,6 @@ void // Call superclass implementation Superclass::PrintSelf(os,indent); } - } +} #endif diff --git a/Modules/Learning/Sampling/src/otbSampleAugmentationFilter.cxx b/Modules/Learning/Sampling/src/otbSampleAugmentationFilter.cxx index 5778de0d9324b7a022cab8569c3b25a48260cfc8..1ff5bb8043539fa4f45dc7c90f0f52535e86f1c3 100644 --- a/Modules/Learning/Sampling/src/otbSampleAugmentationFilter.cxx +++ b/Modules/Learning/Sampling/src/otbSampleAugmentationFilter.cxx @@ -247,7 +247,7 @@ SampleAugmentationFilter { OGRFieldType fieldType = feature.ogr().GetFieldDefnRef(idx)->GetType(); return (fieldType == OFTInteger - || ogr::version_proxy::IsOFTInteger64( fieldType ) + || fieldType == OFTInteger64 || fieldType == OFTReal); } diff --git a/Modules/Learning/Supervised/include/otbBoostMachineLearningModel.h b/Modules/Learning/Supervised/include/otbBoostMachineLearningModel.h index 6b61f1f03201d12caf6e0ba557129017de0fc32f..93fa4da45cd239d9a9f7deae5bbf942e40f53461 100644 --- a/Modules/Learning/Supervised/include/otbBoostMachineLearningModel.h +++ b/Modules/Learning/Supervised/include/otbBoostMachineLearningModel.h @@ -53,7 +53,7 @@ public: typedef typename Superclass::TargetSampleType TargetSampleType; typedef typename Superclass::TargetListSampleType TargetListSampleType; typedef typename Superclass::ConfidenceValueType ConfidenceValueType; - + typedef typename Superclass::ProbaSampleType ProbaSampleType; /** Run-time type information (and related methods). */ itkNewMacro(Self); itkTypeMacro(BoostMachineLearningModel, MachineLearningModel); @@ -124,8 +124,7 @@ protected: ~BoostMachineLearningModel() override; /** Predict values using the model */ - TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=nullptr) const override; - + TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=nullptr, ProbaSampleType *proba=nullptr) const override; /** PrintSelf method */ void PrintSelf(std::ostream& os, itk::Indent indent) const override; diff --git a/Modules/Learning/Supervised/include/otbBoostMachineLearningModel.hxx b/Modules/Learning/Supervised/include/otbBoostMachineLearningModel.hxx index 8112d51d6f338bb376d892507274cb1cc4ff847d..86421b3b4b01bc1fc2313d55d8a01b1debb27f21 100644 --- a/Modules/Learning/Supervised/include/otbBoostMachineLearningModel.hxx +++ b/Modules/Learning/Supervised/include/otbBoostMachineLearningModel.hxx @@ -104,7 +104,7 @@ template <class TInputValue, class TOutputValue> typename BoostMachineLearningModel<TInputValue,TOutputValue> ::TargetSampleType BoostMachineLearningModel<TInputValue,TOutputValue> -::DoPredict(const InputSampleType & input, ConfidenceValueType *quality) const +::DoPredict(const InputSampleType & input, ConfidenceValueType *quality, ProbaSampleType *proba) const { TargetSampleType target; @@ -132,6 +132,8 @@ BoostMachineLearningModel<TInputValue,TOutputValue> #endif ); } + if (proba != nullptr && !this->m_ProbaIndex) + itkExceptionMacro("Probability per class not available for this classifier !"); target[0] = static_cast<TOutputValue>(result); return target; diff --git a/Modules/Learning/Supervised/include/otbCvRTreesWrapper.h b/Modules/Learning/Supervised/include/otbCvRTreesWrapper.h index 97d881371c0768bc1fb5b1584de8c79fe75d95f7..7d8c4ad6cb60570da4ff07759daa5b0112aacd27 100644 --- a/Modules/Learning/Supervised/include/otbCvRTreesWrapper.h +++ b/Modules/Learning/Supervised/include/otbCvRTreesWrapper.h @@ -65,7 +65,7 @@ public: float predict_margin(const cv::Mat& sample, const cv::Mat& missing = cv::Mat()) const; - + #ifdef OTB_OPENCV_3 #define OTB_CV_WRAP_PROPERTY(type,name) \ diff --git a/Modules/Learning/Supervised/include/otbDecisionTreeMachineLearningModel.h b/Modules/Learning/Supervised/include/otbDecisionTreeMachineLearningModel.h index b0940ce737a6ff649319537508f6d7b7334b1888..b90982f2b98ab0ae5d16d7c1976c7f2e93a7ef9d 100644 --- a/Modules/Learning/Supervised/include/otbDecisionTreeMachineLearningModel.h +++ b/Modules/Learning/Supervised/include/otbDecisionTreeMachineLearningModel.h @@ -53,7 +53,7 @@ public: typedef typename Superclass::TargetSampleType TargetSampleType; typedef typename Superclass::TargetListSampleType TargetListSampleType; typedef typename Superclass::ConfidenceValueType ConfidenceValueType; - + typedef typename Superclass::ProbaSampleType ProbaSampleType; /** Run-time type information (and related methods). */ itkNewMacro(Self); itkTypeMacro(DecisionTreeMachineLearningModel, MachineLearningModel); @@ -179,7 +179,7 @@ protected: ~DecisionTreeMachineLearningModel() override; /** Predict values using the model */ - TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=nullptr) const override; + TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=nullptr, ProbaSampleType *proba=nullptr) const override; /** PrintSelf method */ void PrintSelf(std::ostream& os, itk::Indent indent) const override; diff --git a/Modules/Learning/Supervised/include/otbDecisionTreeMachineLearningModel.hxx b/Modules/Learning/Supervised/include/otbDecisionTreeMachineLearningModel.hxx index 52255ac51e365c359177e5d8be2c4ebed4fef38c..b5a7b618eb6ebad88010dc642196bbb18e2835e2 100644 --- a/Modules/Learning/Supervised/include/otbDecisionTreeMachineLearningModel.hxx +++ b/Modules/Learning/Supervised/include/otbDecisionTreeMachineLearningModel.hxx @@ -117,7 +117,7 @@ template <class TInputValue, class TOutputValue> typename DecisionTreeMachineLearningModel<TInputValue,TOutputValue> ::TargetSampleType DecisionTreeMachineLearningModel<TInputValue,TOutputValue> -::DoPredict(const InputSampleType & input, ConfidenceValueType *quality) const +::DoPredict(const InputSampleType & input, ConfidenceValueType *quality, ProbaSampleType *proba) const { TargetSampleType target; @@ -140,8 +140,10 @@ DecisionTreeMachineLearningModel<TInputValue,TOutputValue> itkExceptionMacro("Confidence index not available for this classifier !"); } } + if (proba != nullptr && !this->m_ProbaIndex) + itkExceptionMacro("Probability per class not available for this classifier !"); - return target; +return target; } template <class TInputValue, class TOutputValue> diff --git a/Modules/Learning/Supervised/include/otbGradientBoostedTreeMachineLearningModel.h b/Modules/Learning/Supervised/include/otbGradientBoostedTreeMachineLearningModel.h index 3249ef81a9e2e22a8139db8b419c349c968b2155..15a8df438697b6bf5031eb73e1f3e4852f57af4d 100644 --- a/Modules/Learning/Supervised/include/otbGradientBoostedTreeMachineLearningModel.h +++ b/Modules/Learning/Supervised/include/otbGradientBoostedTreeMachineLearningModel.h @@ -51,7 +51,7 @@ public: typedef typename Superclass::TargetSampleType TargetSampleType; typedef typename Superclass::TargetListSampleType TargetListSampleType; typedef typename Superclass::ConfidenceValueType ConfidenceValueType; - + typedef typename Superclass::ProbaSampleType ProbaSampleType; /** Run-time type information (and related methods). */ itkNewMacro(Self); itkTypeMacro(GradientBoostedTreeMachineLearningModel, MachineLearningModel); @@ -130,8 +130,7 @@ protected: ~GradientBoostedTreeMachineLearningModel() override; /** Predict values using the model */ - TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=nullptr) const override; - + TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=nullptr, ProbaSampleType *proba=nullptr) const override; /** PrintSelf method */ void PrintSelf(std::ostream& os, itk::Indent indent) const override; diff --git a/Modules/Learning/Supervised/include/otbGradientBoostedTreeMachineLearningModel.hxx b/Modules/Learning/Supervised/include/otbGradientBoostedTreeMachineLearningModel.hxx index b40394593bddb97d055b420b311f0cd34fd1dda6..132dd7bc3d12530260a2cc8f0ec2328775a94cbf 100644 --- a/Modules/Learning/Supervised/include/otbGradientBoostedTreeMachineLearningModel.hxx +++ b/Modules/Learning/Supervised/include/otbGradientBoostedTreeMachineLearningModel.hxx @@ -83,7 +83,7 @@ template <class TInputValue, class TOutputValue> typename GradientBoostedTreeMachineLearningModel<TInputValue,TOutputValue> ::TargetSampleType GradientBoostedTreeMachineLearningModel<TInputValue,TOutputValue> -::DoPredict(const InputSampleType & input, ConfidenceValueType *quality) const +::DoPredict(const InputSampleType & input, ConfidenceValueType *quality, ProbaSampleType *proba) const { //convert listsample to Mat cv::Mat sample; @@ -103,6 +103,8 @@ GradientBoostedTreeMachineLearningModel<TInputValue,TOutputValue> itkExceptionMacro("Confidence index not available for this classifier !"); } } + if (proba != nullptr && !this->m_ProbaIndex) + itkExceptionMacro("Probability per class not available for this classifier !"); return target; } diff --git a/Modules/Learning/Supervised/include/otbKNearestNeighborsMachineLearningModel.h b/Modules/Learning/Supervised/include/otbKNearestNeighborsMachineLearningModel.h index fff1dd22567ed636752218d94d9c70cf992184ab..b9bceffb1c5c9f6a876a7047ce1d0dadec22f64d 100644 --- a/Modules/Learning/Supervised/include/otbKNearestNeighborsMachineLearningModel.h +++ b/Modules/Learning/Supervised/include/otbKNearestNeighborsMachineLearningModel.h @@ -53,7 +53,7 @@ public: typedef typename Superclass::TargetSampleType TargetSampleType; typedef typename Superclass::TargetListSampleType TargetListSampleType; typedef typename Superclass::ConfidenceValueType ConfidenceValueType; - + typedef typename Superclass::ProbaSampleType ProbaSampleType; /** Run-time type information (and related methods). */ itkNewMacro(Self); itkTypeMacro(KNearestNeighborsMachineLearningModel, MachineLearningModel); @@ -104,8 +104,7 @@ protected: ~KNearestNeighborsMachineLearningModel() override; /** Predict values using the model */ - TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=nullptr) const override; - + TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=nullptr, ProbaSampleType *proba=nullptr) const override; /** PrintSelf method */ void PrintSelf(std::ostream& os, itk::Indent indent) const override; diff --git a/Modules/Learning/Supervised/include/otbKNearestNeighborsMachineLearningModel.hxx b/Modules/Learning/Supervised/include/otbKNearestNeighborsMachineLearningModel.hxx index 230bd44357d3e52dd82a6598dd1893a3abd901ac..2d12cceb360808be01a6a2579b7b6ed58422d0bd 100644 --- a/Modules/Learning/Supervised/include/otbKNearestNeighborsMachineLearningModel.hxx +++ b/Modules/Learning/Supervised/include/otbKNearestNeighborsMachineLearningModel.hxx @@ -106,7 +106,7 @@ template <class TInputValue, class TTargetValue> typename KNearestNeighborsMachineLearningModel<TInputValue,TTargetValue> ::TargetSampleType KNearestNeighborsMachineLearningModel<TInputValue,TTargetValue> -::DoPredict(const InputSampleType & input, ConfidenceValueType *quality) const +::DoPredict(const InputSampleType & input, ConfidenceValueType *quality, ProbaSampleType *proba) const { TargetSampleType target; @@ -135,6 +135,8 @@ KNearestNeighborsMachineLearningModel<TInputValue,TTargetValue> } (*quality) = static_cast<ConfidenceValueType>(accuracy); } + if (proba != nullptr && !this->m_ProbaIndex) + itkExceptionMacro("Probability per class not available for this classifier !"); // Decision rule : // VOTING is OpenCV default behaviour for classification diff --git a/Modules/Learning/Supervised/include/otbLibSVMMachineLearningModel.h b/Modules/Learning/Supervised/include/otbLibSVMMachineLearningModel.h index 1600b022bc545ace4446d523d865e2b376f79b19..da96ae0f47dc71c7648be456f39358ff119377e4 100644 --- a/Modules/Learning/Supervised/include/otbLibSVMMachineLearningModel.h +++ b/Modules/Learning/Supervised/include/otbLibSVMMachineLearningModel.h @@ -47,7 +47,7 @@ public: typedef typename Superclass::TargetSampleType TargetSampleType; typedef typename Superclass::TargetListSampleType TargetListSampleType; typedef typename Superclass::ConfidenceValueType ConfidenceValueType; - + typedef typename Superclass::ProbaSampleType ProbaSampleType; /** enum to choose the way confidence is computed * CM_INDEX : compute the difference between highest and second highest probability * CM_PROBA : returns probabilities for all classes @@ -272,7 +272,7 @@ protected: ~LibSVMMachineLearningModel() override; /** Predict values using the model */ - TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=nullptr) const override; + TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=nullptr, ProbaSampleType *proba=nullptr) const override; /** PrintSelf method */ void PrintSelf(std::ostream& os, itk::Indent indent) const override; diff --git a/Modules/Learning/Supervised/include/otbLibSVMMachineLearningModel.hxx b/Modules/Learning/Supervised/include/otbLibSVMMachineLearningModel.hxx index 5588ccbe7aa87ea58510da4a4dcbd423a1fd1f77..8435fecce363c43093cf3f37f9c3a1eaf48e80dc 100644 --- a/Modules/Learning/Supervised/include/otbLibSVMMachineLearningModel.hxx +++ b/Modules/Learning/Supervised/include/otbLibSVMMachineLearningModel.hxx @@ -107,7 +107,7 @@ template <class TInputValue, class TOutputValue> typename LibSVMMachineLearningModel<TInputValue,TOutputValue> ::TargetSampleType LibSVMMachineLearningModel<TInputValue,TOutputValue> -::DoPredict(const InputSampleType & input, ConfidenceValueType *quality) const +::DoPredict(const InputSampleType & input, ConfidenceValueType *quality, ProbaSampleType *proba) const { TargetSampleType target; target.Fill(0); @@ -129,6 +129,8 @@ LibSVMMachineLearningModel<TInputValue,TOutputValue> // terminate node x[input.Size()].index = -1; x[input.Size()].value = 0; + if (proba != nullptr && !this->m_ProbaIndex) + itkExceptionMacro("Probability per class not available for this classifier !"); if (quality != nullptr) { diff --git a/Modules/Learning/Supervised/include/otbNeuralNetworkMachineLearningModel.h b/Modules/Learning/Supervised/include/otbNeuralNetworkMachineLearningModel.h index 283b5ce015c53c3c9ac4e8d6c9d91d3c8668e2a0..f461a9e7d4d5f941706c0c234349cdf8881714ec 100644 --- a/Modules/Learning/Supervised/include/otbNeuralNetworkMachineLearningModel.h +++ b/Modules/Learning/Supervised/include/otbNeuralNetworkMachineLearningModel.h @@ -48,7 +48,7 @@ public: typedef typename Superclass::TargetSampleType TargetSampleType; typedef typename Superclass::TargetListSampleType TargetListSampleType; typedef typename Superclass::ConfidenceValueType ConfidenceValueType; - + typedef typename Superclass::ProbaSampleType ProbaSampleType; typedef std::map<TargetValueType, unsigned int> MapOfLabelsType; /** Run-time type information (and related methods). */ @@ -178,7 +178,7 @@ protected: ~NeuralNetworkMachineLearningModel() override; /** Predict values using the model */ - TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=nullptr) const override; + TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=nullptr, ProbaSampleType *proba=nullptr) const override; void LabelsToMat(const TargetListSampleType * listSample, cv::Mat & output); diff --git a/Modules/Learning/Supervised/include/otbNeuralNetworkMachineLearningModel.hxx b/Modules/Learning/Supervised/include/otbNeuralNetworkMachineLearningModel.hxx index 2f807898aa660c52e88ac366808badeb12f6e667..1a54679b29e30bf567b37174120aebb294d76dd8 100644 --- a/Modules/Learning/Supervised/include/otbNeuralNetworkMachineLearningModel.hxx +++ b/Modules/Learning/Supervised/include/otbNeuralNetworkMachineLearningModel.hxx @@ -234,7 +234,7 @@ void NeuralNetworkMachineLearningModel<TInputValue, TOutputValue>::Train() template<class TInputValue, class TOutputValue> typename NeuralNetworkMachineLearningModel<TInputValue, TOutputValue>::TargetSampleType NeuralNetworkMachineLearningModel< - TInputValue, TOutputValue>::DoPredict(const InputSampleType & input, ConfidenceValueType *quality) const + TInputValue, TOutputValue>::DoPredict(const InputSampleType & input, ConfidenceValueType *quality, ProbaSampleType *proba) const { TargetSampleType target; //convert listsample to Mat @@ -282,6 +282,9 @@ typename NeuralNetworkMachineLearningModel<TInputValue, TOutputValue>::TargetSam { (*quality) = static_cast<ConfidenceValueType>(maxResponse) - static_cast<ConfidenceValueType>(secondResponse); } + if (proba != nullptr && !this->m_ProbaIndex) + itkExceptionMacro("Probability per class not available for this classifier !"); + return target; } diff --git a/Modules/Learning/Supervised/include/otbNormalBayesMachineLearningModel.h b/Modules/Learning/Supervised/include/otbNormalBayesMachineLearningModel.h index cb3da6e3025e279b47794c8ba48dca748c832e4d..6589f6c4c174f8afe16dce22194ecb0e23280a11 100644 --- a/Modules/Learning/Supervised/include/otbNormalBayesMachineLearningModel.h +++ b/Modules/Learning/Supervised/include/otbNormalBayesMachineLearningModel.h @@ -53,7 +53,7 @@ public: typedef typename Superclass::TargetSampleType TargetSampleType; typedef typename Superclass::TargetListSampleType TargetListSampleType; typedef typename Superclass::ConfidenceValueType ConfidenceValueType; - + typedef typename Superclass::ProbaSampleType ProbaSampleType; /** Run-time type information (and related methods). */ itkNewMacro(Self); itkTypeMacro(NormalBayesMachineLearningModel, MachineLearningModel); @@ -84,8 +84,7 @@ protected: ~NormalBayesMachineLearningModel() override; /** Predict values using the model */ - TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=nullptr) const override; - + TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=nullptr, ProbaSampleType *proba=nullptr) const override; /** PrintSelf method */ void PrintSelf(std::ostream& os, itk::Indent indent) const override; diff --git a/Modules/Learning/Supervised/include/otbNormalBayesMachineLearningModel.hxx b/Modules/Learning/Supervised/include/otbNormalBayesMachineLearningModel.hxx index 9e0ca05c8bec54e4a80765eea447ed37ba9a8768..1285d211e1c0a906c68d1a38acf1184fe91d8c0f 100644 --- a/Modules/Learning/Supervised/include/otbNormalBayesMachineLearningModel.hxx +++ b/Modules/Learning/Supervised/include/otbNormalBayesMachineLearningModel.hxx @@ -85,7 +85,7 @@ template <class TInputValue, class TOutputValue> typename NormalBayesMachineLearningModel<TInputValue,TOutputValue> ::TargetSampleType NormalBayesMachineLearningModel<TInputValue,TOutputValue> -::DoPredict(const InputSampleType & input, ConfidenceValueType *quality) const +::DoPredict(const InputSampleType & input, ConfidenceValueType *quality, ProbaSampleType *proba) const { TargetSampleType target; @@ -107,6 +107,9 @@ NormalBayesMachineLearningModel<TInputValue,TOutputValue> itkExceptionMacro("Confidence index not available for this classifier !"); } } + if (proba != nullptr && !this->m_ProbaIndex) + itkExceptionMacro("Probability per class not available for this classifier !"); + return target; } diff --git a/Modules/Learning/Supervised/include/otbRandomForestsMachineLearningModel.h b/Modules/Learning/Supervised/include/otbRandomForestsMachineLearningModel.h index 276e9ca3492d21db03d2872b38e4c80cc44002b9..adbade7db5d62c6d3aea1faf809461a01c5e751b 100644 --- a/Modules/Learning/Supervised/include/otbRandomForestsMachineLearningModel.h +++ b/Modules/Learning/Supervised/include/otbRandomForestsMachineLearningModel.h @@ -50,7 +50,7 @@ public: typedef typename Superclass::TargetSampleType TargetSampleType; typedef typename Superclass::TargetListSampleType TargetListSampleType; typedef typename Superclass::ConfidenceValueType ConfidenceValueType; - + typedef typename Superclass::ProbaSampleType ProbaSampleType; // Other typedef itk::VariableSizeMatrix<float> VariableImportanceMatrixType; @@ -137,8 +137,7 @@ protected: ~RandomForestsMachineLearningModel() override; /** Predict values using the model */ - TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=nullptr) const override; - + TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=nullptr, ProbaSampleType *proba=nullptr) const override; /** PrintSelf method */ void PrintSelf(std::ostream& os, itk::Indent indent) const override; diff --git a/Modules/Learning/Supervised/include/otbRandomForestsMachineLearningModel.hxx b/Modules/Learning/Supervised/include/otbRandomForestsMachineLearningModel.hxx index 10508ead57bb89d90b76cc5675731ce864e7786b..a78f668fcbff653f4016f5cdb7a98fa28760951d 100644 --- a/Modules/Learning/Supervised/include/otbRandomForestsMachineLearningModel.hxx +++ b/Modules/Learning/Supervised/include/otbRandomForestsMachineLearningModel.hxx @@ -50,6 +50,7 @@ RandomForestsMachineLearningModel<TInputValue,TOutputValue> m_ComputeMargin(false) { this->m_ConfidenceIndex = true; + this->m_ProbaIndex = false; this->m_IsRegressionSupported = true; } @@ -171,8 +172,9 @@ template <class TInputValue, class TOutputValue> typename RandomForestsMachineLearningModel<TInputValue,TOutputValue> ::TargetSampleType RandomForestsMachineLearningModel<TInputValue,TOutputValue> -::DoPredict(const InputSampleType & value, ConfidenceValueType *quality) const +::DoPredict(const InputSampleType & value, ConfidenceValueType *quality, ProbaSampleType *proba) const { + //std::cout << "Enter predict" << std::endl; TargetSampleType target; //convert listsample to Mat cv::Mat sample; @@ -190,6 +192,10 @@ RandomForestsMachineLearningModel<TInputValue,TOutputValue> else (*quality) = m_RFModel->predict_confidence(sample); } + + if (proba != nullptr && !this->m_ProbaIndex) + itkExceptionMacro("Probability per class not available for this classifier !"); + return target[0]; } diff --git a/Modules/Learning/Supervised/include/otbSVMMachineLearningModel.h b/Modules/Learning/Supervised/include/otbSVMMachineLearningModel.h index dca029a2c8cf2b2a09cea9eb3162a100e7cbbe64..6fcc923971388bcd04c13f21ee89560296d023f4 100644 --- a/Modules/Learning/Supervised/include/otbSVMMachineLearningModel.h +++ b/Modules/Learning/Supervised/include/otbSVMMachineLearningModel.h @@ -60,7 +60,7 @@ public: typedef typename Superclass::TargetSampleType TargetSampleType; typedef typename Superclass::TargetListSampleType TargetListSampleType; typedef typename Superclass::ConfidenceValueType ConfidenceValueType; - + typedef typename Superclass::ProbaSampleType ProbaSampleType; /** Run-time type information (and related methods). */ itkNewMacro(Self); itkTypeMacro(SVMMachineLearningModel, MachineLearningModel); @@ -141,8 +141,7 @@ protected: ~SVMMachineLearningModel() override; /** Predict values using the model */ - TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=nullptr) const override; - + TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=nullptr, ProbaSampleType *proba=nullptr) const override; /** PrintSelf method */ void PrintSelf(std::ostream& os, itk::Indent indent) const override; diff --git a/Modules/Learning/Supervised/include/otbSVMMachineLearningModel.hxx b/Modules/Learning/Supervised/include/otbSVMMachineLearningModel.hxx index a52163ddee88a537e23fb2be5bb1244f34cee585..dc8d55dcddc2d04981b55fac4eabfc05418b0559 100644 --- a/Modules/Learning/Supervised/include/otbSVMMachineLearningModel.hxx +++ b/Modules/Learning/Supervised/include/otbSVMMachineLearningModel.hxx @@ -174,7 +174,7 @@ template <class TInputValue, class TOutputValue> typename SVMMachineLearningModel<TInputValue,TOutputValue> ::TargetSampleType SVMMachineLearningModel<TInputValue,TOutputValue> -::DoPredict(const InputSampleType & input, ConfidenceValueType *quality) const +::DoPredict(const InputSampleType & input, ConfidenceValueType *quality, ProbaSampleType *proba) const { TargetSampleType target; //convert listsample to Mat @@ -198,7 +198,10 @@ SVMMachineLearningModel<TInputValue,TOutputValue> (*quality) = m_SVMModel->predict(sample,true); #endif } - return target; + if (proba != nullptr && !this->m_ProbaIndex) + itkExceptionMacro("Probability per class not available for this classifier !"); + +return target; } template <class TInputValue, class TOutputValue> diff --git a/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModel.h b/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModel.h index 836afb8411431d4633d2c0b997391ac477866c37..b80fc244f0448ca0729cfcd0ed491ab0c107b9cb 100644 --- a/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModel.h +++ b/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModel.h @@ -86,7 +86,8 @@ public: typedef typename Superclass::ConfidenceValueType ConfidenceValueType; typedef typename Superclass::ConfidenceSampleType ConfidenceSampleType; typedef typename Superclass::ConfidenceListSampleType ConfidenceListSampleType; - + typedef typename Superclass::ProbaSampleType ProbaSampleType; + typedef typename Superclass::ProbaListSampleType ProbaListSampleType; /** Run-time type information (and related methods). */ itkNewMacro(Self); itkTypeMacro(SharkRandomForestsMachineLearningModel, MachineLearningModel); @@ -155,10 +156,9 @@ protected: virtual ~SharkRandomForestsMachineLearningModel(); /** Predict values using the model */ - virtual TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=nullptr) const override; - + TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=nullptr, ProbaSampleType *proba=nullptr) const override; - virtual void DoPredictBatch(const InputListSampleType *, const unsigned int & startIndex, const unsigned int & size, TargetListSampleType *, ConfidenceListSampleType * = nullptr) const override; + void DoPredictBatch(const InputListSampleType *, const unsigned int & startIndex, const unsigned int & size, TargetListSampleType *, ConfidenceListSampleType * = nullptr, ProbaListSampleType * = nullptr) const override; /** PrintSelf method */ void PrintSelf(std::ostream& os, itk::Indent indent) const override; diff --git a/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModel.hxx b/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModel.hxx index 35dd418ed62b4f6efc5564c4fc69497dd73d000a..5f7726938e1993bfc1e9beaf007a133f34430082 100644 --- a/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModel.hxx +++ b/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModel.hxx @@ -49,6 +49,7 @@ SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue> ::SharkRandomForestsMachineLearningModel() { this->m_ConfidenceIndex = true; + this->m_ProbaIndex = true; this->m_IsRegressionSupported = false; this->m_IsDoPredictBatchMultiThreaded = true; this->m_NormalizeClassLabels = true; @@ -120,20 +121,32 @@ template <class TInputValue, class TOutputValue> typename SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue> ::TargetSampleType SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue> -::DoPredict(const InputSampleType & value, ConfidenceValueType *quality) const +::DoPredict(const InputSampleType & value, ConfidenceValueType *quality, ProbaSampleType *proba) const { shark::RealVector samples(value.Size()); for(size_t i = 0; i < value.Size();i++) { samples.push_back(value[i]); } - if (quality != nullptr) - { + if (quality != nullptr || proba != nullptr) + { shark::RealVector probas = m_RFModel.decisionFunction()(samples); - (*quality) = ComputeConfidence(probas, m_ComputeMargin); + if (quality != nullptr) + { + (*quality) = ComputeConfidence(probas, m_ComputeMargin); + } + if (proba != nullptr) + { + for(size_t i =0; i< probas.size();i++) + { + //probas contain the N class probability indexed between 0 and N-1 + (*proba)[i] = static_cast<unsigned int>(probas[i]*1000); + } } + } unsigned int res{0}; m_RFModel.eval(samples, res); + TargetSampleType target; if(m_NormalizeClassLabels) { @@ -149,14 +162,15 @@ SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue> template <class TInputValue, class TOutputValue> void SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue> -::DoPredictBatch(const InputListSampleType *input, const unsigned int & startIndex, const unsigned int & size, TargetListSampleType * targets, ConfidenceListSampleType * quality) const +::DoPredictBatch(const InputListSampleType *input, const unsigned int & startIndex, const unsigned int & size, TargetListSampleType * targets, ConfidenceListSampleType * quality, ProbaListSampleType * proba) const { assert(input != nullptr); assert(targets != nullptr); assert(input->Size()==targets->Size()&&"Input sample list and target label list do not have the same size."); assert(((quality==nullptr)||(quality->Size()==input->Size()))&&"Quality samples list is not null and does not have the same size as input samples list"); - + assert((proba==nullptr)||(input->Size()==proba->Size())&&"Proba sample list and target label list do not have the same size."); + if(startIndex+size>input->Size()) { itkExceptionMacro(<<"requested range ["<<startIndex<<", "<<startIndex+size<<"[ partially outside input sample list range.[0,"<<input->Size()<<"["); @@ -168,11 +182,27 @@ SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue> #ifdef _OPENMP omp_set_num_threads(itk::MultiThreader::GetGlobalDefaultNumberOfThreads()); -#endif - + + #endif + if( proba !=nullptr || quality != nullptr) + { + shark::Data<shark::RealVector> probas = m_RFModel.decisionFunction()(inputSamples); + if( proba !=nullptr) + { + unsigned int id = startIndex; + for(shark::RealVector && p : probas.elements()) + { + ProbaSampleType prob{(unsigned int)p.size()}; + for(size_t i =0; i< p.size();i++) + { + prob[i] =p[i]*1000; + } + proba->SetMeasurementVector(id,prob); + ++id; + } + } if(quality != nullptr) { - shark::Data<shark::RealVector> probas = m_RFModel.decisionFunction()(inputSamples); unsigned int id = startIndex; for(shark::RealVector && p : probas.elements()) { @@ -183,7 +213,8 @@ SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue> ++id; } } - + } + auto prediction = m_RFModel(inputSamples); unsigned int id = startIndex; for(const auto& p : prediction.elements()) diff --git a/Modules/Learning/Supervised/src/otbCvRTreesWrapper.cxx b/Modules/Learning/Supervised/src/otbCvRTreesWrapper.cxx index ddc3a821d8f3bb1b9aae69c2559f9b8af543dad1..7c62782107bd4b82a064e3bafc47e1bbcecad97a 100644 --- a/Modules/Learning/Supervised/src/otbCvRTreesWrapper.cxx +++ b/Modules/Learning/Supervised/src/otbCvRTreesWrapper.cxx @@ -140,7 +140,7 @@ float CvRTreesWrapper::predict_confidence(const cv::Mat& sample, float confidence = static_cast<float>(max_votes)/ntrees; return confidence; } - + #ifdef OTB_OPENCV_3 #define OTB_CV_WRAP_IMPL(type,name) \ type CvRTreesWrapper::get##name() const \ diff --git a/Modules/Learning/Supervised/test/otbSharkImageClassificationFilter.cxx b/Modules/Learning/Supervised/test/otbSharkImageClassificationFilter.cxx index 1753b05b36bcb3e96393a485707a7068e7725ee1..010781f1d25ec99c14e4f3468075344f57406057 100644 --- a/Modules/Learning/Supervised/test/otbSharkImageClassificationFilter.cxx +++ b/Modules/Learning/Supervised/test/otbSharkImageClassificationFilter.cxx @@ -100,16 +100,18 @@ void buildModel(unsigned int num_classes, unsigned int num_samples, int otbSharkImageClassificationFilter(int argc, char * argv[]) { - if(argc<5 || argc>7) + if(argc<6 || argc>8) { - std::cout << "Usage: input_image output_image output_confidence batchmode [in_model_name] [mask_name]\n"; + std::cout << "Usage: input_image output_image output_confidence output_proba batchmode [in_model_name] [mask_name]\n"; } std::string imfname = argv[1]; std::string outfname = argv[2]; std::string conffname = argv[3]; - bool batch = (std::string(argv[4])=="1"); + std::string probafname = argv[4]; + bool batch = (std::string(argv[5])=="1"); std::string modelfname = "/tmp/rf_model.txt"; std::string maskfname{}; + int num_classes = 3; MaskReaderType::Pointer mask_reader = MaskReaderType::New(); ReaderType::Pointer reader = ReaderType::New(); @@ -120,13 +122,15 @@ int otbSharkImageClassificationFilter(int argc, char * argv[]) std::cout << "Image has " << num_features << " bands\n"; - if(argc>5) + if(argc>6) { - modelfname = argv[5]; + modelfname = argv[6]; + // We don't know the number of classes, so we set it to a high number + num_classes = 10; } else { - buildModel(3, 1000, num_features, modelfname); + buildModel(num_classes, 1000, num_features, modelfname); } ClassificationFilterType::Pointer filter = ClassificationFilterType::New(); @@ -135,9 +139,10 @@ int otbSharkImageClassificationFilter(int argc, char * argv[]) model->Load(modelfname); filter->SetModel(model); filter->SetInput(reader->GetOutput()); - if(argc==7) + filter->SetNumberOfClasses(num_classes); + if(argc==8) { - maskfname = argv[6]; + maskfname = argv[7]; mask_reader->SetFileName(maskfname); filter->SetInputMask(mask_reader->GetOutput()); } @@ -148,6 +153,7 @@ int otbSharkImageClassificationFilter(int argc, char * argv[]) std::cout << "Classification\n"; filter->SetBatchMode(batch); filter->SetUseConfidenceMap(true); + filter->SetUseProbaMap(true); using TimeT = std::chrono::milliseconds; auto start = std::chrono::system_clock::now(); writer->Update(); @@ -161,5 +167,35 @@ int otbSharkImageClassificationFilter(int argc, char * argv[]) confWriter->SetFileName(conffname); confWriter->Update(); + auto probaWriter = otb::ImageFileWriter<ClassificationFilterType::ProbaImageType>::New(); + probaWriter->SetInput(filter->GetOutputProba()); + probaWriter->SetFileName(probafname); + probaWriter->Update(); + + // Check that the chosen labels correspond to the max proba + + itk::ImageRegionConstIterator<LabeledImageType> labIt(filter->GetOutput(), + filter->GetOutput()->GetLargestPossibleRegion()); + itk::ImageRegionConstIterator<ClassificationFilterType::ProbaImageType> probIt(filter->GetOutputProba(), + filter->GetOutputProba()->GetLargestPossibleRegion()); + + for (labIt.GoToBegin(), probIt.GoToBegin(); !labIt.IsAtEnd(); + ++labIt, ++probIt) + { + if(labIt.Get()>0) //Pixel is not masked + { + auto first = probIt.Get().GetDataPointer(); + auto last = probIt.Get().GetDataPointer(); + std::advance(last, num_classes); + auto max_proba = std::distance(first, std::max_element(first, last)) + 1; + if(labIt.Get() != max_proba) + { + std::cout << "Chosen label " << labIt.Get() << " and max proba position " + << max_proba << " from " << probIt.Get() << " don't match\n"; + return EXIT_FAILURE; + } + } + } + return EXIT_SUCCESS; } diff --git a/Modules/Learning/Supervised/test/tests-shark.cmake b/Modules/Learning/Supervised/test/tests-shark.cmake index 87fbcbfc48077ea8fcbf0f07a6ea25b9da195e81..9c44f9eb23f428c88043aeb2cf8951373c33075b 100644 --- a/Modules/Learning/Supervised/test/tests-shark.cmake +++ b/Modules/Learning/Supervised/test/tests-shark.cmake @@ -46,6 +46,7 @@ otb_add_test(NAME leTvImageClassificationFilterSharkFast COMMAND otbSupervisedT ${INPUTDATA}/Classification/QB_1_ortho.tif ${TEMP}/leSharkImageClassificationFilterOutput.tif ${TEMP}/leSharkImageClassificationFilterConfidence.tif + ${TEMP}/leSharkImageClassificationFilterProba.tif 1 ${INPUTDATA}/Classification/otbSharkImageClassificationFilter_RFmodel.txt ) @@ -72,6 +73,7 @@ otb_add_test(NAME leTvImageClassificationFilterSharkFastMask COMMAND otbSupervi ${INPUTDATA}/Classification/QB_1_ortho.tif ${TEMP}/leSharkImageClassificationFilterWithMaskOutput.tif ${TEMP}/leSharkImageClassificationFilterWithMaskConfidence.tif + ${TEMP}/leSharkImageClassificationFilterWithMaskProba.tif 1 ${INPUTDATA}/Classification/otbSharkImageClassificationFilter_RFmodel.txt ${INPUTDATA}/Classification/QB_1_ortho_mask.tif diff --git a/Modules/Learning/Unsupervised/include/otbSharkKMeansMachineLearningModel.h b/Modules/Learning/Unsupervised/include/otbSharkKMeansMachineLearningModel.h index 05a408cd35b3c66fbdac66eefdc039b49ffe3d9e..873bb5e3578b2bdc4d1b0bc3c29a88563b9ef135 100644 --- a/Modules/Learning/Unsupervised/include/otbSharkKMeansMachineLearningModel.h +++ b/Modules/Learning/Unsupervised/include/otbSharkKMeansMachineLearningModel.h @@ -87,8 +87,8 @@ public: typedef typename Superclass::ConfidenceValueType ConfidenceValueType; typedef typename Superclass::ConfidenceSampleType ConfidenceSampleType; typedef typename Superclass::ConfidenceListSampleType ConfidenceListSampleType; - - + typedef typename Superclass::ProbaSampleType ProbaSampleType; + typedef typename Superclass::ProbaListSampleType ProbaListSampleType; typedef shark::HardClusteringModel<shark::RealVector> ClusteringModelType; typedef ClusteringModelType::OutputType ClusteringOutputType; @@ -137,11 +137,10 @@ protected: /** Predict values using the model */ virtual TargetSampleType - DoPredict(const InputSampleType &input, ConfidenceValueType *quality = nullptr) const override; - + DoPredict(const InputSampleType &input, ConfidenceValueType *quality = nullptr, ProbaSampleType *proba=nullptr) const override; virtual void DoPredictBatch(const InputListSampleType *, const unsigned int &startIndex, const unsigned int &size, - TargetListSampleType *, ConfidenceListSampleType * = nullptr) const override; + TargetListSampleType *, ConfidenceListSampleType * = nullptr, ProbaListSampleType * = nullptr) const override; template<typename DataType> DataType NormalizeData(const DataType &data) const; diff --git a/Modules/Learning/Unsupervised/include/otbSharkKMeansMachineLearningModel.hxx b/Modules/Learning/Unsupervised/include/otbSharkKMeansMachineLearningModel.hxx index 1cd01e13c47a7d1187251e46dbf4d83ac109a5b5..82f16e23d7d75b924623ca67753f37038ee98dce 100644 --- a/Modules/Learning/Unsupervised/include/otbSharkKMeansMachineLearningModel.hxx +++ b/Modules/Learning/Unsupervised/include/otbSharkKMeansMachineLearningModel.hxx @@ -102,7 +102,7 @@ template<class TInputValue, class TOutputValue> typename SharkKMeansMachineLearningModel<TInputValue, TOutputValue> ::TargetSampleType SharkKMeansMachineLearningModel<TInputValue, TOutputValue> -::DoPredict(const InputSampleType &value, ConfidenceValueType *quality) const +::DoPredict(const InputSampleType &value, ConfidenceValueType *quality, ProbaSampleType *proba) const { shark::RealVector data( value.Size()); for( size_t i = 0; i < value.Size(); i++ ) @@ -117,6 +117,13 @@ SharkKMeansMachineLearningModel<TInputValue, TOutputValue> ( *quality ) = ConfidenceValueType( 1.); } + if (proba != nullptr) + { + if (!this->m_ProbaIndex) + { + itkExceptionMacro("Probability per class not available for this classifier !"); + } + } TargetSampleType target; ClusteringOutputType predictedValue = (*m_ClusteringModel)( data ); target[0] = static_cast<TOutputValue>(predictedValue); @@ -130,7 +137,8 @@ SharkKMeansMachineLearningModel<TInputValue, TOutputValue> const unsigned int &startIndex, const unsigned int &size, TargetListSampleType *targets, - ConfidenceListSampleType *quality) const + ConfidenceListSampleType *quality, + ProbaListSampleType * proba) const { // Perform check on input values @@ -180,6 +188,10 @@ SharkKMeansMachineLearningModel<TInputValue, TOutputValue> quality->SetMeasurementVector( qid, static_cast<ConfidenceValueType>(1.) ); } } + if (proba !=nullptr && !this->m_ProbaIndex) + { + itkExceptionMacro("Probability per class not available for this classifier !"); + } } diff --git a/Modules/Radiometry/SARCalibration/include/otbSarBurstExtractionImageFilter.h b/Modules/Radiometry/SARCalibration/include/otbSarBurstExtractionImageFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..420870e469a40ad3516fb25131ce9f4c902abc9c --- /dev/null +++ b/Modules/Radiometry/SARCalibration/include/otbSarBurstExtractionImageFilter.h @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES) + * + * This file is part of Orfeo Toolbox + * + * https://www.orfeo-toolbox.org/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef otbSarBurstExtractionImageFilter_h +#define otbSarBurstExtractionImageFilter_h + +#include "itkImageToImageFilter.h" +#include "itkSmartPointer.h" + +namespace otb +{ +/** \class SarBurstExtractionImageFilter + * \brief Performs a burst extraction by keeping only lines and samples + * of a required Burst + * + * This filter performs a burst extraction by keeping only lines and samples + * of a required burst. This operation is useful when dealing with + * Sentinel1 IW SLC products, where each subswath is composed of + * several overlapping burst separated by black lines. The aim is to separate + * bursts to be able to process each burst independently. + * The output image represents only one burst and is smaller in azimuth and range + * direction than the input line. This filter is the perfect preprocessing step + * to process each burst of S1 IW SLC product with OTB without suffering from + * artifacts caused by bursts separation. + * + * Note that currently only Sentinel1 IW SLC products are supported. + * + * \ingroup OTBSARCalibration + */ + +template <class TImage> class ITK_EXPORT SarBurstExtractionImageFilter : + public itk::ImageToImageFilter<TImage,TImage> +{ +public: + // Standard class typedefs + typedef SarBurstExtractionImageFilter Self; + typedef itk::ImageToImageFilter<TImage,TImage> Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; + + itkNewMacro(Self); + itkTypeMacro(SarBurstExtractionImageFilter,ImageToImageFilter); + + typedef TImage ImageType; + typedef typename ImageType::RegionType RegionType; + typedef typename ImageType::PointType PointType; + + typedef std::pair<unsigned long, unsigned long> RecordType; + typedef std::vector<RecordType> LinesRecordVectorType; + + // Setter + itkSetMacro(BurstIndex, unsigned int); + itkSetMacro(AllPixels, bool); + +protected: + // Constructor + SarBurstExtractionImageFilter(); + + // Destructor + ~SarBurstExtractionImageFilter() override = default; + + // Needs to be re-implemented since size of output is modified + virtual void GenerateOutputInformation() override; + + // Needs to be re-implemented since size of output is modified + virtual void GenerateInputRequestedRegion() override; + + // Actual processing + virtual void ThreadedGenerateData(const RegionType& outputRegionForThread, itk::ThreadIdType threadId) override; + + RegionType OutputRegionToInputRegion(const RegionType& outputRegion) const; + +private: + SarBurstExtractionImageFilter(const Self&) = delete; + void operator=(const Self &) = delete; + + // Pair for sample valid selection + RecordType m_LinesRecord; + + // Pair for sample valid selection + RecordType m_SamplesRecord; + + // Burst index + unsigned int m_BurstIndex; + + // Mode for extraction : + // If true : all pixels of the burst are selected + // If false : only valid pixels are selected + bool m_AllPixels; +}; + +} // End namespace otb + +#ifndef OTB_MANUAL_INSTANTIATION +#include "otbSarBurstExtractionImageFilter.hxx" +#endif + + + +#endif diff --git a/Modules/Radiometry/SARCalibration/include/otbSarBurstExtractionImageFilter.hxx b/Modules/Radiometry/SARCalibration/include/otbSarBurstExtractionImageFilter.hxx new file mode 100644 index 0000000000000000000000000000000000000000..b4c7d2f5545dfab2ff06d46049643f2f82813319 --- /dev/null +++ b/Modules/Radiometry/SARCalibration/include/otbSarBurstExtractionImageFilter.hxx @@ -0,0 +1,243 @@ +/* + * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES) + * + * This file is part of Orfeo Toolbox + * + * https://www.orfeo-toolbox.org/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef otbSarBurstExtractionImageFilter_hxx +#define otbSarBurstExtractionImageFilter_hxx + +#include "otbSarBurstExtractionImageFilter.h" + +#include "otbSarSensorModelAdapter.h" +#include "otbImageKeywordlist.h" +#include "itkImageScanlineIterator.h" +#include "itkImageScanlineConstIterator.h" +#include "itkImageRegionIterator.h" +#include "itkImageRegionConstIterator.h" + +namespace otb +{ +// Constructor +template <class TImage> SarBurstExtractionImageFilter<TImage>::SarBurstExtractionImageFilter() + : m_LinesRecord(), m_SamplesRecord(), m_BurstIndex(0), m_AllPixels(false) +{} + +// Needs to be re-implemented since size of output is modified +template< class TImage> +void +SarBurstExtractionImageFilter<TImage>::GenerateOutputInformation() +{ + // Call superclass implementation + Superclass::GenerateOutputInformation(); + + // Retrieve the input image pointer + const ImageType * inputPtr = this->GetInput(); + ImageType * outputPtr = this->GetOutput(); + + // Check that azimuth spacing has not been modified + if(std::abs(inputPtr->GetSignedSpacing()[1]-1.)>=std::numeric_limits<double>::epsilon()) + itkExceptionMacro("Can not perform deburst if input image azimuth spacing is not 1."); + + // Check that the azimuth sampling grid has not been modified + if(std::abs(inputPtr->GetOrigin()[1]-static_cast<long>(inputPtr->GetOrigin()[1])-0.5)>=std::numeric_limits<double>::epsilon()) + itkExceptionMacro("Can not perform burst extraction if input image azimuth origin is not N.5"); + + // Retrieve input image keywordlist + ImageKeywordlist inputKwl = inputPtr->GetImageKeywordlist(); + + // Try to create a SarSensorModelAdapter + SarSensorModelAdapter::Pointer sarSensorModel = SarSensorModelAdapter::New(); + bool loadOk = sarSensorModel->LoadState(inputKwl); + + if(!loadOk || !sarSensorModel->IsValidSensorModel()) + itkExceptionMacro(<<"Input image does not contain a valid SAR sensor model."); + + // Try to call the burst extraction function + bool burstExtractionOk = sarSensorModel->BurstExtraction(m_BurstIndex, m_LinesRecord, m_SamplesRecord, + m_AllPixels); + + if(!burstExtractionOk) + itkExceptionMacro(<<"Could not etract Burst from input image"); + + // Compute the actual lines to remove + typename ImageType::RegionType largestPossibleRegion = this->GetInput()->GetLargestPossibleRegion(); + typename ImageType::PointType origin = this->GetInput()->GetOrigin(); + + // Export the new keywordlist + ImageKeywordlist newKwl; + + bool saveOk = sarSensorModel->SaveState(newKwl); + + if(!saveOk) + itkExceptionMacro(<<"Could not export deburst SAR sensor model to keyword list"); + + // Move origin and size (if necessary) + long originOffset_samples = static_cast<long>(this->GetInput()->GetOrigin()[0]-0.5); + long originOffset_lines = static_cast<long>(this->GetInput()->GetOrigin()[1]-0.5); + unsigned long outputOriginSample = 0; + unsigned long outputOriginLine = 0; + + typename ImageType::SizeType burstSize = largestPossibleRegion.GetSize(); + + if (static_cast<int>(m_SamplesRecord.first) > originOffset_samples) + { + outputOriginSample = 0; + } + else + { + outputOriginSample = originOffset_samples - static_cast<int>(m_SamplesRecord.first); + } + + if (static_cast<int>(m_LinesRecord.first) > originOffset_lines) + { + outputOriginLine = 0; + } + else + { + outputOriginLine = originOffset_lines - static_cast<int>(m_LinesRecord.first); + } + + long firstOutSample = static_cast<long>(std::max( static_cast<long>(m_SamplesRecord.first), originOffset_samples)); + long secondOutSample = static_cast<long>(std::min(static_cast<long>(m_SamplesRecord.second), + static_cast<long>(largestPossibleRegion.GetSize()[0] + + originOffset_samples - 1))); + + long firstOutLine = static_cast<long>(std::max(static_cast<long>(m_LinesRecord.first), originOffset_lines)); + long secondOutLine = static_cast<long>(std::min(static_cast<long>(m_LinesRecord.second), + static_cast<long>(largestPossibleRegion.GetSize()[1] + + originOffset_lines - 1))); + + burstSize[0] = secondOutSample - firstOutSample + 1; + burstSize[1] = secondOutLine - firstOutLine + 1; + + origin[0]=0.5+outputOriginSample; + origin[1]=0.5+outputOriginLine; + + outputPtr->SetOrigin(origin); + + // Set largest possible region + typename ImageType::RegionType outputLargestPossibleRegion = largestPossibleRegion; + largestPossibleRegion.SetSize(burstSize); + outputPtr->SetLargestPossibleRegion(largestPossibleRegion); + + newKwl.AddKey("support_data.number_samples", std::to_string(burstSize[0])); + newKwl.AddKey("support_data.number_lines", std::to_string(burstSize[1])); + + newKwl.AddKey("number_samples", std::to_string(burstSize[0])); + newKwl.AddKey("number_lines", std::to_string(burstSize[1])); + + // Set new keyword list to output image + outputPtr->SetImageKeywordList(newKwl); +} + +template<class TImage> +typename SarBurstExtractionImageFilter<TImage>::RegionType +SarBurstExtractionImageFilter<TImage>::OutputRegionToInputRegion(const RegionType& outputRegion) const +{ + RegionType inputRegion = outputRegion; + + typename RegionType::IndexType index = inputRegion.GetIndex(); + + long originOffset = static_cast<long>(this->GetInput()->GetOrigin()[1]-0.5); + long originOffset_samples = static_cast<long>(this->GetInput()->GetOrigin()[0]-0.5); + + if (static_cast<int>(m_SamplesRecord.first) > originOffset_samples) + { + index[0] += m_SamplesRecord.first - originOffset_samples; + } + if (static_cast<int>(m_LinesRecord.first) > originOffset) + { + index[1] += m_LinesRecord.first - originOffset; + } + + inputRegion.SetIndex(index); + + return inputRegion; +} + + +// Needs to be re-implemented since size of output is modified +template <class TImage> void SarBurstExtractionImageFilter<TImage>::GenerateInputRequestedRegion() +{ + RegionType outputRequestedRegion = this->GetOutput()->GetRequestedRegion(); + RegionType inputRequestedRegion = OutputRegionToInputRegion(outputRequestedRegion); + + ImageType * inputPtr = const_cast<ImageType *>(this->GetInput()); + + inputPtr->SetRequestedRegion(inputRequestedRegion); +} + + +// Actual processing +template <class TImage> +void +SarBurstExtractionImageFilter<TImage>::ThreadedGenerateData(const RegionType& outputRegionForThread, + itk::ThreadIdType itkNotUsed(threadId)) +{ + // Compute corresponding input region + RegionType inputRegionForThread = OutputRegionToInputRegion(outputRegionForThread); + + itk::ImageRegionConstIterator<ImageType> inputIt(this->GetInput(),inputRegionForThread); + itk::ImageRegionIterator<ImageType> outputIt(this->GetOutput(),outputRegionForThread); + + inputIt.GoToBegin(); + outputIt.GoToBegin(); + + int linesRecordFirst = static_cast<int>(m_LinesRecord.first); + int linesRecordSecond = static_cast<int>(m_LinesRecord.second); + int samplesRecordFirst = static_cast<int>(m_SamplesRecord.first); + int samplesRecordSecond = static_cast<int>(m_SamplesRecord.second); + + while(!inputIt.IsAtEnd()&&!outputIt.IsAtEnd()) + { + typename ImageType::IndexType currentInputIndex = inputIt.GetIndex(); + PointType currentInputPoint; + this->GetInput()->TransformIndexToPhysicalPoint(currentInputIndex,currentInputPoint); + + bool lineToKeep = false; + bool sampleToKeep = false; + + // Check lines + if (currentInputPoint[1]-0.5 >= linesRecordFirst && + currentInputPoint[1]-0.5 <= linesRecordSecond) + { + lineToKeep = true; + } + + // Check samples + if (currentInputPoint[0]-0.5 >= samplesRecordFirst && + currentInputPoint[0]-0.5 <= samplesRecordSecond) + { + sampleToKeep = true; + } + + // If ok, copy input pixel into output image + if(lineToKeep && sampleToKeep) + { + outputIt.Set(inputIt.Get()); + + ++outputIt; + } + + ++inputIt; + } +} + +} // End namespace otb + +#endif diff --git a/Modules/Radiometry/SARCalibration/include/otbSarConcatenateBurstsImageFilter.h b/Modules/Radiometry/SARCalibration/include/otbSarConcatenateBurstsImageFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..f7960a9b91d56f42a615f4fcac412231d8b33a48 --- /dev/null +++ b/Modules/Radiometry/SARCalibration/include/otbSarConcatenateBurstsImageFilter.h @@ -0,0 +1,115 @@ + /* + * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES) + * + * This file is part of Orfeo Toolbox + * + * https://www.orfeo-toolbox.org/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#ifndef otbSarConcatenateBurstsImageFilter_h +#define otbSarConcatenateBurstsImageFilter_h + +#include "itkImageToImageFilter.h" +#include "otbTileImageFilter.h" +#include "otbImageKeywordlist.h" + +namespace otb +{ +/** \class SarConcatenateBurstsImageFilter + * \brief This filter allows making a spatial mosaic from a set of bursts + * + * This filter derives from TileImagefilter and produces a spatial mosaic from a set of bursts + * from Sentinel-1 IW products . The layout parameter allows setting up of the images will + * be patched together: it is a 2D array containing the number of images in the horizontal + * direction and vertical direction respectively. + * + * Images can be set using the PushBackInput() or SetInput(unsigned + * int, Image *) methods. Please note that input images are supposed + * to be set in the lexicographical order. + * + * This filter does not support missing images: the number of input + * images must match exactly layout[0]*layout[1]. Additional + * consistency checks are that the number of components and spacing + * must be consistent for all images, and the size of the images must + * match with each others. + * + * Metadata are adapted in order to correspond to the contatenated SAR image. + * + * \ingroup OTBSARCalibration + * \ingroup MultiThreaded + * + * \ingroup OTBImageManipulation + */ +template <class TImage> +class ITK_EXPORT SarConcatenateBurstsImageFilter : + public TileImageFilter<TImage> +{ +public: + /** Standard class typedef */ + typedef SarConcatenateBurstsImageFilter Self; + typedef TileImageFilter<TImage> Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; + + /** Helper typedefs */ + typedef TImage ImageType; + typedef typename ImageType::Pointer ImagePointerType; + typedef typename ImageType::SizeType SizeType; + typedef typename ImageType::RegionType RegionType; + + typedef std::pair<unsigned long, unsigned long> RecordType; + typedef std::vector<RecordType> LinesRecordVectorType; + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(SarConcatenateBurstsImageFilter, TileImageFilter); + + // Setter + void SetSLCImageKeyWorList(ImageKeywordlist sarImageKWL); + + bool getDeburstLinesAndSamples(LinesRecordVectorType & linesRecord, LinesRecordVectorType & samplesRecord); + +protected: + /** Constructor */ + SarConcatenateBurstsImageFilter() = default; + + /** Destructor */ + ~SarConcatenateBurstsImageFilter() = default; + + /** Generate input requested region method */ + void GenerateOutputInformation() override; + + +private: + SarConcatenateBurstsImageFilter(const Self &) = delete; + void operator =(const Self&) = delete; + + // SLC KeywordList + ImageKeywordlist m_SLCImageKWL; + + // Deburst SLC KeywordList + ImageKeywordlist m_DeburstSLCImageKWL; +}; + +} // end namespace itk + +#ifndef OTB_MANUAL_INSTANTIATION +#include "otbSarConcatenateBurstsImageFilter.hxx" +#endif + +#endif diff --git a/Modules/Radiometry/SARCalibration/include/otbSarConcatenateBurstsImageFilter.hxx b/Modules/Radiometry/SARCalibration/include/otbSarConcatenateBurstsImageFilter.hxx new file mode 100644 index 0000000000000000000000000000000000000000..b88468459ea0b1af4f63caee7c6b32b0eefbc156 --- /dev/null +++ b/Modules/Radiometry/SARCalibration/include/otbSarConcatenateBurstsImageFilter.hxx @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES) + * + * This file is part of Orfeo Toolbox + * + * https://www.orfeo-toolbox.org/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef otbSarConcatenateBurstsImageFilter_hxx +#define otbSarConcatenateBurstsImageFilter_hxx + +#include "otbSarConcatenateBurstsImageFilter.h" +#include "itkImageRegionIterator.h" +#include "otbSarSensorModelAdapter.h" + +namespace otb +{ +template <class TImage> +void +SarConcatenateBurstsImageFilter<TImage> +::SetSLCImageKeyWorList(ImageKeywordlist sarImageKWL) +{ + m_SLCImageKWL = sarImageKWL; +} + +template <class TImage> +bool +SarConcatenateBurstsImageFilter<TImage> +::getDeburstLinesAndSamples(LinesRecordVectorType & linesRecord, LinesRecordVectorType & samplesRecord) +{ + // Try to create a SarSensorModelAdapter + SarSensorModelAdapter::Pointer sarSensorModel = SarSensorModelAdapter::New(); + + bool loadOk = sarSensorModel->LoadState(m_SLCImageKWL); + + if(!loadOk || !sarSensorModel->IsValidSensorModel()) + itkExceptionMacro(<<"Input image does not contain a valid SAR sensor model."); + + // Try to call the deburstAndConcatenate function + bool deburstAndConcatenateOk = sarSensorModel->DeburstAndConcatenate(linesRecord, samplesRecord); + + if(!deburstAndConcatenateOk) + itkExceptionMacro(<<"Could not deburst or concatenate from input bursts"); + + // Export the new keywordlist + bool saveOk = sarSensorModel->SaveState(m_DeburstSLCImageKWL); + + if(!saveOk) + itkExceptionMacro(<<"Could not export deburst SAR sensor model to keyword list"); + + return true; +} + +template <class TImage> +void +SarConcatenateBurstsImageFilter<TImage> +::GenerateOutputInformation() +{ + // First, call superclass implementation + Superclass::GenerateOutputInformation(); + + // Output KeywordList + ImageType * outputPtr = this->GetOutput(); + + m_DeburstSLCImageKWL.AddKey("support_data.number_samples", std::to_string(this->GetOutput()-> + GetLargestPossibleRegion(). + GetSize()[0])); + m_DeburstSLCImageKWL.AddKey("support_data.number_lines", std::to_string(this->GetOutput()-> + GetLargestPossibleRegion(). + GetSize()[1])); + + m_DeburstSLCImageKWL.AddKey("number_samples", std::to_string(this->GetOutput()-> + GetLargestPossibleRegion(). + GetSize()[0])); + m_DeburstSLCImageKWL.AddKey("number_lines", std::to_string(this->GetOutput()-> + GetLargestPossibleRegion(). + GetSize()[1])); + + // Set new keyword list to output image + outputPtr->SetImageKeywordList(m_DeburstSLCImageKWL); +} + + +} // end namepsace otb + +#endif diff --git a/Modules/Radiometry/SARCalibration/include/otbSarDeburstImageFilter.h b/Modules/Radiometry/SARCalibration/include/otbSarDeburstImageFilter.h index 6b771c9dbfa6052d49104cc93303a85d3572a800..5489259e10fd06dfdf67a5a0620c9f174a6c0527 100644 --- a/Modules/Radiometry/SARCalibration/include/otbSarDeburstImageFilter.h +++ b/Modules/Radiometry/SARCalibration/include/otbSarDeburstImageFilter.h @@ -62,8 +62,11 @@ public: typedef typename ImageType::RegionType RegionType; typedef typename ImageType::PointType PointType; - typedef std::pair<unsigned long, unsigned long> LinesRecordType; - typedef std::vector<LinesRecordType> LinesRecordVectorType; + typedef std::pair<unsigned long, unsigned long> RecordType; + typedef std::vector<RecordType> LinesRecordVectorType; + + // Setter + itkSetMacro(OnlyValidSample, bool); protected: // Constructor @@ -81,6 +84,9 @@ protected: // Actual processing virtual void ThreadedGenerateData(const RegionType& outputRegionForThread, itk::ThreadIdType threadId) override; + void ThreadedGenerateDataWithAllSamples(const RegionType& outputRegionForThread, itk::ThreadIdType threadId); + void ThreadedGenerateDataWithOnlyValidSamples(const RegionType& outputRegionForThread, itk::ThreadIdType threadId); + RegionType OutputRegionToInputRegion(const RegionType& outputRegion) const; private: @@ -89,7 +95,12 @@ private: // Vector of line records LinesRecordVectorType m_LinesRecord; - + + // Pair for sample valid selection + RecordType m_SamplesRecord; + + bool m_OnlyValidSample; + }; } // End namespace otb diff --git a/Modules/Radiometry/SARCalibration/include/otbSarDeburstImageFilter.hxx b/Modules/Radiometry/SARCalibration/include/otbSarDeburstImageFilter.hxx index d9de620dba6c6643f22426cb45f4ca74bed45232..c51edd2fb1714b65ec48892f611f46ec5dd6028a 100644 --- a/Modules/Radiometry/SARCalibration/include/otbSarDeburstImageFilter.hxx +++ b/Modules/Radiometry/SARCalibration/include/otbSarDeburstImageFilter.hxx @@ -27,12 +27,14 @@ #include "otbImageKeywordlist.h" #include "itkImageScanlineIterator.h" #include "itkImageScanlineConstIterator.h" +#include "itkImageRegionIterator.h" +#include "itkImageRegionConstIterator.h" namespace otb { // Constructor template <class TImage> SarDeburstImageFilter<TImage>::SarDeburstImageFilter() - : m_LinesRecord() + : m_LinesRecord(), m_SamplesRecord(), m_OnlyValidSample(false) {} // Needs to be re-implemented since size of output is modified @@ -66,7 +68,7 @@ SarDeburstImageFilter<TImage>::GenerateOutputInformation() itkExceptionMacro(<<"Input image does not contain a valid SAR sensor model."); // Try to call the deburst function - bool deburstOk = sarSensorModel->Deburst(m_LinesRecord); + bool deburstOk = sarSensorModel->Deburst(m_LinesRecord, m_SamplesRecord, m_OnlyValidSample); if(!deburstOk || m_LinesRecord.empty()) itkExceptionMacro(<<"Could not deburst SAR sensor model from input image"); @@ -83,9 +85,6 @@ SarDeburstImageFilter<TImage>::GenerateOutputInformation() if(!saveOk) itkExceptionMacro(<<"Could not export deburst SAR sensor model to keyword list"); - // Set new keyword list to output image - outputPtr->SetImageKeywordList(newKwl); - // Now, filter the LinesRecord so as to account for possible // extracts on input image long firstInputLine = static_cast<long>(origin[1]-0.5); @@ -97,7 +96,20 @@ SarDeburstImageFilter<TImage>::GenerateOutputInformation() unsigned long outputOriginLine = 0; SarSensorModelAdapter::ImageLineToDeburstLine(m_LinesRecord,firstInputLine,outputOriginLine); - // std::cout<<"OutputOriginLine: "<<outputOriginLine<<std::endl; + long originOffset_samples = static_cast<long>(this->GetInput()->GetOrigin()[0]-0.5); + unsigned long outputOriginSample = 0; + if (m_OnlyValidSample) + { + if (static_cast<int>(m_SamplesRecord.first) > originOffset_samples) + { + outputOriginSample = 0; + } + else + { + outputOriginSample = originOffset_samples - static_cast<int>(m_SamplesRecord.first); + } + origin[0]=0.5+outputOriginSample; + } origin[1]=0.5+outputOriginLine; outputPtr->SetOrigin(origin); @@ -111,9 +123,9 @@ SarDeburstImageFilter<TImage>::GenerateOutputInformation() // If record is inside input image region if((long)it->first<=lastInputLine && (long)it->second>=firstInputLine) { - LinesRecordType filteredRecord = *it; - filteredRecord.first = std::max((long)filteredRecord.first,firstInputLine); - filteredRecord.second = std::min((long)filteredRecord.second,lastInputLine); + RecordType filteredRecord = *it; + filteredRecord.first = std::max(static_cast<long>(filteredRecord.first),firstInputLine); + filteredRecord.second = std::min(static_cast<long>(filteredRecord.second),lastInputLine); filteredRecords.push_back(filteredRecord); } } @@ -123,6 +135,8 @@ SarDeburstImageFilter<TImage>::GenerateOutputInformation() // TODO: Ensure that records are sorted ? + + // Compute deburst azimuth size typename ImageType::SizeType deburstSize = largestPossibleRegion.GetSize(); deburstSize[1]=0; @@ -134,10 +148,28 @@ SarDeburstImageFilter<TImage>::GenerateOutputInformation() deburstSize[1]+=it->second-it->first+1; } + if (m_OnlyValidSample) + { + long minEnd = static_cast<long>(std::min(static_cast<long>(m_SamplesRecord.second), + static_cast<long>(largestPossibleRegion.GetSize()[0] + originOffset_samples-1))); + long maxStart = static_cast<long>(std::max(static_cast<long>(m_SamplesRecord.first), + originOffset_samples)); + deburstSize[0] = minEnd - maxStart + 1; + } + // Set largest possible region typename ImageType::RegionType outputLargestPossibleRegion = largestPossibleRegion; largestPossibleRegion.SetSize(deburstSize); outputPtr->SetLargestPossibleRegion(largestPossibleRegion); + + newKwl.AddKey("support_data.number_samples", std::to_string(deburstSize[0])); + newKwl.AddKey("support_data.number_lines", std::to_string(deburstSize[1])); + + newKwl.AddKey("number_samples", std::to_string(deburstSize[0])); + newKwl.AddKey("number_lines", std::to_string(deburstSize[1])); + + // Set new keyword list to output image + outputPtr->SetImageKeywordList(newKwl); } template<class TImage> @@ -163,6 +195,7 @@ SarDeburstImageFilter<TImage>::OutputRegionToInputRegion(const RegionType& outpu SarSensorModelAdapter::DeburstLineToImageLine(m_LinesRecord,lowerLeftLine,inputLowerLeftLine); long originOffset = static_cast<long>(this->GetInput()->GetOrigin()[1]-0.5); + long originOffset_samples = static_cast<long>(this->GetInput()->GetOrigin()[0]-0.5); inputUpperLeftLine-=originOffset; inputLowerLeftLine-=originOffset; @@ -171,6 +204,14 @@ SarDeburstImageFilter<TImage>::OutputRegionToInputRegion(const RegionType& outpu typename RegionType::SizeType size = inputRegion.GetSize(); typename RegionType::IndexType index = inputRegion.GetIndex(); + + if (m_OnlyValidSample) + { + if (static_cast<int>(m_SamplesRecord.first) > originOffset_samples) + { + index[0]+= m_SamplesRecord.first - originOffset_samples; + } + } index[1]=inputUpperLeftLine; size[1]=inputLowerLeftLine-inputUpperLeftLine+1; @@ -194,7 +235,26 @@ template <class TImage> void SarDeburstImageFilter<TImage>::GenerateInputRequest } // Actual processing -template <class TImage> void SarDeburstImageFilter<TImage>::ThreadedGenerateData(const RegionType& outputRegionForThread, itk::ThreadIdType itkNotUsed(threadId)) +template <class TImage> +void +SarDeburstImageFilter<TImage>::ThreadedGenerateData(const RegionType& outputRegionForThread, + itk::ThreadIdType itkNotUsed(threadId)) +{ + if (m_OnlyValidSample) + { + this->ThreadedGenerateDataWithOnlyValidSamples(outputRegionForThread, 0); + } + else + { + this->ThreadedGenerateDataWithAllSamples(outputRegionForThread, 0); + } +} + +// Actual processing with all samples +template <class TImage> +void +SarDeburstImageFilter<TImage>::ThreadedGenerateDataWithAllSamples(const RegionType& outputRegionForThread, + itk::ThreadIdType itkNotUsed(threadId)) { // Compute corresponding input region RegionType inputRegionForThread = OutputRegionToInputRegion(outputRegionForThread); @@ -213,25 +273,24 @@ template <class TImage> void SarDeburstImageFilter<TImage>::ThreadedGenerateData bool lineToKeep = false; - for(LinesRecordVectorType::const_iterator it = m_LinesRecord.begin(); - it!=m_LinesRecord.end();++it) - { - if(currentInputPoint[1]-0.5>=it->first && currentInputPoint[1]-0.5<=it->second) - { - lineToKeep = true; - break; - } - } + for (auto const& record : m_LinesRecord) + { + if (currentInputPoint[1]-0.5>=record.first && currentInputPoint[1]-0.5<=record.second) + { + lineToKeep = true; + break; + } + } if(lineToKeep) { - for(inputIt.GoToBeginOfLine(),outputIt.GoToBeginOfLine(); - !inputIt.IsAtEndOfLine() && !outputIt.IsAtEndOfLine(); - ++inputIt,++outputIt) - { - outputIt.Set(inputIt.Get()); - - } - outputIt.NextLine(); + for(inputIt.GoToBeginOfLine(),outputIt.GoToBeginOfLine(); + !inputIt.IsAtEndOfLine() && !outputIt.IsAtEndOfLine(); + ++inputIt,++outputIt) + { + outputIt.Set(inputIt.Get()); + + } + outputIt.NextLine(); } @@ -239,6 +298,58 @@ template <class TImage> void SarDeburstImageFilter<TImage>::ThreadedGenerateData } } +// Actual processing with only valid samples +template <class TImage> +void +SarDeburstImageFilter<TImage>::ThreadedGenerateDataWithOnlyValidSamples(const RegionType& outputRegionForThread, + itk::ThreadIdType itkNotUsed(threadId)) +{ + // Compute corresponding input region + RegionType inputRegionForThread = OutputRegionToInputRegion(outputRegionForThread); + + itk::ImageRegionConstIterator<ImageType> inputIt(this->GetInput(),inputRegionForThread); + itk::ImageRegionIterator<ImageType> outputIt(this->GetOutput(),outputRegionForThread); + + inputIt.GoToBegin(); + outputIt.GoToBegin(); + + while(!inputIt.IsAtEnd()&&!outputIt.IsAtEnd()) + { + typename ImageType::IndexType currentInputIndex = inputIt.GetIndex(); + PointType currentInputPoint; + this->GetInput()->TransformIndexToPhysicalPoint(currentInputIndex,currentInputPoint); + + bool lineToKeep = false; + bool sampleToKeep = false; + + for (auto const& record : m_LinesRecord) + { + if (currentInputPoint[1]-0.5>=record.first && currentInputPoint[1]-0.5<=record.second) + { + lineToKeep = true; + break; + } + } + + if (currentInputPoint[0]-0.5 >= static_cast<int>(m_SamplesRecord.first) && + currentInputPoint[1]-0.5 <= static_cast<int>(m_SamplesRecord.second)) + { + sampleToKeep = true; + } + + if(lineToKeep && sampleToKeep) + { + outputIt.Set(inputIt.Get()); + + ++outputIt; + } + + + ++inputIt; + } +} + + } // End namespace otb #endif diff --git a/Modules/Radiometry/SARCalibration/otb-module.cmake b/Modules/Radiometry/SARCalibration/otb-module.cmake index 54f896fe57f4c29e84534e292558d9025cfc7cd1..13eb2a48f5d24f0e1f3dc653f47ef2642d041e5a 100644 --- a/Modules/Radiometry/SARCalibration/otb-module.cmake +++ b/Modules/Radiometry/SARCalibration/otb-module.cmake @@ -27,6 +27,7 @@ otb_module(OTBSARCalibration OTBITK OTBMetadata OTBOSSIMAdapters + OTBImageManipulation TEST_DEPENDS OTBImageBase diff --git a/Modules/Radiometry/SARCalibration/test/CMakeLists.txt b/Modules/Radiometry/SARCalibration/test/CMakeLists.txt index 1c8f86f42639f2b3ffb247677b0ac42ad914323e..ae7b2bb8356bfc1a58de54394acefbd4ad9b1575 100644 --- a/Modules/Radiometry/SARCalibration/test/CMakeLists.txt +++ b/Modules/Radiometry/SARCalibration/test/CMakeLists.txt @@ -42,6 +42,7 @@ otbTerraSarBrightnessImageComplexFilterTest.cxx otbSarRadiometricCalibrationToImageFilterWithComplexPixelTest.cxx otbSarBrightnessToImageFilterTest.cxx otbSarDeburstFilterTest.cxx +otbSarBurstExtractionFilterTest.cxx ) add_executable(otbSARCalibrationTestDriver ${OTBSARCalibrationTests}) @@ -297,3 +298,39 @@ otb_add_test(NAME saTvSarDeburstImageFilterTest COMMAND otbSARCalibrationTestDri otbSarDeburstFilterTest ${INPUTDATA}/s1a-iw1-slc-vh-amp_xt.tif ${TEMP}/saTvSarDeburstImageFilterTestOutput.tif) + +otb_add_test(NAME saTvSarDeburstImageFilterTest2 COMMAND otbSARCalibrationTestDriver + --compare-image ${NOTOL} + ${BASELINE}/saTvSarDeburstImageFilterTest2Output.tif + ${TEMP}/saTvSarDeburstImageFilterTest2Output.tif + otbSarDeburstFilterTest + ${INPUTDATA}/s1a-iw1-slc-vv-20170111_Burst01_amp.tiff + ${TEMP}/saTvSarDeburstImageFilterTest2Output.tif) + +otb_add_test(NAME saTvSarDeburstImageFilterTest3 COMMAND otbSARCalibrationTestDriver + --compare-image ${NOTOL} + ${BASELINE}/saTvSarDeburstImageFilterTest3Output.tif + ${TEMP}/saTvSarDeburstImageFilterTest3Output.tif + otbSarDeburstFilterTest + ${INPUTDATA}/s1a-iw1-slc-vv-20170111_Burst01_amp.tiff + ${TEMP}/saTvSarDeburstImageFilterTest3Output.tif + WithOnlyValidSamples) + + +otb_add_test(NAME saTvSarBurstExtractionImageFilterTest1 COMMAND otbSARCalibrationTestDriver + --compare-image ${NOTOL} + ${BASELINE}/saTvSarBurstImageFilterTest1Output.tif + ${TEMP}/saTvSarBurstImageFilterTest1Output.tif + otbSarBurstExtractionFilterTest + ${INPUTDATA}/s1a-iw1-slc-vv-20170111_Burst01_amp.tiff + ${TEMP}/saTvSarBurstImageFilterTest1Output.tif + 0) + +otb_add_test(NAME saTvSarBurstExtractionImageFilterTest2 COMMAND otbSARCalibrationTestDriver + --compare-image ${NOTOL} + ${BASELINE}/saTvSarBurstImageFilterTest2Output.tif + ${TEMP}/saTvSarBurstImageFilterTest2Output.tif + otbSarBurstExtractionFilterTest + ${INPUTDATA}/s1a-iw1-slc-vv-20170111_Burst01_amp.tiff + ${TEMP}/saTvSarBurstImageFilterTest2Output.tif + 1) diff --git a/Modules/Radiometry/SARCalibration/test/otbSARCalibrationTestDriver.cxx b/Modules/Radiometry/SARCalibration/test/otbSARCalibrationTestDriver.cxx index 35733b76f1852d7435fcdf2c9f8d4a09dc7a4361..3438d9c62eaeda5ad791ba0a5e711bc953e4b416 100644 --- a/Modules/Radiometry/SARCalibration/test/otbSARCalibrationTestDriver.cxx +++ b/Modules/Radiometry/SARCalibration/test/otbSARCalibrationTestDriver.cxx @@ -42,4 +42,5 @@ void RegisterTests() REGISTER_TEST(otbSarRadiometricCalibrationToImageFilterWithComplexPixelTest); REGISTER_TEST(otbSarBrightnessToImageFilterTest); REGISTER_TEST(otbSarDeburstFilterTest); + REGISTER_TEST(otbSarBurstExtractionFilterTest); } diff --git a/Modules/Radiometry/SARCalibration/test/otbSarBurstExtractionFilterTest.cxx b/Modules/Radiometry/SARCalibration/test/otbSarBurstExtractionFilterTest.cxx new file mode 100644 index 0000000000000000000000000000000000000000..e0602f305e91da342a60b5e384258602cf542881 --- /dev/null +++ b/Modules/Radiometry/SARCalibration/test/otbSarBurstExtractionFilterTest.cxx @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES) + * + * This file is part of Orfeo Toolbox + * + * https://www.orfeo-toolbox.org/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "otbSarBurstExtractionImageFilter.h" +#include "otbImage.h" +#include "otbImageFileReader.h" +#include "otbImageFileWriter.h" + +typedef otb::Image<unsigned short> ImageType; +typedef otb::ImageFileReader<ImageType> ReaderType; +typedef otb::ImageFileWriter<ImageType> WriterType; +typedef otb::SarBurstExtractionImageFilter<ImageType> BurstExtractionFilterType; + +int otbSarBurstExtractionFilterTest(int itkNotUsed(argc), char * argv[]) +{ + ReaderType::Pointer reader = ReaderType::New(); + reader->SetFileName(argv[1]); + + BurstExtractionFilterType::Pointer filter = BurstExtractionFilterType::New(); + filter->SetInput(reader->GetOutput()); + filter->SetBurstIndex(std::stoi(argv[3])); + + WriterType::Pointer writer = WriterType::New(); + writer->SetInput(filter->GetOutput()); + writer->SetFileName(argv[2]); + writer->Update(); + + // check that there is now a single burst in data + reader = ReaderType::New(); + reader->SetFileName(argv[2]); + reader->UpdateOutputInformation(); + + unsigned int nb_bursts = atoi(reader->GetOutput()->GetImageKeywordlist().GetMetadataByKey("support_data.geom.bursts.number").c_str()); + + if(nb_bursts != 1) + { + std::cerr<<"Error: more than 1 burst ("<<nb_bursts<<" bursts) found in output metadata."<<std::endl; + } + else + { + std::cout<<"Metadata have a single burst as expected."<<std::endl; + } + + return EXIT_SUCCESS; +} + diff --git a/Modules/Radiometry/SARCalibration/test/otbSarDeburstFilterTest.cxx b/Modules/Radiometry/SARCalibration/test/otbSarDeburstFilterTest.cxx index d221088626f509462223f9cbbb93a6ce8d96c75a..deac69d67dfad7a7dc8b28a1126945dfe5676a7f 100644 --- a/Modules/Radiometry/SARCalibration/test/otbSarDeburstFilterTest.cxx +++ b/Modules/Radiometry/SARCalibration/test/otbSarDeburstFilterTest.cxx @@ -28,13 +28,20 @@ typedef otb::ImageFileReader<ImageType> ReaderType; typedef otb::ImageFileWriter<ImageType> WriterType; typedef otb::SarDeburstImageFilter<ImageType> DeburstFilterType; -int otbSarDeburstFilterTest(int itkNotUsed(argc), char * argv[]) +int otbSarDeburstFilterTest(int argc, char * argv[]) { ReaderType::Pointer reader = ReaderType::New(); reader->SetFileName(argv[1]); + bool onlyValidSamples = false; + if (argc == 4) + { + onlyValidSamples = true; + } + DeburstFilterType::Pointer filter = DeburstFilterType::New(); filter->SetInput(reader->GetOutput()); + filter->SetOnlyValidSample(onlyValidSamples); WriterType::Pointer writer = WriterType::New(); writer->SetInput(filter->GetOutput()); diff --git a/Modules/Remote/temporal-gapfilling.remote.cmake b/Modules/Remote/temporal-gapfilling.remote.cmake index 2dd788d21391a19390f40ac90ff3af1b5271311b..5d948a6ddaecceb5f4ff6a5324e463ec80030340 100644 --- a/Modules/Remote/temporal-gapfilling.remote.cmake +++ b/Modules/Remote/temporal-gapfilling.remote.cmake @@ -27,5 +27,5 @@ https://gitlab.orfeo-toolbox.org/jinglada/temporalgapfilling " GIT_REPOSITORY https://gitlab.orfeo-toolbox.org/jinglada/temporalgapfilling.git # Commit on develop branch which includes patches for Windows support - GIT_TAG 4fc4a71acf7b9b051cda5a3b950de2cdb9d26287 + GIT_TAG 9d97764f0411de1a32dd5e0a90bdcdd8adfa049f ) diff --git a/Modules/Segmentation/Conversion/include/otbRasterizeVectorDataFilter.h b/Modules/Segmentation/Conversion/include/otbRasterizeVectorDataFilter.h index d719606ae3492d9589f49fa15429bbb00b32d640..f7fbf00ff58fe49e17d28c672ad982426fb3badc 100644 --- a/Modules/Segmentation/Conversion/include/otbRasterizeVectorDataFilter.h +++ b/Modules/Segmentation/Conversion/include/otbRasterizeVectorDataFilter.h @@ -31,7 +31,6 @@ #include "gdal.h" #include "gdal_alg.h" #include "ogr_srs_api.h" -#include "otbOGRVersionProxy.h" namespace otb { @@ -148,7 +147,7 @@ protected: { if (m_OGRDataSourcePointer != nullptr) { - ogr::version_proxy::Close(m_OGRDataSourcePointer); + GDALClose(m_OGRDataSourcePointer); } } @@ -160,7 +159,7 @@ private: RasterizeVectorDataFilter(const Self&) = delete; void operator=(const Self&) = delete; - ogr::version_proxy::GDALDatasetType * m_OGRDataSourcePointer; + GDALDataset * m_OGRDataSourcePointer; // Vector Of LayersH std::vector< OGRLayerH > m_SrcDataSetLayers; diff --git a/Modules/Segmentation/Conversion/include/otbVectorDataToLabelImageFilter.h b/Modules/Segmentation/Conversion/include/otbVectorDataToLabelImageFilter.h index 6cdbabc3974e38da1993b092a130ea042879fffc..d67617fc170887bdc864770ba7655131c1e9f14e 100644 --- a/Modules/Segmentation/Conversion/include/otbVectorDataToLabelImageFilter.h +++ b/Modules/Segmentation/Conversion/include/otbVectorDataToLabelImageFilter.h @@ -29,7 +29,6 @@ #include "gdal.h" #include "ogr_api.h" -#include "otbOGRVersionProxy.h" #include <string> namespace otb { @@ -151,7 +150,7 @@ protected: if (m_OGRDataSourcePointer != nullptr) { - ogr::version_proxy::Close(m_OGRDataSourcePointer); + GDALClose(m_OGRDataSourcePointer); } } @@ -163,7 +162,7 @@ private: VectorDataToLabelImageFilter(const Self&) = delete; void operator=(const Self&) = delete; - ogr::version_proxy::GDALDatasetType * m_OGRDataSourcePointer; + GDALDataset * m_OGRDataSourcePointer; // Vector Of OGRGeometyH std::vector< OGRGeometryH > m_SrcDataSetGeometries; diff --git a/Modules/Segmentation/MorphologicalProfiles/include/otbClosingOpeningMorphologicalFilter.hxx b/Modules/Segmentation/MorphologicalProfiles/include/otbClosingOpeningMorphologicalFilter.hxx index 9624d10ad77d5b713f46b0b54e5ea98ce2a9e47d..efe975f0b356185d3c350f0ace0c9f23ca069686 100644 --- a/Modules/Segmentation/MorphologicalProfiles/include/otbClosingOpeningMorphologicalFilter.hxx +++ b/Modules/Segmentation/MorphologicalProfiles/include/otbClosingOpeningMorphologicalFilter.hxx @@ -22,7 +22,6 @@ #define otbClosingOpeningMorphologicalFilter_hxx #include "otbClosingOpeningMorphologicalFilter.h" -#include "itkUnaryFunctorImageFilter.h" #include "itkGrayscaleMorphologicalOpeningImageFilter.h" #include "itkGrayscaleMorphologicalClosingImageFilter.h" #include "itkProgressAccumulator.h" diff --git a/Modules/Segmentation/MorphologicalProfiles/include/otbGeodesicMorphologyDecompositionImageFilter.h b/Modules/Segmentation/MorphologicalProfiles/include/otbGeodesicMorphologyDecompositionImageFilter.h index 4b2ef4d9bd4f79a25d6e820dba48a907c6c43c94..bcdcd54c024279112162d91a93bd9bd695b1530e 100644 --- a/Modules/Segmentation/MorphologicalProfiles/include/otbGeodesicMorphologyDecompositionImageFilter.h +++ b/Modules/Segmentation/MorphologicalProfiles/include/otbGeodesicMorphologyDecompositionImageFilter.h @@ -22,7 +22,6 @@ #define otbGeodesicMorphologyDecompositionImageFilter_h #include "otbGeodesicMorphologyLevelingFilter.h" -#include "itkUnaryFunctorImageFilter.h" #include "itkSubtractImageFilter.h" #include "itkOpeningByReconstructionImageFilter.h" #include "itkClosingByReconstructionImageFilter.h" diff --git a/Modules/Segmentation/MorphologicalProfiles/include/otbGeodesicMorphologyDecompositionImageFilter.hxx b/Modules/Segmentation/MorphologicalProfiles/include/otbGeodesicMorphologyDecompositionImageFilter.hxx index 514b4e0e56177912beb3ab603de409082e268dec..d5e9fda923b7d1da8caef571f544e874ffd2a1c2 100644 --- a/Modules/Segmentation/MorphologicalProfiles/include/otbGeodesicMorphologyDecompositionImageFilter.hxx +++ b/Modules/Segmentation/MorphologicalProfiles/include/otbGeodesicMorphologyDecompositionImageFilter.hxx @@ -88,9 +88,12 @@ GeodesicMorphologyDecompositionImageFilter<TInputImage, TOutputImage, TStructuri m_ConcaveFilter->SetInput1(m_ClosingFilter->GetOutput()); m_ConcaveFilter->SetInput2(this->GetInput()); - m_LevelingFilter->SetInput(this->GetInput()); - m_LevelingFilter->SetInputConvexMap(m_ConvexFilter->GetOutput()); - m_LevelingFilter->SetInputConcaveMap(m_ConcaveFilter->GetOutput()); + using namespace otb::Functor::LevelingFunctor_tags; + // Template keyword mandatory to avoid parsing error when using + // template methods within template code + m_LevelingFilter->template SetVariadicNamedInput<pixel>(this->GetInput()); + m_LevelingFilter->template SetVariadicNamedInput<convex_pixel>(m_ConvexFilter->GetOutput()); + m_LevelingFilter->template SetVariadicNamedInput<concave_pixel>(m_ConcaveFilter->GetOutput()); m_ConvexFilter->GraftOutput(this->GetConvexMap()); m_ConvexFilter->Update(); diff --git a/Modules/Segmentation/MorphologicalProfiles/include/otbGeodesicMorphologyLevelingFilter.h b/Modules/Segmentation/MorphologicalProfiles/include/otbGeodesicMorphologyLevelingFilter.h index c0e57a2343e6bccadd2a8a7622d19f0613dc9cf4..e2cbc4c84e53ec7265e97278e661f585ae82b403 100644 --- a/Modules/Segmentation/MorphologicalProfiles/include/otbGeodesicMorphologyLevelingFilter.h +++ b/Modules/Segmentation/MorphologicalProfiles/include/otbGeodesicMorphologyLevelingFilter.h @@ -21,16 +21,25 @@ #ifndef otbGeodesicMorphologyLevelingFilter_h #define otbGeodesicMorphologyLevelingFilter_h -#include "itkTernaryFunctorImageFilter.h" +#include "otbFunctorImageFilter.h" namespace otb { namespace Functor { +namespace LevelingFunctor_tags +{ +struct pixel {}; +struct convex_pixel {}; +struct concave_pixel {}; +} /** \class LevelingFunctor * \brief This functor performs the pixel-wise leveling operation needed in the * geodesic morphology decomposition filter. For more details, please refer to * the documentation of this filter. + * + * Use otb::GeodesicMorphologyLevelingFilter to apply it image-wise. + * * \sa GeodesicMorphologyDecompositionImageFilter * * \ingroup OTBMorphologicalProfiles @@ -44,7 +53,7 @@ public: /// Destructor virtual ~LevelingFunctor() {} - inline TOutput operator ()(const TInput& pixel, const TInputMap& convexPixel, const TInputMap& concavePixel) + inline TOutput operator ()(const TInput& pixel, const TInputMap& convexPixel, const TInputMap& concavePixel) const { TOutput result; @@ -65,77 +74,25 @@ public: }; } // end namespace Functor -/** \class GeodesicMorphologyLevelingFilter +/** \typedef GeodesicMorphologyLevelingFilter * \brief This filter performs the leveling operation defined in the documentation of * the geodesic decomposition image filter, given the original image, convex and concave membership * functions. Please refer to the documentation of this filter for more details. * + * It applies the Functor::LevelingFunctor image-wise. + * * \sa GeodesicMorphologyDecompositionImageFilter - * + * * \ingroup OTBMorphologicalProfiles */ -template <class TInputImage, class TInputMaps, class TOutputImage> -class ITK_EXPORT GeodesicMorphologyLevelingFilter - : public itk::TernaryFunctorImageFilter<TInputImage, TInputImage, - TInputImage, TOutputImage, - Functor::LevelingFunctor<typename TInputImage::PixelType, - typename TInputMaps::PixelType, - typename TOutputImage::PixelType> > -{ -public: - /** Standard typedefs */ - typedef GeodesicMorphologyLevelingFilter Self; - typedef itk::TernaryFunctorImageFilter<TInputImage, TInputImage, - TInputImage, TOutputImage, - Functor::LevelingFunctor<typename TInputImage::PixelType, - typename TInputMaps::PixelType, - typename TOutputImage::PixelType> > Superclass; - typedef itk::SmartPointer<Self> Pointer; - typedef itk::SmartPointer<const Self> ConstPointer; - /** Type macro */ - itkNewMacro(Self); - - /** Creation through object factory macro */ - itkTypeMacro(GeodesicMorphologyLevelingFilter, TernaryFunctorImageFilter); - - /** - * Set the convex membership image. - */ - void SetInputConvexMap(const TInputMaps * convexMap) - { - this->SetInput2(convexMap); - } - /** - * Set the concave membership image. - */ - void SetInputConcaveMap(const TInputMaps * concaveMap) - { - this->SetInput3(concaveMap); - } - /** - * Set the original input image - */ - using Superclass::SetInput; - void SetInput(const TInputImage * input) override - { - this->SetInput1(input); - } - -protected: - /** Constructor */ - GeodesicMorphologyLevelingFilter() {}; - /** Destructor */ - ~GeodesicMorphologyLevelingFilter() override {} - /**PrintSelf method */ - void PrintSelf(std::ostream& os, itk::Indent indent) const override - { - Superclass::PrintSelf(os, indent); - } - -private: - GeodesicMorphologyLevelingFilter(const Self &) = delete; - void operator =(const Self&) = delete; -}; +template <class TInputImage, class TInputMaps, class TOutputImage> +using GeodesicMorphologyLevelingFilter = FunctorImageFilter + < Functor::LevelingFunctor<typename TInputImage::PixelType, + typename TInputMaps::PixelType, + typename TOutputImage::PixelType>, + std::tuple<typename Functor::LevelingFunctor_tags::pixel, + typename Functor::LevelingFunctor_tags::convex_pixel, + typename Functor::LevelingFunctor_tags::concave_pixel > >; } // End namespace otb #endif diff --git a/Modules/Segmentation/MorphologicalProfiles/include/otbMorphologicalClosingProfileFilter.h b/Modules/Segmentation/MorphologicalProfiles/include/otbMorphologicalClosingProfileFilter.h index 151dca67a3fc4b0a68c3f585b6cab925a476125e..ef89706a0b4770d16046e879e87f06f2fedd958d 100644 --- a/Modules/Segmentation/MorphologicalProfiles/include/otbMorphologicalClosingProfileFilter.h +++ b/Modules/Segmentation/MorphologicalProfiles/include/otbMorphologicalClosingProfileFilter.h @@ -22,7 +22,6 @@ #define otbMorphologicalClosingProfileFilter_h #include "otbImageToProfileFilter.h" -#include "itkUnaryFunctorImageFilter.h" #include "itkClosingByReconstructionImageFilter.h" namespace otb diff --git a/Modules/Segmentation/MorphologicalProfiles/include/otbMorphologicalOpeningProfileFilter.h b/Modules/Segmentation/MorphologicalProfiles/include/otbMorphologicalOpeningProfileFilter.h index 3b9668b04af5288c14f13ee1268459ce50c4e45c..803fc651107b950dd90dfe3fb8de61c9b6c7717c 100644 --- a/Modules/Segmentation/MorphologicalProfiles/include/otbMorphologicalOpeningProfileFilter.h +++ b/Modules/Segmentation/MorphologicalProfiles/include/otbMorphologicalOpeningProfileFilter.h @@ -22,7 +22,6 @@ #define otbMorphologicalOpeningProfileFilter_h #include "otbImageToProfileFilter.h" -#include "itkUnaryFunctorImageFilter.h" #include "itkOpeningByReconstructionImageFilter.h" namespace otb diff --git a/Modules/Segmentation/MorphologicalProfiles/include/otbMorphologicalProfilesSegmentationFilter.hxx b/Modules/Segmentation/MorphologicalProfiles/include/otbMorphologicalProfilesSegmentationFilter.hxx index 11a772035d919dc70ecb1d2993b118cec4e5668b..68c37cf462a8fd8cf90dda0016dee707842df991 100644 --- a/Modules/Segmentation/MorphologicalProfiles/include/otbMorphologicalProfilesSegmentationFilter.hxx +++ b/Modules/Segmentation/MorphologicalProfiles/include/otbMorphologicalProfilesSegmentationFilter.hxx @@ -49,10 +49,13 @@ MorphologicalProfilesSegmentationFilter<TInputImage,TOutputImage,TInternalPrecis m_OpeningCharacteristicsFilter->SetInput(m_OpeningDerivativeProfile->GetOutput()); m_ClosingCharacteristicsFilter->SetInput(m_ClosingDerivativeProfile->GetOutput()); - m_ClassificationFilter->SetOpeningProfileDerivativeMaxima(m_OpeningCharacteristicsFilter->GetOutput()); - m_ClassificationFilter->SetOpeningProfileCharacteristics(m_OpeningCharacteristicsFilter->GetOutputCharacteristics()); - m_ClassificationFilter->SetClosingProfileDerivativeMaxima(m_ClosingCharacteristicsFilter->GetOutput()); - m_ClassificationFilter->SetClosingProfileCharacteristics(m_ClosingCharacteristicsFilter->GetOutputCharacteristics()); + using namespace Functor::MultiScaleConvexOrConcaveDecisionRule_tags; + // Template keyword mandatory to avoid parsing error when using + // template methods within template code + m_ClassificationFilter->template SetVariadicNamedInput<max_opening_profile_derivative>(m_OpeningCharacteristicsFilter->GetOutput()); + m_ClassificationFilter->template SetVariadicNamedInput<opening_profile_characteristics>(m_OpeningCharacteristicsFilter->GetOutputCharacteristics()); + m_ClassificationFilter->template SetVariadicNamedInput<max_closing_profile_derivative>(m_ClosingCharacteristicsFilter->GetOutput()); + m_ClassificationFilter->template SetVariadicNamedInput<closing_profile_characteristics>(m_ClosingCharacteristicsFilter->GetOutputCharacteristics()); m_ConnectedComponentsFilter->SetInput(m_ClassificationFilter->GetOutput()); @@ -85,8 +88,8 @@ MorphologicalProfilesSegmentationFilter<TInputImage,TOutputImage,TInternalPrecis m_ClosingCharacteristicsFilter->SetInitialValue(m_ProfileStart); m_ClosingCharacteristicsFilter->SetStep(m_ProfileStep); - m_ClassificationFilter->SetSigma(m_Sigma); - m_ClassificationFilter->SetLabelSeparator(m_ProfileStart + m_ProfileSize * m_ProfileStep); + m_ClassificationFilter->GetModifiableFunctor().SetSigma(m_Sigma); + m_ClassificationFilter->GetModifiableFunctor().SetLabelSeparator(m_ProfileStart + m_ProfileSize * m_ProfileStep); m_ConnectedComponentsFilter->GraftOutput(this->GetOutput()); m_ConnectedComponentsFilter->Update(); diff --git a/Modules/Segmentation/MorphologicalProfiles/include/otbMultiScaleConvexOrConcaveClassificationFilter.h b/Modules/Segmentation/MorphologicalProfiles/include/otbMultiScaleConvexOrConcaveClassificationFilter.h index fc23f5a6a95577067144f9a81d6bd9691ac58588..8819ff33b4e9485519e0984e6bb3d89660aab75d 100644 --- a/Modules/Segmentation/MorphologicalProfiles/include/otbMultiScaleConvexOrConcaveClassificationFilter.h +++ b/Modules/Segmentation/MorphologicalProfiles/include/otbMultiScaleConvexOrConcaveClassificationFilter.h @@ -21,14 +21,26 @@ #ifndef otbMultiScaleConvexOrConcaveClassificationFilter_h #define otbMultiScaleConvexOrConcaveClassificationFilter_h -#include "otbQuaternaryFunctorImageFilter.h" +#include "otbFunctorImageFilter.h" + namespace otb { namespace Functor { +namespace MultiScaleConvexOrConcaveDecisionRule_tags +{ +struct max_opening_profile_derivative {}; +struct max_closing_profile_derivative {}; +struct opening_profile_characteristics {}; +struct closing_profile_characteristics {}; + +} // End namespace MultiScaleConvexOrConcaveDecisionRule_tags + /** \class MultiScaleConvexOrConcaveDecisionRule * \brief This Functor apply a classification rule on two membership value along with two labels. * + * Use otb::MultiScaleConvexOrConcaveClassificationFilter to apply it image-wise. + * * \par * This algorithm is based on the following publication: * \par @@ -82,10 +94,10 @@ public: * \param opDeChar The characteristic of the opening profile * \param cloDeChar The characteristic of the closing profile */ - inline TLabeled operator ()(const TInput& opDeMax, - const TInput& cloDeMax, - const TLabeled& opDeChar, - const TLabeled& cloDeChar) + TLabeled operator ()(const TInput& opDeMax, + const TInput& cloDeMax, + const TLabeled& opDeChar, + const TLabeled& cloDeChar) const { TLabeled resp = 0; @@ -141,118 +153,29 @@ private: }; } //end namespace Functor -/** \class MultiScaleConvexOrConcaveClassificationFilter - * \brief Apply the MultiScaleConvexOrConcaveDecisionRule to whole images. +/** \typedef MultiScaleConvexOrConcaveClassificationFilter + * \brief Apply the otb::Functor::MultiScaleConvexOrConcaveDecisionRule to whole images. * - * See MultiScaleConvexOrConcaveDecisionRule functor documentation for more details. + * See otb::Functor::MultiScaleConvexOrConcaveDecisionRule functor documentation for more details. * + * Set inputs with: + * \code + * + * SetVariadicNamedInput<MultiScaleConvexOrConcaveDecisionRule_tags::max_opening_profile_derivative>(in1); + * SetVariadicNamedInput<MultiScaleConvexOrConcaveDecisionRule_tags::max_closing_profile_derivative>(in2); + * SetVariadicNamedInput<MultiScaleConvexOrConcaveDecisionRule_tags::opening_profile_characteristics>(in3); + * SetVariadicNamedInput<MultiScaleConvexOrConcaveDecisionRule_tags::closing_profile_characteristics>(in4); * + * \endcode + * * \ingroup OTBMorphologicalProfiles */ template <class TInputImage, class TOutputImage> -class ITK_EXPORT MultiScaleConvexOrConcaveClassificationFilter - : public QuaternaryFunctorImageFilter<TInputImage, TInputImage, TOutputImage, TOutputImage, TOutputImage, - Functor::MultiScaleConvexOrConcaveDecisionRule<typename TInputImage::PixelType, - typename TOutputImage::PixelType> > -{ -public: - /** Standard typedefs */ - typedef MultiScaleConvexOrConcaveClassificationFilter Self; - typedef QuaternaryFunctorImageFilter<TInputImage, TInputImage, TOutputImage, TOutputImage, TOutputImage, - Functor::MultiScaleConvexOrConcaveDecisionRule<typename TInputImage::PixelType, - typename TOutputImage::PixelType> > - Superclass; - typedef itk::SmartPointer<Self> Pointer; - typedef itk::SmartPointer<const Self> ConstPointer; - - /** Type macro */ - itkNewMacro(Self); - - /** Creation through object factory macro */ - itkTypeMacro(MultiScaleConvexOrConcaveClassificationFilter, QuaternaryFunctorImageFilter); - - /** Template class typedef */ - typedef TInputImage InputImageType; - typedef TOutputImage OutputImageType; - typedef typename OutputImageType::PixelType LabelType; - typedef Functor::MultiScaleConvexOrConcaveDecisionRule<typename TInputImage::PixelType, - typename TOutputImage::PixelType> DecisionFunctorType; - /** - * Set the opening profile derivative maxima image - * \param derivativeMaxima the opening profile derivative maxima image - * - */ - void SetOpeningProfileDerivativeMaxima(const TInputImage * derivativeMaxima) - { - this->SetInput1(derivativeMaxima); - } - /** - * Set the opening profile characteristics image - * \param characteristics the opening profile characteristics image - * - */ - void SetOpeningProfileCharacteristics(const TOutputImage * characteristics) - { - this->SetInput3(characteristics); - } - /** - * Set the closing profile derivative maxima image - * \param derivativeMaxima the closing profile derivative maxima image - * - */ - void SetClosingProfileDerivativeMaxima(const TInputImage * derivativeMaxima) - { - this->SetInput2(derivativeMaxima); - } - /** - * Set the closing profile characteristics image - * \param characteristics the closing profile characteristics image - * - */ - void SetClosingProfileCharacteristics(const TOutputImage * characteristics) - { - this->SetInput4(characteristics); - } - - /** Set/Get the tolerance value */ - itkSetMacro(Sigma, double); - itkGetMacro(Sigma, double); - /** Set/Get the label separator */ - itkSetMacro(LabelSeparator, LabelType); - itkGetMacro(LabelSeparator, LabelType); - - /** Set the functor parameters before calling the ThreadedGenerateData() */ - void BeforeThreadedGenerateData(void) override - { - this->GetFunctor().SetLabelSeparator(m_LabelSeparator); - this->GetFunctor().SetSigma(m_Sigma); - } - -protected: - /** Constructor */ - MultiScaleConvexOrConcaveClassificationFilter() - { - m_LabelSeparator = 10; - m_Sigma = 0.0; - }; - /** Destructor */ - ~MultiScaleConvexOrConcaveClassificationFilter() override {} - /**PrintSelf method */ - void PrintSelf(std::ostream& os, itk::Indent indent) const override - { - Superclass::PrintSelf(os, indent); - os << indent << "LabelSeparator: " << m_LabelSeparator << std::endl; - os << indent << "Sigma: " << m_Sigma << std::endl; - } - -private: - MultiScaleConvexOrConcaveClassificationFilter(const Self &) = delete; - void operator =(const Self&) = delete; - - /** Label separator between convex and concave labels */ - LabelType m_LabelSeparator; - /** Tolerance value */ - double m_Sigma; -}; +using MultiScaleConvexOrConcaveClassificationFilter += FunctorImageFilter<Functor::MultiScaleConvexOrConcaveDecisionRule<typename TInputImage::PixelType, typename TOutputImage::PixelType>, + std::tuple<Functor::MultiScaleConvexOrConcaveDecisionRule_tags::max_opening_profile_derivative, + Functor::MultiScaleConvexOrConcaveDecisionRule_tags::max_closing_profile_derivative, + Functor::MultiScaleConvexOrConcaveDecisionRule_tags::opening_profile_characteristics, + Functor::MultiScaleConvexOrConcaveDecisionRule_tags::closing_profile_characteristics> >; } // End namespace otb #endif diff --git a/Modules/Segmentation/MorphologicalProfiles/include/otbOpeningClosingMorphologicalFilter.hxx b/Modules/Segmentation/MorphologicalProfiles/include/otbOpeningClosingMorphologicalFilter.hxx index fc3f05561ccabc085ef29ac6ffeff19748e3c37e..8380c1110a63c35c97a6813cb5ada983748292da 100644 --- a/Modules/Segmentation/MorphologicalProfiles/include/otbOpeningClosingMorphologicalFilter.hxx +++ b/Modules/Segmentation/MorphologicalProfiles/include/otbOpeningClosingMorphologicalFilter.hxx @@ -22,7 +22,6 @@ #define otbOpeningClosingMorphologicalFilter_hxx #include "otbOpeningClosingMorphologicalFilter.h" -#include "itkUnaryFunctorImageFilter.h" #include "itkGrayscaleMorphologicalOpeningImageFilter.h" #include "itkGrayscaleMorphologicalClosingImageFilter.h" #include "itkProgressAccumulator.h" diff --git a/Modules/Segmentation/MorphologicalProfiles/include/otbProfileToProfileDerivativeFilter.h b/Modules/Segmentation/MorphologicalProfiles/include/otbProfileToProfileDerivativeFilter.h index 80230dff776078976def7bb921a8c87217e4baac..f459a85abbf76f226211c485adaade1b51be996a 100644 --- a/Modules/Segmentation/MorphologicalProfiles/include/otbProfileToProfileDerivativeFilter.h +++ b/Modules/Segmentation/MorphologicalProfiles/include/otbProfileToProfileDerivativeFilter.h @@ -22,7 +22,6 @@ #define otbProfileToProfileDerivativeFilter_h #include "otbImageListToImageListFilter.h" -#include "itkUnaryFunctorImageFilter.h" #include "itkSubtractImageFilter.h" #include "itkAbsImageFilter.h" diff --git a/Modules/Segmentation/MorphologicalProfiles/otb-module.cmake b/Modules/Segmentation/MorphologicalProfiles/otb-module.cmake index d05a0c719d87ec054fd64352751e9e8e222d34b4..005074cff8e2b4bde4a2995fbcb3cc58727a3814 100644 --- a/Modules/Segmentation/MorphologicalProfiles/otb-module.cmake +++ b/Modules/Segmentation/MorphologicalProfiles/otb-module.cmake @@ -27,6 +27,7 @@ otb_module(OTBMorphologicalProfiles OTBITK OTBImageBase OTBObjectList + OTBFunctor TEST_DEPENDS OTBImageIO diff --git a/Modules/Segmentation/MorphologicalProfiles/test/otbGeodesicMorphologyLevelingFilter.cxx b/Modules/Segmentation/MorphologicalProfiles/test/otbGeodesicMorphologyLevelingFilter.cxx index 0c1faa3267f5cbc89b439f7b32c19a137e629671..3fe3e2ee05e18d911369e1b455afa0c1a5118280 100644 --- a/Modules/Segmentation/MorphologicalProfiles/test/otbGeodesicMorphologyLevelingFilter.cxx +++ b/Modules/Segmentation/MorphologicalProfiles/test/otbGeodesicMorphologyLevelingFilter.cxx @@ -46,9 +46,10 @@ int otbGeodesicMorphologyLevelingFilter(int itkNotUsed(argc), char * argv[]) FilterType::Pointer filter = FilterType::New(); - filter->SetInput(reader->GetOutput()); - filter->SetInputConvexMap(convreader->GetOutput()); - filter->SetInputConcaveMap(concreader->GetOutput()); + using namespace otb::Functor::LevelingFunctor_tags; + filter->SetVariadicNamedInput<pixel>(reader->GetOutput()); + filter->SetVariadicNamedInput<convex_pixel>(convreader->GetOutput()); + filter->SetVariadicNamedInput<concave_pixel>(concreader->GetOutput()); WriterType::Pointer writer = WriterType::New(); writer->SetFileName(outfname); diff --git a/Modules/Segmentation/MorphologicalProfiles/test/otbMultiScaleConvexOrConcaveClassificationFilter.cxx b/Modules/Segmentation/MorphologicalProfiles/test/otbMultiScaleConvexOrConcaveClassificationFilter.cxx index 6dddf61e56c06ac9180ba23f1c78d4f047413b3e..a01e2ba2f7e3290adc1823cc2bb8e5bd9bbb9046 100644 --- a/Modules/Segmentation/MorphologicalProfiles/test/otbMultiScaleConvexOrConcaveClassificationFilter.cxx +++ b/Modules/Segmentation/MorphologicalProfiles/test/otbMultiScaleConvexOrConcaveClassificationFilter.cxx @@ -96,12 +96,13 @@ int otbMultiScaleConvexOrConcaveClassificationFilter(int itkNotUsed(argc), char cmsCharFilter->SetStep(step); MultiScaleClassificationFilterType::Pointer classificationFilter = MultiScaleClassificationFilterType::New(); - classificationFilter->SetOpeningProfileDerivativeMaxima(omsCharFilter->GetOutput()); - classificationFilter->SetOpeningProfileCharacteristics(omsCharFilter->GetOutputCharacteristics()); - classificationFilter->SetClosingProfileDerivativeMaxima(cmsCharFilter->GetOutput()); - classificationFilter->SetClosingProfileCharacteristics(cmsCharFilter->GetOutputCharacteristics()); - classificationFilter->SetSigma(sigma); - classificationFilter->SetLabelSeparator(initialValue + profileSize * step); + using namespace otb::Functor::MultiScaleConvexOrConcaveDecisionRule_tags; + classificationFilter->SetVariadicNamedInput<max_opening_profile_derivative>(omsCharFilter->GetOutput()); + classificationFilter->SetVariadicNamedInput<opening_profile_characteristics>(omsCharFilter->GetOutputCharacteristics()); + classificationFilter->SetVariadicNamedInput<max_closing_profile_derivative>(cmsCharFilter->GetOutput()); + classificationFilter->SetVariadicNamedInput<closing_profile_characteristics>(cmsCharFilter->GetOutputCharacteristics()); + classificationFilter->GetModifiableFunctor().SetSigma(sigma); + classificationFilter->GetModifiableFunctor().SetLabelSeparator(initialValue + profileSize * step); LabeledWriterType::Pointer labeledWriter = LabeledWriterType::New(); diff --git a/Modules/Segmentation/OGRProcessing/include/otbOGRLayerStreamStitchingFilter.h b/Modules/Segmentation/OGRProcessing/include/otbOGRLayerStreamStitchingFilter.h index b3702ad155522de6e79a96f313059dee0b38d472..43750ae207e7cf346d96561050656b005b1d18ba 100644 --- a/Modules/Segmentation/OGRProcessing/include/otbOGRLayerStreamStitchingFilter.h +++ b/Modules/Segmentation/OGRProcessing/include/otbOGRLayerStreamStitchingFilter.h @@ -24,10 +24,6 @@ #include "otbOGRDataSourceWrapper.h" #include "otbMacro.h" -//#if(GDAL_VERSION_NUM < 1800) -//#error OGRLayerStreamStitchingFilter requires GDAL version >= 1.8.0 -//#endif - #include "itkProgressReporter.h" #include <algorithm> diff --git a/Modules/Segmentation/OGRProcessing/include/otbOGRLayerStreamStitchingFilter.hxx b/Modules/Segmentation/OGRProcessing/include/otbOGRLayerStreamStitchingFilter.hxx index 5359e967bfb7224311aa9d452965ea4cc9c4315c..a3c72bb38bdfad22e828baa0e041b102549658c1 100644 --- a/Modules/Segmentation/OGRProcessing/include/otbOGRLayerStreamStitchingFilter.hxx +++ b/Modules/Segmentation/OGRProcessing/include/otbOGRLayerStreamStitchingFilter.hxx @@ -291,12 +291,8 @@ OGRLayerStreamStitchingFilter<TInputImage> } else if (intersection->getGeometryType() == wkbMultiLineString) { - #if(GDAL_VERSION_NUM < 1800) - fusion.overlap = GetLengthOGRGeometryCollection(dynamic_cast<OGRGeometryCollection *> (intersection.get())); - #else fusion.overlap = dynamic_cast<OGRMultiLineString *>(intersection.get())->get_Length(); - #endif - } + } /** -Wunused-variable long upperFID = upper.feat.GetFID(); @@ -325,9 +321,6 @@ OGRLayerStreamStitchingFilter<TInputImage> ogr::Field field = upper.feat[0]; try { - #ifdef OTB_USE_GDAL_20 - // In this case, the feature id can be either - // OFTInteger64 or OFTInteger switch(field.GetType()) { case OFTInteger64: @@ -340,10 +333,6 @@ OGRLayerStreamStitchingFilter<TInputImage> fusionFeature[0].SetValue(field.GetValue<int>()); } } - #else - // Only OFTInteger supported in this case - fusionFeature[0].SetValue(field.GetValue<int>()); - #endif m_OGRLayer.CreateFeature(fusionFeature); m_OGRLayer.DeleteFeature(lower.feat.GetFID()); m_OGRLayer.DeleteFeature(upper.feat.GetFID()); diff --git a/Modules/ThirdParty/GDAL/otb-module-init.cmake b/Modules/ThirdParty/GDAL/otb-module-init.cmake index b13104318f0de04de73b78aaeb59d1aafd203e3c..68bdd5597c3258a8fd27c27a2b1d38814e0a99b2 100644 --- a/Modules/ThirdParty/GDAL/otb-module-init.cmake +++ b/Modules/ThirdParty/GDAL/otb-module-init.cmake @@ -35,8 +35,8 @@ if(NOT GDAL_CONFIG_CHECKING) return() endif() -set(MIN_MAJOR_VERSION 1) -set(MIN_MINOR_VERSION 10) +set(MIN_MAJOR_VERSION 2) +set(MIN_MINOR_VERSION 0) # Ensure that the temporary dir always exists before starting tests if(NOT EXISTS ${TEMP}) @@ -95,11 +95,6 @@ if(EXISTS "${TEMP}/gdalVersion.txt") file(READ "${TEMP}/gdalVersion.txt" _GDAL_VERSION_STRING) #can't we use GDAL_VERSION_NUM ? string(SUBSTRING ${_GDAL_VERSION_STRING} 0 2 VER2) - if("${VER2}" STREQUAL "2.") - set(OTB_USE_GDAL_20 true CACHE INTERNAL "True if GDAL >= 2.0.0 has been detected" FORCE ) - else() - set(OTB_USE_GDAL_20 false CACHE INTERNAL "True if GDAL >= 2.0.0 has been detected" FORCE ) - endif() set(GDAL_VERSION_STRING "${_GDAL_VERSION_STRING}" CACHE INTERNAL "" FORCE) else() error_message( "${TEMP}/gdalVersion.txt does not exist. Cannot continue.") diff --git a/Modules/ThirdParty/OssimPlugins/include/ossim/ossimSarSensorModel.h b/Modules/ThirdParty/OssimPlugins/include/ossim/ossimSarSensorModel.h index 7bbc7f2df4e4939f9b66d123886abce9bef52da8..8cd2881e0e1fd1b6794ceb44a8562b68aa25a0ce 100644 --- a/Modules/ThirdParty/OssimPlugins/include/ossim/ossimSarSensorModel.h +++ b/Modules/ThirdParty/OssimPlugins/include/ossim/ossimSarSensorModel.h @@ -288,12 +288,19 @@ public: * Note that the deburst operation has no effect if theBurstRecords * contains a single burst. Otherwise it will merge burst together * into a single burst, and update GCPs accordingly. + * Two modes are available for the output image : with all samples and + * with only valid samples. A pair of samples specifies first and last samples * \return true if the deburst operation succeeded. No changes is * made to the object if the operation fails. * \param lines A container for the lines ranges to keep in the * deburst image. + * \param samples A container for the samples to keep in the + * deburst image. + * \param onlyValidSample If true, the selected mode is with only valid sample. */ - bool deburst(std::vector<std::pair<unsigned long,unsigned long> >& lines); + bool deburst(std::vector<std::pair<unsigned long,unsigned long> >& lines, + std::pair<unsigned long,unsigned long> & samples, bool onlyValidSample=false); + /** * This is a helper function to convert image line to deburst image @@ -314,6 +321,38 @@ public: */ static void deburstLineToImageLine(const std::vector<std::pair<unsigned long,unsigned long> >& lines, unsigned long deburstLine, unsigned long & imageLine); + /** + * This method will perform an extration of one burst. It wil return the + * lines and samples to extract in the image file. + * \return true if the extraction operation succeeded. No changes is + * made to the object if the operation fails. + * \param burst_index Index of Burst. + * \param lines A container for the lines to keep in the + * standalone burst. + * \param samples A container for the samples to keep in the + * standalone burst. + */ + bool burstExtraction(const unsigned int burst_index, std::pair<unsigned long,unsigned long> & lines, + std::pair<unsigned long,unsigned long> & samples, bool allPixels=false); + + /** + * This method will perform a deburst and concatenation operation, and return the + * vector of lines and the vector of samples to keep in the + * image file. The lines and samples represents start/size into each indepedent bursts. + * Note that the deburst operation has no effect if theBurstRecords + * contains a single burst. Otherwise it will merge burst together + * into a single burst, and update GCPs accordingly. + * \return true if the deburst operation succeeded. No changes is + * made to the object if the operation fails. + * \param lines A container for the lines ranges to keep in the + * deburst image. + * \param samples A container for the samples ranges to keep in the + * deburst image. + * \param lines A Boolean to indicate only valids samples are required. + */ + bool deburstAndConcatenate(std::vector<std::pair<unsigned long,unsigned long> >& linesBursts, + std::vector<std::pair<unsigned long,unsigned long> >& samplesBursts); + /** * Returns pointer to a new instance, copy of this. */ @@ -453,6 +492,14 @@ protected: double theRangeTimeOffset; // Offset in seconds, computed bool theRightLookingFlag; + TimeType theFirstLineTime; + TimeType theLastLineTime; + + unsigned long theNumberOfLinesPerBurst; + unsigned long theNumberOfSamplesPerBurst; + + bool redaptMedataAfterDeburst; + static const double C; static const unsigned int thePluginVersion; // version of the SarSensorModel plugin diff --git a/Modules/ThirdParty/OssimPlugins/src/ossim/ossimSarSensorModel.cpp b/Modules/ThirdParty/OssimPlugins/src/ossim/ossimSarSensorModel.cpp index 31c046fe6baed47cf66876f07021e43d2c7a5fd5..ddb5bda193e99aade9a595a29b932245cee695ab 100644 --- a/Modules/ThirdParty/OssimPlugins/src/ossim/ossimSarSensorModel.cpp +++ b/Modules/ThirdParty/OssimPlugins/src/ossim/ossimSarSensorModel.cpp @@ -139,7 +139,8 @@ namespace ossimplugins theBistaticCorrectionNeeded(false), theAzimuthTimeOffset(seconds(0)), theRangeTimeOffset(0.), - theRightLookingFlag(true) + theRightLookingFlag(true), + redaptMedataAfterDeburst(false) {} ossimSarSensorModel::GCPRecordType const& @@ -1359,6 +1360,14 @@ bool ossimSarSensorModel::worldToAzimuthRangeTime(const ossimGpt& worldPt, TimeT add(kwl, HEADER_PREFIX, "version", thePluginVersion); + if (redaptMedataAfterDeburst) + { + add(kwl, SUPPORT_DATA_PREFIX, "first_line_time", theFirstLineTime); + add(kwl, SUPPORT_DATA_PREFIX, "last_line_time", theLastLineTime); + add(kwl, HEADER_PREFIX, "first_line_time", theFirstLineTime); + add(kwl, HEADER_PREFIX, "last_line_time", theLastLineTime); + } + return ossimSensorModel::saveState(kwl, prefix); } @@ -1386,17 +1395,32 @@ bool ossimSarSensorModel::worldToAzimuthRangeTime(const ossimGpt& worldPt, TimeT get(kwl, SUPPORT_DATA_PREFIX, "radar_frequency" , theRadarFrequency ); double azimuthTimeInterval = 0.; // in seconds get(kwl, SUPPORT_DATA_PREFIX, "line_time_interval" , azimuthTimeInterval); + #if defined(USE_BOOST_TIME) theAzimuthTimeInterval = boost::posix_time::precise_duration(azimuthTimeInterval * 1000000.); #else theAzimuthTimeInterval = seconds(azimuthTimeInterval); #endif - get(kwl, theOrbitRecords); // TODO: don't fetch burst records if already read thanks to xml loading // that required them theBurstRecords.clear(); get(kwl, theBurstRecords); + + if(theBurstRecords.size() > 1) + { + unsigned int version; + get(kwl, HEADER_PREFIX, "version", version); + + if (version > 2) + { + const std::string BURST_NUMBER_LINES_KEY = "support_data.geom.bursts.number_lines_per_burst"; + const std::string BURST_NUMBER_SAMPLES_KEY = "support_data.geom.bursts.number_samples_per_burst"; + get(kwl, BURST_NUMBER_LINES_KEY, theNumberOfLinesPerBurst); + get(kwl, BURST_NUMBER_SAMPLES_KEY, theNumberOfSamplesPerBurst); + } + } + if (isGRD()) { get(kwl, SR_PREFIX, keySr0, theSlantRangeToGroundRangeRecords); @@ -1425,7 +1449,8 @@ bool ossimSarSensorModel::worldToAzimuthRangeTime(const ossimGpt& worldPt, TimeT return false; } -bool ossimSarSensorModel::deburst(std::vector<std::pair<unsigned long, unsigned long> >& lines) +bool ossimSarSensorModel::deburst(std::vector<std::pair<unsigned long, unsigned long> >& lines, + std::pair<unsigned long,unsigned long> & samples, bool onlyValidSample) { if(theBurstRecords.empty()) return false; @@ -1452,6 +1477,8 @@ bool ossimSarSensorModel::deburst(std::vector<std::pair<unsigned long, unsigned TimeType deburstAzimuthStartTime = it->azimuthStartTime; unsigned long deburstEndLine = 0; + + samples = std::make_pair(it->startSample, it->endSample); for(; next!= itend ;++it,++next) { @@ -1466,17 +1493,44 @@ bool ossimSarSensorModel::deburst(std::vector<std::pair<unsigned long, unsigned unsigned long currentStop = it->endLine-halfLineOverlapEnd; - deburstEndLine+=currentStop-currentStart; + deburstEndLine+= currentStop - currentStart + 1; // +1 because currentStart/Stop are both valids + lines.push_back(std::make_pair(currentStart,currentStop)); - currentStart = next->startLine+halfLineOverlapBegin; + currentStart = next->startLine+halfLineOverlapBegin; + + if (onlyValidSample) + { + // Find the first and last valid sampleburst + if (it->startSample > samples.first) + { + samples.first = it->startSample; + } + if (it->endSample < samples.second) + { + samples.second = it->endSample; + } + } } TimeType deburstAzimuthStopTime = it->azimuthStopTime; deburstEndLine+=it->endLine-currentStart; lines.push_back(std::make_pair(currentStart,it->endLine)); + + if (onlyValidSample) + { + if (it->startSample > samples.first) + { + samples.first = it->startSample; + } + if (it->endSample < samples.second) + { + samples.second = it->endSample; + } + } + // Now, update other metadata accordingly @@ -1489,6 +1543,13 @@ bool ossimSarSensorModel::deburst(std::vector<std::pair<unsigned long, unsigned deburstBurst.azimuthStartTime = deburstAzimuthStartTime; deburstBurst.endLine = deburstEndLine; deburstBurst.azimuthStopTime = deburstAzimuthStopTime; + + if (onlyValidSample) + { + deburstBurst.startSample = 0; + deburstBurst.endSample = samples.second - samples.first; + } + theBurstRecords.push_back(deburstBurst); @@ -1501,24 +1562,355 @@ bool ossimSarSensorModel::deburst(std::vector<std::pair<unsigned long, unsigned unsigned long newLine=0; unsigned long gcpLine = std::floor(currentGCP.imPt.y+0.5); + unsigned long gcpSample = std::floor(currentGCP.imPt.x+0.5); + // Be careful about fractional part of GCPs - double fractional = currentGCP.imPt.y - gcpLine; - - bool deburstOk = imageLineToDeburstLine(lines,gcpLine,newLine); + double fractionalLines = currentGCP.imPt.y - gcpLine; + double fractionalSamples = currentGCP.imPt.x - gcpSample; - if(deburstOk) + bool linesOk = imageLineToDeburstLine(lines,gcpLine,newLine); + + // Gcp into valid samples + bool samplesOk = true; + unsigned long newSample = gcpSample; + + if (onlyValidSample) + { + samplesOk = false; + if (gcpSample >= samples.first && gcpSample <= samples.second) + { + samplesOk = true; + newSample -= samples.first; // Offset with first valid sample + } + } + + if(linesOk && samplesOk) { - currentGCP.imPt.y = newLine+fractional; - deburstGCPs.push_back(currentGCP); + currentGCP.imPt.y = newLine + fractionalLines; + currentGCP.imPt.x = newSample + fractionalSamples; + + deburstGCPs.push_back(currentGCP); } } theGCPRecords.swap(deburstGCPs); + + // Adapt general metadata : theNearRangeTime, first_time_line, last_time_line + redaptMedataAfterDeburst = true; + theFirstLineTime = deburstBurst.azimuthStartTime; + theLastLineTime = deburstBurst.azimuthStopTime; + + if (onlyValidSample) + theNearRangeTime += samples.first*(1/theRangeSamplingRate); + + return true; } + +bool +ossimSarSensorModel::burstExtraction(const unsigned int burst_index, + std::pair<unsigned long,unsigned long> & lines, + std::pair<unsigned long,unsigned long> & samples, bool allPixels) +{ + if(theBurstRecords.empty()) + return false; + + // Check the single burst record case + if(theBurstRecords.size() == 1) + { + lines = std::make_pair(theBurstRecords.front().startLine,theBurstRecords.front().endLine); + return false; + } + + // If all pixels is required + if (allPixels) + { + samples = std::make_pair(0, theNumberOfSamplesPerBurst - 1); + lines = std::make_pair(burst_index*theNumberOfLinesPerBurst, (burst_index+1)*theNumberOfLinesPerBurst - 1); + + redaptMedataAfterDeburst = true; + theFirstLineTime = theBurstRecords[burst_index].azimuthStartTime - (theBurstRecords[burst_index].startLine - lines.first) * theAzimuthTimeInterval; + theLastLineTime = theFirstLineTime + (lines.second - lines.first) * theAzimuthTimeInterval; + + // Clear the previous burst records + theBurstRecords.clear(); + + // Create the single burst + BurstRecordType oneBurst; + oneBurst.startLine = 0; + oneBurst.azimuthStartTime = theFirstLineTime; + oneBurst.endLine = lines.second - lines.first; + oneBurst.azimuthStopTime = theLastLineTime; + oneBurst.startSample = 0; + oneBurst.endSample = samples.second - samples.first; + + theBurstRecords.push_back(oneBurst); + } + else + { + // Retrieve into TheBurstRecord, the required index + BurstRecordType burstInd_Record = theBurstRecords[burst_index]; + lines = std::make_pair(burstInd_Record.startLine, burstInd_Record.endLine); + samples = std::make_pair(burstInd_Record.startSample, burstInd_Record.endSample); + TimeType burstAzimuthStartTime = burstInd_Record.azimuthStartTime; + TimeType burstAzimuthStopTime = burstInd_Record.azimuthStopTime; + + // Clear the previous burst records + theBurstRecords.clear(); + + // Create the single burst + BurstRecordType oneBurst; + oneBurst.startLine = 0; + oneBurst.azimuthStartTime = burstAzimuthStartTime; + oneBurst.endLine = lines.second - lines.first; + oneBurst.azimuthStopTime = burstAzimuthStopTime; + oneBurst.startSample = 0; + oneBurst.endSample = samples.second - samples.first; + + theBurstRecords.push_back(oneBurst); + + // Adapt general metadata : theNearRangeTime, first_time_line, last_time_line + redaptMedataAfterDeburst = true; + theFirstLineTime = oneBurst.azimuthStartTime; + theLastLineTime = oneBurst.azimuthStopTime; + theNearRangeTime += samples.first*(1/theRangeSamplingRate); + } + + std::vector<GCPRecordType> oneBurstGCPs; + + // Now move GCPs + for (auto const& token : theGCPRecords) + { + GCPRecordType currentGCP = token; + + unsigned long gcpLine = std::floor(currentGCP.imPt.y+0.5); + unsigned long gcpSample = std::floor(currentGCP.imPt.x+0.5); + + // Be careful about fractional part of GCPs + double fractionalLines = currentGCP.imPt.y - gcpLine; + double fractionalSamples = currentGCP.imPt.x - gcpSample; + + + // Gcp into valid samples and valid lines + unsigned long newSample = gcpSample; + bool samplesOk = false; + + if (gcpSample >= samples.first && gcpSample <= samples.second) + { + samplesOk = true; + newSample -= samples.first; // Offset with first valid sample + } + + unsigned long newLine = gcpLine; + bool linesOk = false; + + if (gcpLine >= lines.first && gcpLine <= lines.second) + { + linesOk = true; + newLine -= lines.first; // Offset with first valid line + } + + if(linesOk && samplesOk) + { + currentGCP.imPt.y = newLine + fractionalLines; + currentGCP.imPt.x = newSample + fractionalSamples; + oneBurstGCPs.push_back(currentGCP); + } + } + + theGCPRecords.swap(oneBurstGCPs); + + return true; +} + +bool +ossimSarSensorModel::deburstAndConcatenate(std::vector<std::pair<unsigned long,unsigned long> >& linesBursts, + std::vector<std::pair<unsigned long,unsigned long> >& samplesBursts) +{ + if(theBurstRecords.empty()) + return false; + + // declare lines and samples + std::vector<std::pair<unsigned long,unsigned long> > lines; + lines.reserve(theBurstRecords.size()); + std::pair<unsigned long,unsigned long> samples; + + // First, clear lines record + linesBursts.clear(); + samplesBursts.clear(); + + // Check the single burst record case + if(theBurstRecords.size() == 1) + { + linesBursts.push_back(std::make_pair(theBurstRecords.front().startLine,theBurstRecords.front().endLine)); + samplesBursts.push_back(std::make_pair(theBurstRecords.front().startLine,theBurstRecords.front().endLine)); + return false; + } + + + ///////// deburst operation //////// + // Process each burst + std::vector<BurstRecordType>::const_iterator it = theBurstRecords.begin(); + // Correct since we have at least 2 bursts records + std::vector<BurstRecordType>::const_iterator next = it+1; + std::vector<BurstRecordType>::const_iterator itend = theBurstRecords.end(); + + unsigned long currentStart = it->startLine; + TimeType deburstAzimuthStartTime = it->azimuthStartTime; + + unsigned long deburstEndLine = 0; + + samples = std::make_pair(it->startSample, it->endSample); + + // Store halfLineOverlapBegin/End + unsigned long * halfLineOverlapBegin = new unsigned long[theBurstRecords.size()]; + unsigned long * halfLineOverlapEnd = new unsigned long[theBurstRecords.size()]; + + halfLineOverlapBegin[0] = 0; + + unsigned int counterBegin = 1; + unsigned int counterEnd = 0; + + for(; next!= itend ;++it,++next) + { + DurationType timeOverlapEnd = (it->azimuthStopTime - next->azimuthStartTime); + + unsigned long overlapLength = timeOverlapEnd/theAzimuthTimeInterval; + + halfLineOverlapEnd[counterEnd] = overlapLength/2; + TimeType endTimeInNextBurst = it->azimuthStopTime-(halfLineOverlapEnd[counterEnd]-1)*theAzimuthTimeInterval; + + halfLineOverlapBegin[counterBegin] = std::floor(0.5+(endTimeInNextBurst-next->azimuthStartTime)/theAzimuthTimeInterval); + + unsigned long currentStop = it->endLine-halfLineOverlapEnd[counterEnd]; + + deburstEndLine+= currentStop - currentStart + 1; // +1 because currentStart/Stop are both valids + + lines.push_back(std::make_pair(currentStart,currentStop)); + + currentStart = next->startLine+halfLineOverlapBegin[counterBegin]; + + // Find the first and last valid sampleburst + if (it->startSample > samples.first) + { + samples.first = it->startSample; + } + if (it->endSample < samples.second) + { + samples.second = it->endSample; + } + + + ++counterBegin; + ++counterEnd; + } + + halfLineOverlapEnd[theBurstRecords.size() - 1] = 0; + + TimeType deburstAzimuthStopTime = it->azimuthStopTime; + deburstEndLine+=it->endLine - currentStart; + + lines.push_back(std::make_pair(currentStart,it->endLine)); + + if (it->startSample > samples.first) + { + samples.first = it->startSample; + } + if (it->endSample < samples.second) + { + samples.second = it->endSample; + } + + // Now, update other metadata accordingly + std::vector<GCPRecordType> deburstGCPs; + + // Now move GCPs + for(std::vector<GCPRecordType>::iterator gcpIt = theGCPRecords.begin(); gcpIt!=theGCPRecords.end();++gcpIt) + { + GCPRecordType currentGCP = *gcpIt; + unsigned long newLine=0; + + unsigned long gcpLine = std::floor(currentGCP.imPt.y+0.5); + unsigned long gcpSample = std::floor(currentGCP.imPt.x+0.5); + + // Be careful about fractional part of GCPs + double fractionalLines = currentGCP.imPt.y - gcpLine; + double fractionalSamples = currentGCP.imPt.x - gcpSample; + + bool linesOk = imageLineToDeburstLine(lines,gcpLine,newLine); + + // Gcp into valid samples + unsigned long newSample = gcpSample; + + if (linesOk && gcpSample >= samples.first && gcpSample <= samples.second) + { + newSample -= samples.first; // Offset with first valid sample + currentGCP.imPt.y = newLine + fractionalLines; + currentGCP.imPt.x = newSample + fractionalSamples; + deburstGCPs.push_back(currentGCP); + } + } + + theGCPRecords.swap(deburstGCPs); + + ///// linesBursts and samplesBursts (into Burst geometry) ///// + std::vector<BurstRecordType>::const_iterator itBursts = theBurstRecords.begin(); + std::vector<std::pair<unsigned long,unsigned long> >::const_iterator itlines = lines.begin(); + + unsigned int counter = 0; + + for(; itBursts!= theBurstRecords.end() ;++itBursts) + { + unsigned long currentStart_L = halfLineOverlapBegin[counter]; + unsigned long currentStop_L = itBursts->endLine - itBursts->startLine - halfLineOverlapEnd[counter]; + linesBursts.push_back(std::make_pair(currentStart_L, currentStop_L)); + + unsigned long currentStart_S = 0; + unsigned long currentStop_S = samples.second-samples.first; + + if (itBursts->startSample < samples.first) + { + currentStart_S = samples.first - itBursts->startSample; + } + currentStop_S += currentStart_S; + + samplesBursts.push_back(std::make_pair(currentStart_S, currentStop_S)); + + ++counter; + } + + // Clear the previous burst records + theBurstRecords.clear(); + + // Create the single burst + BurstRecordType deburstBurst; + deburstBurst.startLine = 0; + deburstBurst.azimuthStartTime = deburstAzimuthStartTime; + deburstBurst.endLine = deburstEndLine; + deburstBurst.azimuthStopTime = deburstAzimuthStopTime; + deburstBurst.startSample = 0; + deburstBurst.endSample = samples.second - samples.first; + + theBurstRecords.push_back(deburstBurst); + + // Adapt general metadata : theNearRangeTime, first_time_line, last_time_line + redaptMedataAfterDeburst = true; + theFirstLineTime = deburstBurst.azimuthStartTime; + theLastLineTime = deburstBurst.azimuthStopTime; + + theNearRangeTime += samples.first*(1/theRangeSamplingRate); + + // Free Memory + delete [] halfLineOverlapBegin; + delete [] halfLineOverlapEnd; + + return true; +} + + bool ossimSarSensorModel::imageLineToDeburstLine(const std::vector<std::pair<unsigned long,unsigned long> >& lines, unsigned long imageLine, unsigned long & deburstLine) { std::vector<std::pair<unsigned long,unsigned long> >::const_iterator vit = lines.begin(); diff --git a/Modules/ThirdParty/OssimPlugins/test/ossimSentinel1ModelTest.cpp b/Modules/ThirdParty/OssimPlugins/test/ossimSentinel1ModelTest.cpp index ca968e66dfa844a0bddafd6f4088814d68b91877..698519844650f95d5ca81885c017cffacea60d78 100644 --- a/Modules/ThirdParty/OssimPlugins/test/ossimSentinel1ModelTest.cpp +++ b/Modules/ThirdParty/OssimPlugins/test/ossimSentinel1ModelTest.cpp @@ -109,9 +109,10 @@ int main(int argc, char * argv[]) ; std::vector<std::pair<unsigned long, unsigned long> > deburstLines; + std::pair<unsigned long, unsigned long> deburstSamples; std::cout<<"Trying to deburst data ..."<<std::endl; - bool deburstOk = sensor->deburst(deburstLines); + bool deburstOk = sensor->deburst(deburstLines, deburstSamples); std::cout<<"Deburst succeed: "<<(deburstOk?"yes":"no")<<std::endl; if(deburstOk)