From b6b669a479a2367c538c34b6eb4b93afda38ce46 Mon Sep 17 00:00:00 2001 From: Guillaume Pasero <guillaume.pasero@c-s.fr> Date: Thu, 6 Feb 2020 17:52:50 +0100 Subject: [PATCH] ENH: parse RPC --- .../include/otbImageMetadataInterfaceBase.h | 2 + .../include/otbMetadataSupplierInterface.h | 38 +++++++++++++++- .../src/otbImageMetadataInterfaceBase.cxx | 43 +++++++++++++++---- .../src/otbPleiadesImageMetadataInterface.cxx | 15 +------ Modules/IO/IOGDAL/src/otbGDALImageIO.cxx | 38 ++++++++-------- .../IO/ImageIO/include/otbImageFileReader.hxx | 5 +-- 6 files changed, 94 insertions(+), 47 deletions(-) diff --git a/Modules/Core/Metadata/include/otbImageMetadataInterfaceBase.h b/Modules/Core/Metadata/include/otbImageMetadataInterfaceBase.h index 8a83263e28..5074efe9a0 100644 --- a/Modules/Core/Metadata/include/otbImageMetadataInterfaceBase.h +++ b/Modules/Core/Metadata/include/otbImageMetadataInterfaceBase.h @@ -234,6 +234,8 @@ public: double& Fetch(const MetadataSupplierInterface * mds, const char *path, MDNum key, int band=-1); + boost::any& FetchRPC(const MetadataSupplierInterface * mds); + protected: ImageMetadataInterfaceBase(); ~ImageMetadataInterfaceBase() override diff --git a/Modules/Core/Metadata/include/otbMetadataSupplierInterface.h b/Modules/Core/Metadata/include/otbMetadataSupplierInterface.h index 369eb5eb04..f726cfd3af 100644 --- a/Modules/Core/Metadata/include/otbMetadataSupplierInterface.h +++ b/Modules/Core/Metadata/include/otbMetadataSupplierInterface.h @@ -27,7 +27,7 @@ #include <string> #include "otbStringUtils.h" #include "otbMacro.h" -//#include "otbStringUtilities.h" +#include "otbStringUtilities.h" namespace otb { @@ -99,9 +99,43 @@ public: } } + /** Parse a metadata value to a std::vector, + * If size>=0, then the final std::vector size is checked and an exception + * is raised if it doesn't match the given size.*/ + template < typename T> std::vector<T> GetAsVector(const char *path, const char sep=' ', int size=-1) const + { + const char * ret = GetMetadataValue(path); + if (ret == nullptr) + { + otbGenericExceptionMacro(MissingMetadataException,<<"Missing metadata '"<<path<<"'") + } + string_view value(ret); + string_view filt_value = rstrip(lstrip(value,"[ "), "] "); + std::vector<T> output; + typedef part_range<splitter_on_delim> range_type; + const range_type parts = split_on(filt_value, sep); + for (auto const& part : parts) + { + // TODO: check if we can use lexical_cast on a string_view + std::string strPart = to<std::string>(part, "casting string_view to std::string"); + try + { + output.push_back(boost::lexical_cast<T>(strPart)); + } + catch (boost::bad_lexical_cast&) + { + otbGenericExceptionMacro(MissingMetadataException,<<"Bad metadata vector element in '"<<path<<"', got :"<<part) + } + } + if ((size >= 0) and (output.size() != (size_t)size)) + { + otbGenericExceptionMacro(MissingMetadataException,<<"Bad number of elements in vector '"<<path<<"', expected "<<size<< ", got "<<output.size()) + } + return output; + } + }; -// Specialization of GetAs // TODO : for complex types ... } // end namespace otb diff --git a/Modules/Core/Metadata/src/otbImageMetadataInterfaceBase.cxx b/Modules/Core/Metadata/src/otbImageMetadataInterfaceBase.cxx index 4b274e1945..91c3c79404 100644 --- a/Modules/Core/Metadata/src/otbImageMetadataInterfaceBase.cxx +++ b/Modules/Core/Metadata/src/otbImageMetadataInterfaceBase.cxx @@ -22,6 +22,7 @@ #include "otbImageMetadataInterfaceBase.h" #include "otbNoDataHelper.h" +#include "otbGeometryMetadata.h" #include "itkMetaDataObject.h" #include "itksys/SystemTools.hxx" @@ -516,14 +517,6 @@ void ImageMetadataInterfaceBase::PrintMetadata(std::ostream& os, itk::Indent ind kwl.Print(os); break; } - case MetaDataKey::TIMAGEMETADATA: - { - ImageMetadata imd; - itk::ExposeMetaData<ImageMetadata>(dict2, keys[itkey], imd); - os << indent << "---> " << keys[itkey] << " = " << std::endl; - os << imd; - break; - } // case MetaDataKey::TVECTORDATAKEYWORDLIST: // itk::ExposeMetaData<VectorDataKeywordlist>(dict2, keys[itkey], vectorDataKeywordlistValue); // @@ -652,6 +645,40 @@ ImageMetadataInterfaceBase::Fetch( return m_ImageMetadata.NumericKeys[key]; } +boost::any& ImageMetadataInterfaceBase::FetchRPC( + const MetadataSupplierInterface * mds) +{ + Projection::RPCParam rpcStruct; + rpcStruct.LineOffset = mds->GetAs<double>("RPC/LINE_OFF"); + rpcStruct.SampleOffset = mds->GetAs<double>("RPC/SAMP_OFF"); + rpcStruct.LatOffset = mds->GetAs<double>("RPC/LAT_OFF"); + rpcStruct.LonOffset = mds->GetAs<double>("RPC/LONG_OFF"); + rpcStruct.HeightOffset = mds->GetAs<double>("RPC/HEIGHT_OFF"); + + rpcStruct.LineScale = mds->GetAs<double>("RPC/LINE_SCALE"); + rpcStruct.SampleScale = mds->GetAs<double>("RPC/SAMP_SCALE"); + rpcStruct.LatScale = mds->GetAs<double>("RPC/LAT_SCALE"); + rpcStruct.LonScale = mds->GetAs<double>("RPC/LONG_SCALE"); + rpcStruct.HeightScale = mds->GetAs<double>("RPC/HEIGHT_SCALE"); + + std::vector<double> coeffs(20); + + coeffs = mds->GetAsVector<double>("RPC/LINE_NUM_COEFF",' ',20); + std::copy(coeffs.begin(), coeffs.end(), rpcStruct.LineNum); + + coeffs = mds->GetAsVector<double>("RPC/LINE_DEN_COEFF",' ',20); + std::copy(coeffs.begin(), coeffs.end(), rpcStruct.LineDen); + + coeffs = mds->GetAsVector<double>("RPC/SAMP_NUM_COEFF",' ',20); + std::copy(coeffs.begin(), coeffs.end(), rpcStruct.SampleNum); + + coeffs = mds->GetAsVector<double>("RPC/SAMP_DEN_COEFF",' ',20); + std::copy(coeffs.begin(), coeffs.end(), rpcStruct.SampleDen); + + m_ImageMetadata.SensorGeometry.push_back(rpcStruct); + return m_ImageMetadata.SensorGeometry.back(); +} + // TODO: replace by template with Traits on metadata key } // end namespace otb diff --git a/Modules/Core/Metadata/src/otbPleiadesImageMetadataInterface.cxx b/Modules/Core/Metadata/src/otbPleiadesImageMetadataInterface.cxx index 32dc2c4067..4bde7f4b4e 100644 --- a/Modules/Core/Metadata/src/otbPleiadesImageMetadataInterface.cxx +++ b/Modules/Core/Metadata/src/otbPleiadesImageMetadataInterface.cxx @@ -1778,21 +1778,8 @@ bool PleiadesImageMetadataInterface::Parse(const MetadataSupplierInterface *mds) // fill RPC model if (m_ImageMetadata.StringKeys[MDStr::GeometricLevel] == "SENSOR") { - // check we have a RPC model - if (m_ImageMetadata.SensorGeometry.empty()) - { - otbGenericExceptionMacro(MissingMetadataException,<<"No geometric model found") - } - try - { - boost::any_cast<Projection::RPCParam>(m_ImageMetadata.SensorGeometry[0]); - } - catch(boost::bad_any_cast&) - { - otbGenericExceptionMacro(MissingMetadataException,<<"Not a RPCParam") - } + FetchRPC(mds); } - return true; } diff --git a/Modules/IO/IOGDAL/src/otbGDALImageIO.cxx b/Modules/IO/IOGDAL/src/otbGDALImageIO.cxx index 53a89de3f9..3aa1c20a2d 100644 --- a/Modules/IO/IOGDAL/src/otbGDALImageIO.cxx +++ b/Modules/IO/IOGDAL/src/otbGDALImageIO.cxx @@ -670,6 +670,7 @@ void GDALImageIO::InternalReadImageInformation() // Initialize the ImageMetadata structure ImageMetadata imd; + m_Imd = imd; // Report the typical block size if possible if (dataset->GetRasterCount() > 0) @@ -696,8 +697,8 @@ void GDALImageIO::InternalReadImageInformation() itk::EncapsulateMetaData<unsigned int>(dict, MetaDataKey::TileHintX, blockSizeX); itk::EncapsulateMetaData<unsigned int>(dict, MetaDataKey::TileHintY, blockSizeY); - imd.TileHintX = blockSizeX; - imd.TileHintY = blockSizeY; + m_Imd.TileHintX = blockSizeX; + m_Imd.TileHintY = blockSizeY; } } @@ -707,7 +708,7 @@ void GDALImageIO::InternalReadImageInformation() itk::EncapsulateMetaData<IOComponentType>(dict, MetaDataKey::DataType, this->GetComponentType()); - imd.DataType = this->GetComponentType(); + m_Imd.DataType = this->GetComponentType(); /* -------------------------------------------------------------------- */ /* Get Spacing */ @@ -769,14 +770,14 @@ void GDALImageIO::InternalReadImageInformation() itk::EncapsulateMetaData<std::string>(dict, MetaDataKey::ProjectionRefKey, static_cast<std::string>(pszPrettyWkt)); - imd.ProjectionRef = std::string(pszPrettyWkt); + m_Imd.ProjectionRef = std::string(pszPrettyWkt); CPLFree(pszPrettyWkt); } else { itk::EncapsulateMetaData<std::string>(dict, MetaDataKey::ProjectionRefKey, static_cast<std::string>(pszProjection)); - imd.ProjectionRef = std::string(pszProjection); + m_Imd.ProjectionRef = std::string(pszProjection); } if (pSR != nullptr) @@ -815,7 +816,7 @@ void GDALImageIO::InternalReadImageInformation() } itk::EncapsulateMetaData<std::string>(dict, MetaDataKey::GCPProjectionKey, gcpProjectionKey); - imd.GCPProjection = gcpProjectionKey; + m_Imd.GCPProjection = gcpProjectionKey; if (gcpProjectionKey.empty()) { @@ -848,7 +849,7 @@ void GDALImageIO::InternalReadImageInformation() key = lStream.str(); itk::EncapsulateMetaData<OTB_GCP>(dict, key, pOtbGCP); - imd.GCPs.push_back(pOtbGCP); + m_Imd.GCPs.push_back(pOtbGCP); } } @@ -864,7 +865,7 @@ void GDALImageIO::InternalReadImageInformation() for (int cpt = 0; cpt < 6; ++cpt) { VadfGeoTransform.push_back(adfGeoTransform[cpt]); - imd.GeoTransform[cpt] = adfGeoTransform[cpt]; + m_Imd.GeoTransform[cpt] = adfGeoTransform[cpt]; } itk::EncapsulateMetaData<MetaDataKey::VectorType>(dict, MetaDataKey::GeoTransformKey, VadfGeoTransform); @@ -986,8 +987,8 @@ void GDALImageIO::InternalReadImageInformation() VGeo.push_back(GeoY); itk::EncapsulateMetaData<MetaDataKey::VectorType>(dict, MetaDataKey::UpperLeftCornerKey, VGeo); - imd.ULX = GeoX; - imd.ULY = GeoY; + m_Imd.ULX = GeoX; + m_Imd.ULY = GeoY; VGeo.clear(); @@ -996,8 +997,8 @@ void GDALImageIO::InternalReadImageInformation() VGeo.push_back(GeoY); itk::EncapsulateMetaData<MetaDataKey::VectorType>(dict, MetaDataKey::UpperRightCornerKey, VGeo); - imd.URX = GeoX; - imd.URY = GeoY; + m_Imd.URX = GeoX; + m_Imd.URY = GeoY; VGeo.clear(); @@ -1006,8 +1007,8 @@ void GDALImageIO::InternalReadImageInformation() VGeo.push_back(GeoY); itk::EncapsulateMetaData<MetaDataKey::VectorType>(dict, MetaDataKey::LowerLeftCornerKey, VGeo); - imd.LLX = GeoX; - imd.LLY = GeoY; + m_Imd.LLX = GeoX; + m_Imd.LLY = GeoY; VGeo.clear(); @@ -1016,8 +1017,8 @@ void GDALImageIO::InternalReadImageInformation() VGeo.push_back(GeoY); itk::EncapsulateMetaData<MetaDataKey::VectorType>(dict, MetaDataKey::LowerRightCornerKey, VGeo); - imd.LRX = GeoX; - imd.LRY = GeoY; + m_Imd.LRX = GeoX; + m_Imd.LRY = GeoY; VGeo.clear(); @@ -1109,7 +1110,7 @@ void GDALImageIO::InternalReadImageInformation() bmd.NoDataFlag = false; bmd.NoDataValue = 0.0; } - imd.Bands.push_back(bmd); + m_Imd.Bands.push_back(bmd); } if (noDataFound) @@ -1117,9 +1118,6 @@ void GDALImageIO::InternalReadImageInformation() itk::EncapsulateMetaData<MetaDataKey::BoolVectorType>(dict, MetaDataKey::NoDataValueAvailable, isNoDataAvailable); itk::EncapsulateMetaData<MetaDataKey::VectorType>(dict, MetaDataKey::NoDataValue, noDataValues); } - - // give the ImageMetadata to ImageFileReader - itk::EncapsulateMetaData<ImageMetadata>(dict, MetaDataKey::ImageMetadataKey, imd); } bool GDALImageIO::CanWriteFile(const char* name) diff --git a/Modules/IO/ImageIO/include/otbImageFileReader.hxx b/Modules/IO/ImageIO/include/otbImageFileReader.hxx index 3131167366..7971fba593 100644 --- a/Modules/IO/ImageIO/include/otbImageFileReader.hxx +++ b/Modules/IO/ImageIO/include/otbImageFileReader.hxx @@ -391,9 +391,8 @@ void ImageFileReader<TOutputImage, ConvertPixelTraits>::GenerateOutputInformatio // detect Image supporting new ImageMetadata ImageCommons* img_common = dynamic_cast<ImageCommons*>(this->GetOutput()); - // Initialize ImageMetadata from ImageIO - ImageMetadata imd; - itk::ExposeMetaData<ImageMetadata>(dict, MetaDataKey::ImageMetadataKey, imd); + // Get ImageMetadata from ImageIO + ImageMetadata imd = m_ImageIO->GetImageMetadata(); if (!m_KeywordListUpToDate && !m_FilenameHelper->GetSkipGeom()) { -- GitLab