diff --git a/CMake/FindNumpy.cmake b/CMake/FindNumpy.cmake index 764f57497c1dfbf43dda09118bc8e538fb513047..b53aa7c18a7d8bc7e3f1a1ef39ef4c400b7ca9cb 100644 --- a/CMake/FindNumpy.cmake +++ b/CMake/FindNumpy.cmake @@ -5,7 +5,7 @@ # NUMPY_INCLUDE_DIR - where to find numpy/arrayobject.h, etc. EXEC_PROGRAM ("${PYTHON_EXECUTABLE}" - ARGS "-c 'import numpy; print numpy.get_include()'" + ARGS "${CMAKE_SOURCE_DIR}/CMake/otbTestNumpy.py" OUTPUT_VARIABLE NUMPY_INCLUDE_DIR RETURN_VALUE NUMPY_NOT_FOUND) diff --git a/CMake/otbTestNumpy.py b/CMake/otbTestNumpy.py new file mode 100644 index 0000000000000000000000000000000000000000..6b9a80111c4a895d0069dc9639c9701628c32e49 --- /dev/null +++ b/CMake/otbTestNumpy.py @@ -0,0 +1,2 @@ +import numpy +print numpy.get_include() diff --git a/Modules/Adapters/BoostAdapters/include/otbStringUtils.h b/Modules/Adapters/BoostAdapters/include/otbStringUtils.h index 9c675f695fd19226845e538a84e4c6a4cba3cd7b..341b231eb2b73ce2895635aa609105b62234dea0 100644 --- a/Modules/Adapters/BoostAdapters/include/otbStringUtils.h +++ b/Modules/Adapters/BoostAdapters/include/otbStringUtils.h @@ -40,7 +40,7 @@ Res LexicalCast(In const& in, std::string const& kind) { } catch (boost::bad_lexical_cast &) { std::ostringstream oss; - oss << "Cannot decode " << in << " as this is not a valid value for " << kind; + oss << "Cannot decode '" << in << "' as this is not a valid value for '" << kind << "'"; throw std::runtime_error(oss.str()); } } diff --git a/Modules/Applications/AppSARCalibration/app/otbSarRadiometricCalibration.cxx b/Modules/Applications/AppSARCalibration/app/otbSarRadiometricCalibration.cxx index b3068c927ac1452f6b48af361950def7f55d29fb..3aa03c21a0f7bfc511697246794bf35695ae6300 100644 --- a/Modules/Applications/AppSARCalibration/app/otbSarRadiometricCalibration.cxx +++ b/Modules/Applications/AppSARCalibration/app/otbSarRadiometricCalibration.cxx @@ -24,7 +24,6 @@ namespace otb { namespace Wrapper { - class SarRadiometricCalibration : public Application { public: @@ -40,17 +39,17 @@ public: itkTypeMacro(SarRadiometricCalibration, otb::Application); typedef otb::SarRadiometricCalibrationToImageFilter<ComplexFloatImageType, - ComplexFloatImageType> CalibrationFilterType; + FloatImageType> CalibrationFilterType; private: void DoInit() { SetName("SarRadiometricCalibration"); - SetDescription("Perform SAR calibration on input complex images"); + SetDescription("Perform radiometric calibration of SAR images. Following sensors are supported: TerraSAR-X, Sentinel1 and Radarsat-2.Both Single Look Complex(SLC) and detected products are supported as input.\n"); // Documentation SetDocName("SAR Radiometric calibration"); - SetDocLongDescription("This application performs SAR calibration on input complex images."); + SetDocLongDescription("The objective of SAR calibration is to provide imagery in which the pixel values can be directly related to the radar backscatter of the scene. This application allows to compute Sigma Naught (Radiometric Calibration) for TerraSAR-X, Sentinel1 L1 and Radarsat-2 sensors. Metadata are automatically retrieved from image products.The application supports complex and non-complex images (SLC or detected products).\n"); SetDocLimitations("None"); SetDocAuthors("OTB-Team"); SetDocSeeAlso(" "); @@ -58,25 +57,39 @@ private: AddDocTag(Tags::Calibration); AddDocTag(Tags::SAR); - AddParameter(ParameterType_ComplexInputImage, "in", "Input Complex Image"); + AddParameter(ParameterType_ComplexInputImage, "in", "Input Image"); SetParameterDescription("in", "Input complex image"); - AddParameter(ParameterType_ComplexOutputImage, "out", "Output Image"); - SetParameterDescription("out", "Output calibrated complex image"); + AddParameter(ParameterType_OutputImage, "out", "Output Image"); + SetParameterDescription("out", "Output calibrated image. This image contains the backscatter (sigmaNought) of the input image."); AddRAMParameter(); AddParameter(ParameterType_Empty, "noise", "Disable Noise"); - SetParameterDescription("noise", "Flag to disable noise"); + SetParameterDescription("noise", "Flag to disable noise. For 5.2.0 release, the noise values are only read by TerraSARX product."); MandatoryOff("noise"); + AddParameter(ParameterType_Choice, "lut", "Lookup table sigma /gamma/ beta/ DN."); + SetParameterDescription("lut", "Lookup table values are not available with all SAR products. Products that provide lookup table with metadata are: Sentinel1, Radarsat2."); + AddChoice("lut.sigma", "Use sigma nought lookup"); + SetParameterDescription("lut.sigma","Use Sigma nought lookup value from product metadata"); + AddChoice("lut.gamma", "Use gamma nought lookup"); + SetParameterDescription("lut.gamma","Use Gamma nought lookup value from product metadata"); + AddChoice("lut.beta", "Use beta nought lookup"); + SetParameterDescription("lut.beta","Use Beta nought lookup value from product metadata"); + AddChoice("lut.dn", "Use DN value lookup"); + SetParameterDescription("lut.dn","Use DN value lookup value from product metadata"); + SetDefaultParameterInt("lut", 0); + // Doc example parameter settings SetDocExampleParameterValue("in", "RSAT_imagery_HH.tif"); SetDocExampleParameterValue("out", "SarRadiometricCalibration.tif" ); } void DoUpdateParameters() - { } + { + + } void DoExecute() { @@ -92,11 +105,19 @@ private: m_CalibrationFilter->SetEnableNoise(false); } + short lut = 0; + + lut = GetParameterInt("lut"); + + m_CalibrationFilter->SetLookupSelected(lut); + // Set the output image - SetParameterComplexOutputImage("out", m_CalibrationFilter->GetOutput()); + SetParameterOutputImage("out", m_CalibrationFilter->GetOutput()); + } CalibrationFilterType::Pointer m_CalibrationFilter; + }; } } diff --git a/Modules/Applications/AppSARCalibration/test/CMakeLists.txt b/Modules/Applications/AppSARCalibration/test/CMakeLists.txt index 285dd10621352c2af1047c31a52db69076a4e299..02e9e48f3f4e073a84a970187f66ba67e308842a 100644 --- a/Modules/Applications/AppSARCalibration/test/CMakeLists.txt +++ b/Modules/Applications/AppSARCalibration/test/CMakeLists.txt @@ -1,2 +1,17 @@ otb_module_test() #----------- SarRadiometricCalibration TESTS ---------------- +otb_test_application(NAME apTvRaSarRadiometricCalibration_SENTINEL1 + APP SarRadiometricCalibration + OPTIONS -in ${INPUTDATA}/SENTINEL1_SLC_S6_1S_extract_300_300.tif?&geom=${INPUTDATA}/SENTINEL1_SLC_S6_1S_extract_300_300.geom + -out ${TEMP}/apTvRaSarRadiometricCalibration_SENTINEL1.tif + VALID --compare-image ${NOTOL} + ${BASELINE}/raTvSarRadiometricCalibration_SENTINEL1.tif + ${TEMP}/apTvRaSarRadiometricCalibration_SENTINEL1.tif ) + +otb_test_application(NAME apTvRaSarRadiometricCalibration_RADARSAT2 + APP SarRadiometricCalibration + OPTIONS -in ${INPUTDATA}/RADARSAT2_ALTONA_300_300_VV.tif?&geom=${INPUTDATA}/RADARSAT2_ALTONA_300_300_VV.geom + -out ${TEMP}/apTvRaSarRadiometricCalibration_RADARSAT2.tif + VALID --compare-image ${NOTOL} + ${BASELINE}/raTvSarRadiometricCalibration_RADARSAT2.tif + ${TEMP}/apTvRaSarRadiometricCalibration_RADARSAT2.tif ) diff --git a/Modules/Core/Metadata/include/otbRadarsat2ImageMetadataInterface.h b/Modules/Core/Metadata/include/otbRadarsat2ImageMetadataInterface.h new file mode 100644 index 0000000000000000000000000000000000000000..46439ca65227e1671ad6cfb565d2a0c6786da27b --- /dev/null +++ b/Modules/Core/Metadata/include/otbRadarsat2ImageMetadataInterface.h @@ -0,0 +1,203 @@ +/*========================================================================= + + Program: ORFEO Toolbox + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved. + See OTBCopyright.txt for details. + + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __otbRadarsat2ImageMetadataInterface_h +#define __otbRadarsat2ImageMetadataInterface_h + +#include "otbSarImageMetadataInterface.h" + +namespace otb +{ +/** \class Radarsat2ImageMetadataInterface + * + * \brief Creation of an "otb" Radarsat2ImageMetadataInterface that gets metadata. + * + * + * \ingroup OTBMetadata + */ + +class ITK_ABI_EXPORT Radarsat2ImageMetadataInterface : public SarImageMetadataInterface +{ +public: + + typedef Radarsat2ImageMetadataInterface Self; + typedef SarImageMetadataInterface Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(Radarsat2ImageMetadataInterface, SarImageMetadataInterface); + + typedef Superclass::ImageType ImageType; + typedef Superclass::MetaDataDictionaryType MetaDataDictionaryType; + typedef Superclass::VectorType VectorType; + typedef Superclass::VariableLengthVectorType VariableLengthVectorType; + typedef Superclass::ImageKeywordlistType ImageKeywordlistType; + typedef Superclass::LookupDataPointerType LookupDataPointerType; +// typedef Radarsat2CalibrationLookupData::Pointer LookupDataPointerType; + + /*ImageMetadataInterfaceBase pure virtuals */ + /** Get the imaging production day from the ossim metadata : DATASET_PRODUCTION_DATE metadata variable */ + int GetProductionDay() const; + + /** Get the imaging production month from the ossim metadata : DATASET_PRODUCTION_DATE metadata variable */ + int GetProductionMonth() const; + + /** Get the imaging production year from the ossim metadata : DATASET_PRODUCTION_DATE metadata variable */ + int GetProductionYear() const; + + /** check sensor ID */ + bool CanRead() const; + + int GetDay() const; + + int GetMonth() const; + + int GetYear() const; + + int GetHour() const; + + int GetMinute() const; + + UIntVectorType GetDefaultDisplay() const; + + /*SarImageMetadataInterface pure virutals rituals */ + double GetPRF() const; + + double GetRSF() const; + + double GetRadarFrequency() const; + + double GetCenterIncidenceAngle() const; + + /*get lookup data for calulating backscatter */ + void CreateCalibrationLookupData(const short type); + + +protected: + /* class constructor */ + Radarsat2ImageMetadataInterface(); + + /* class desctructor */ + virtual ~Radarsat2ImageMetadataInterface() {} + +private: + Radarsat2ImageMetadataInterface(const Self &); //purposely not implemented + void operator =(const Self&); //purposely not implemented + +/* Helper function to parse date and time into a std::vector<std::string> + * using boost::split() expect date time in yyyy-mm-ddThh:mm:ss.ms + * the date-time string is to be found in keywordlist with key 'key' + * fills argument dateFields of type std::vector<std::string> which is mutable! + * TODO: move this method into base class + */ + void ParseDateTime(const char* key, std::vector<int>& dateFields) const; + + mutable std::vector<int> m_ProductionDateFields; + mutable std::vector<int> m_AcquisitionDateFields; + +}; + + +class Radarsat2CalibrationLookupData : public SarCalibrationLookupData +{ + +public: + + /** Standard typedefs */ + typedef Radarsat2CalibrationLookupData Self; + typedef SarCalibrationLookupData Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; + + /** Creation through the object factory */ + itkNewMacro(Self); + + /** RTTI */ + itkTypeMacro(Radarsat2CalibrationLookupData, SarCalibrationLookupData); + + typedef itk::IndexValueType IndexValueType; + + typedef std::vector<float> GainListType; + + + Radarsat2CalibrationLookupData() + : m_Offset(0) + { + + } + + virtual ~Radarsat2CalibrationLookupData() + { + + } + + void InitParameters(short type, int offset, GainListType gains) + { + this->SetType(type); + m_Offset = offset; + m_Gains = gains; + } + + double GetValue(const IndexValueType x, const IndexValueType itkNotUsed(y)) + { + double lutVal = 1.0; + + const size_t pos = x + m_Offset; + if(pos < m_Gains.size()) + { + lutVal = m_Gains[pos]; + } + else + { + //itkExceptionMacro( << "error: (pos < list.size() )" << pos << " < " << list.size()) + } + return lutVal; + } + + void PrintSelf(std::ostream & os, itk::Indent indent) const + { + os << indent << " offset:'" << m_Offset << "'" << std::endl; + os << " referenceNoiseLevel.gain: " << std::endl; + std::vector<float>::const_iterator it = m_Gains.begin(); + while (it != m_Gains.end()) + { + os << (*it) << " "; + ++it; + } + os << std::endl; + + Superclass::PrintSelf(os, indent); + } + +private: + + Radarsat2CalibrationLookupData(const Self&); //purposely not implemented + void operator =(const Self&); //purposely not implemented + + GainListType m_Gains; + int m_Offset; + + +}; + +} // end namespace otb + +#endif diff --git a/Modules/Core/Metadata/include/otbRadarsat2ImageMetadataInterfaceFactory.h b/Modules/Core/Metadata/include/otbRadarsat2ImageMetadataInterfaceFactory.h new file mode 100644 index 0000000000000000000000000000000000000000..2aeb8a8f583be04f5b8fcb0f022015daea6d283f --- /dev/null +++ b/Modules/Core/Metadata/include/otbRadarsat2ImageMetadataInterfaceFactory.h @@ -0,0 +1,68 @@ +/*========================================================================= + + Program: ORFEO Toolbox + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved. + See OTBCopyright.txt for details. + + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __otbRadarsat2ImageMetadataInterfaceFactory_h +#define __otbRadarsat2ImageMetadataInterfaceFactory_h + +#include "itkObjectFactoryBase.h" + +namespace otb +{ +/** \class Radarsat2ImageMetadataInterfaceFactory + * \brief Creating an instance of a ImageMetadataInterface object using object factory. + * + * \ingroup OTBMetadata + */ +class ITK_EXPORT Radarsat2ImageMetadataInterfaceFactory : public itk::ObjectFactoryBase +{ +public: + /** Standard class typedefs. */ + typedef Radarsat2ImageMetadataInterfaceFactory Self; + typedef itk::ObjectFactoryBase Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; + + /** Class methods used to interface with the registered factories. */ + virtual const char* GetITKSourceVersion(void) const; + virtual const char* GetDescription(void) const; + + /** Method for class instantiation. */ + itkFactorylessNewMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(Radarsat2ImageMetadataInterfaceFactory, itk::ObjectFactoryBase); + + /** Register one factory of this type */ + static void RegisterOneFactory(void) + { + Pointer factory = Radarsat2ImageMetadataInterfaceFactory::New(); + itk::ObjectFactoryBase::RegisterFactory(factory); + } + +protected: + Radarsat2ImageMetadataInterfaceFactory(); + virtual ~Radarsat2ImageMetadataInterfaceFactory(); + +private: + Radarsat2ImageMetadataInterfaceFactory(const Self &); //purposely not implemented + void operator =(const Self&); //purposely not implemented + +}; + +} // end namespace otb + +#endif diff --git a/Modules/Core/Metadata/src/CMakeLists.txt b/Modules/Core/Metadata/src/CMakeLists.txt index 77dad8c9f5ae67af5ba6ed436ab72c0954abf9a9..a81509ee9cba75db47fa7fb168357b91525385f2 100644 --- a/Modules/Core/Metadata/src/CMakeLists.txt +++ b/Modules/Core/Metadata/src/CMakeLists.txt @@ -39,6 +39,9 @@ set(OTBMetadata_SRC otbSentinel1ImageMetadataInterfaceFactory.cxx otbSentinel1ImageMetadataInterface.cxx + otbRadarsat2ImageMetadataInterfaceFactory.cxx + otbRadarsat2ImageMetadataInterface.cxx + otbNoDataHelper.cxx ) diff --git a/Modules/Core/Metadata/src/otbImageMetadataInterfaceFactory.cxx b/Modules/Core/Metadata/src/otbImageMetadataInterfaceFactory.cxx index 4b554bf6267ff9239d5e2beada80d77a0bae57df..31ff54ac85a44fed7046c77541c120fc79204146 100644 --- a/Modules/Core/Metadata/src/otbImageMetadataInterfaceFactory.cxx +++ b/Modules/Core/Metadata/src/otbImageMetadataInterfaceFactory.cxx @@ -33,6 +33,7 @@ // SAR Sensors #include "otbTerraSarImageMetadataInterfaceFactory.h" #include "otbSentinel1ImageMetadataInterfaceFactory.h" +#include "otbRadarsat2ImageMetadataInterfaceFactory.h" #include "itkMutexLock.h" #include "itkMutexLockHolder.h" @@ -112,7 +113,7 @@ ImageMetadataInterfaceFactory itk::ObjectFactoryBase::RegisterFactory(WorldView2ImageMetadataInterfaceFactory::New()); itk::ObjectFactoryBase::RegisterFactory(TerraSarImageMetadataInterfaceFactory::New()); itk::ObjectFactoryBase::RegisterFactory(Sentinel1ImageMetadataInterfaceFactory::New()); - + itk::ObjectFactoryBase::RegisterFactory(Radarsat2ImageMetadataInterfaceFactory::New()); firstTime = false; } } diff --git a/Modules/Core/Metadata/src/otbRadarsat2ImageMetadataInterface.cxx b/Modules/Core/Metadata/src/otbRadarsat2ImageMetadataInterface.cxx new file mode 100644 index 0000000000000000000000000000000000000000..748c45d65419a9b9dea843f12fed6d93ba3e4f00 --- /dev/null +++ b/Modules/Core/Metadata/src/otbRadarsat2ImageMetadataInterface.cxx @@ -0,0 +1,260 @@ +/*========================================================================= + + Program: ORFEO Toolbox + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved. + See OTBCopyright.txt for details. + + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include "otbSarImageMetadataInterface.h" +#include "otbRadarsat2ImageMetadataInterface.h" + +#include "otbMacro.h" +#include "itkMetaDataObject.h" +#include "otbImageKeywordlist.h" + +//useful constants +#include <otbMath.h> + +namespace otb +{ + +Radarsat2ImageMetadataInterface +::Radarsat2ImageMetadataInterface() +{ + +} + +bool +Radarsat2ImageMetadataInterface::CanRead() const +{ + std::string sensorID = GetSensorID(); + + if (sensorID.find("RADARSAT-2") != std::string::npos) + { + return true; + } + else + return false; +} + + +void +Radarsat2ImageMetadataInterface:: +CreateCalibrationLookupData(const short type) + { + std::string lut = "SigmaNought"; + + switch (type) + { + case SarCalibrationLookupData::BETA: + { + lut = "BetaNought"; + } + break; + + case SarCalibrationLookupData::GAMMA: + { + lut = "GammaNought"; + } + break; + + case SarCalibrationLookupData::DN: + { + lut = "DN"; + } + break; + + case SarCalibrationLookupData::SIGMA: + default: + { + lut = "SigmaNought"; + } + break; + } + + const ImageKeywordlistType imageKeywordlist = this->GetImageKeywordlist(); + const std::string key = "referenceNoiseLevel[" + lut + "].gain"; + + Radarsat2CalibrationLookupData::GainListType glist; + int offset = 0; + + Utils::ConvertStringToVector(imageKeywordlist.GetMetadataByKey("referenceNoiseLevel[" + lut + "].gain"), glist, "referenceNoiseLevel[" + lut + "].gain"); + + Utils::LexicalCast<int>(imageKeywordlist.GetMetadataByKey("referenceNoiseLevel[" + lut + "].offset"), "referenceNoiseLevel[" + lut + "].offset"); + + Radarsat2CalibrationLookupData::Pointer sarLut; + sarLut = Radarsat2CalibrationLookupData::New(); + sarLut->InitParameters(type, offset, glist); + this->SetCalibrationLookupData(sarLut); + +} + +void +Radarsat2ImageMetadataInterface +::ParseDateTime(const char* key, std::vector<int>& dateFields) const +{ + if(dateFields.size() < 1 ) + { + //parse from keyword list + if (!this->CanRead()) + { + itkExceptionMacro(<< "Invalid Metadata, not a valid product"); + } + + const ImageKeywordlistType imageKeywordlist = this->GetImageKeywordlist(); + if (!imageKeywordlist.HasKey(key)) + { + itkExceptionMacro( << "no key named '" << key << "'"); + } + + std::string date_time_str = imageKeywordlist.GetMetadataByKey(key); + date_time_str.resize(date_time_str.size() - 1); + Utils::ConvertStringToVector(date_time_str, dateFields, key, "-T:."); + } +} + +int +Radarsat2ImageMetadataInterface::GetYear() const +{ + int value = 0; + ParseDateTime("support_data.image_date", m_AcquisitionDateFields); + if(m_AcquisitionDateFields.size() > 0 ) + { + value = Utils::LexicalCast<int>( m_AcquisitionDateFields[0], "support_data.image_date(year)" ); + } + return value; +} + +int +Radarsat2ImageMetadataInterface::GetMonth() const +{ + int value = 0; + ParseDateTime("support_data.image_date", m_AcquisitionDateFields); + if(m_AcquisitionDateFields.size() > 1 ) + { + value = Utils::LexicalCast<int>( m_AcquisitionDateFields[1], "support_data.image_date(month)" ); + } + return value; +} + +int +Radarsat2ImageMetadataInterface::GetDay() const +{ + int value = 0; + ParseDateTime("support_data.image_date", m_AcquisitionDateFields); + if(m_AcquisitionDateFields.size() > 2 ) + { + value = Utils::LexicalCast<int>( m_AcquisitionDateFields[2], "support_data.image_date(day)" ); + } + return value; +} + +int +Radarsat2ImageMetadataInterface::GetHour() const +{ + int value = 0; + ParseDateTime("support_data.image_date", m_AcquisitionDateFields); + if(m_AcquisitionDateFields.size() > 3 ) + { + value = Utils::LexicalCast<int>( m_AcquisitionDateFields[3], "support_data.image_date(hour)" ); + } + return value; +} + +int +Radarsat2ImageMetadataInterface::GetMinute() const +{ + int value = 0; + ParseDateTime("support_data.image_date", m_AcquisitionDateFields); + if(m_AcquisitionDateFields.size() > 4 ) + { + value = Utils::LexicalCast<int>( m_AcquisitionDateFields[4], "support_data.image_date(minute)" ); + } + return value; +} + +int +Radarsat2ImageMetadataInterface::GetProductionYear() const +{ + int value = 0; + ParseDateTime("support_data.date", m_ProductionDateFields); + if(m_ProductionDateFields.size() > 0 ) + { + value = Utils::LexicalCast<int>( m_ProductionDateFields[0], "support_data.image_date(year)" ); + } + return value; + +} + +int +Radarsat2ImageMetadataInterface::GetProductionMonth() const +{ + int value = 0; + ParseDateTime("support_data.date", m_ProductionDateFields); + if(m_ProductionDateFields.size() > 1 ) + { + value = Utils::LexicalCast<int>( m_ProductionDateFields[1], "support_data.image_date(production month)" ); + } + return value; +} + +int +Radarsat2ImageMetadataInterface::GetProductionDay() const +{ + int value = 0; + ParseDateTime("support_data.date", m_ProductionDateFields); + if(m_ProductionDateFields.size() > 2 ) + { + value = Utils::LexicalCast<int>( m_ProductionDateFields[2], "support_data.image_date(production day)" ); + } + return value; +} + + +double +Radarsat2ImageMetadataInterface::GetPRF() const +{ + return 0; +} + +double +Radarsat2ImageMetadataInterface::GetRSF() const +{ + return 0; +} + +double +Radarsat2ImageMetadataInterface::GetRadarFrequency() const +{ + return 0; +} + +double +Radarsat2ImageMetadataInterface::GetCenterIncidenceAngle() const +{ + return 0; +} + +Radarsat2ImageMetadataInterface::UIntVectorType +Radarsat2ImageMetadataInterface:: +GetDefaultDisplay() const +{ + UIntVectorType rgb(3); + rgb[0] = 0; + rgb[1] = 0; + rgb[2] = 0; + return rgb; +} + +} // end namespace otb diff --git a/Modules/Core/Metadata/src/otbRadarsat2ImageMetadataInterfaceFactory.cxx b/Modules/Core/Metadata/src/otbRadarsat2ImageMetadataInterfaceFactory.cxx new file mode 100644 index 0000000000000000000000000000000000000000..e9f656cfc1ef64bdb6225559b6de5091d97c9f60 --- /dev/null +++ b/Modules/Core/Metadata/src/otbRadarsat2ImageMetadataInterfaceFactory.cxx @@ -0,0 +1,58 @@ +/*========================================================================= + + Program: ORFEO Toolbox + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved. + See OTBCopyright.txt for details. + + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + + +#include <typeinfo> +#include <cassert> + +#include "otbRadarsat2ImageMetadataInterfaceFactory.h" +#include "otbRadarsat2ImageMetadataInterface.h" + +#include "itkCreateObjectFunction.h" +#include "itkVersion.h" + +namespace otb +{ +Radarsat2ImageMetadataInterfaceFactory +::Radarsat2ImageMetadataInterfaceFactory() +{ + this->RegisterOverride("SarImageMetadataInterface", + "otbRadarsat2ImageMetadataInterface", + "Radarsat2 Metadata Interface", + 1, + itk::CreateObjectFunction<Radarsat2ImageMetadataInterface>::New()); +} + +Radarsat2ImageMetadataInterfaceFactory +::~Radarsat2ImageMetadataInterfaceFactory() +{ +} + +const char* +Radarsat2ImageMetadataInterfaceFactory::GetITKSourceVersion(void) const +{ + return ITK_SOURCE_VERSION; +} + +const char* +Radarsat2ImageMetadataInterfaceFactory::GetDescription() const +{ + return "Radarsat2 Metadata Interface Factory, handle Radarsat2 metadata in OTB"; +} + +} // end namespace otb diff --git a/Modules/Core/Metadata/src/otbSarImageMetadataInterfaceFactory.cxx b/Modules/Core/Metadata/src/otbSarImageMetadataInterfaceFactory.cxx index 0cb27515e7e87d6f06f8c5390162500e6caa4509..f0c7bcff04e050b29babcf8d89c88a5493cec70e 100644 --- a/Modules/Core/Metadata/src/otbSarImageMetadataInterfaceFactory.cxx +++ b/Modules/Core/Metadata/src/otbSarImageMetadataInterfaceFactory.cxx @@ -23,6 +23,7 @@ // SAR Sensors #include "otbTerraSarImageMetadataInterfaceFactory.h" #include "otbSentinel1ImageMetadataInterfaceFactory.h" +#include "otbRadarsat2ImageMetadataInterfaceFactory.h" #include "itkMutexLock.h" #include "itkMutexLockHolder.h" @@ -81,6 +82,7 @@ SarImageMetadataInterfaceFactory { itk::ObjectFactoryBase::RegisterFactory(TerraSarImageMetadataInterfaceFactory::New()); itk::ObjectFactoryBase::RegisterFactory(Sentinel1ImageMetadataInterfaceFactory::New()); + itk::ObjectFactoryBase::RegisterFactory(Radarsat2ImageMetadataInterfaceFactory::New()); firstTime = false; } } diff --git a/Modules/Core/Metadata/test/CMakeLists.txt b/Modules/Core/Metadata/test/CMakeLists.txt index 7cf31ac3f3b85b70acc2b6bcb2d192a147e4532c..23e6ef48e261edb6a9d8a5e4cd89acb047b646da 100644 --- a/Modules/Core/Metadata/test/CMakeLists.txt +++ b/Modules/Core/Metadata/test/CMakeLists.txt @@ -25,6 +25,7 @@ otbDefaultImageMetadataInterface.cxx otbImageMetadataInterfaceTest2.cxx otbNoDataHelperTest.cxx otbSarCalibrationLookupDataTest.cxx +otbRadarsat2ImageMetadataInterfaceNew.cxx ) add_executable(otbMetadataTestDriver ${OTBMetadataTests}) @@ -76,17 +77,28 @@ otb_add_test(NAME ioTvSarImageMetadataInterfaceTest_TSX1PANGKALANBUUNUsingHHCosF ${TEMP}/ioTvSarImageMetadataInterface_TSX1PANGKALANBUUNUsingHHCosFile.txt ) -otb_add_test(NAME ioTvImageMetadataInterfaceBaseTest_Sentinel1 COMMAND otbMetadataTestDriver - --compare-ascii ${EPSILON_9} ${BASELINE_FILES}/ioTvImageMetadataInterfaceBase_Sentinel1.txt - ${TEMP}/ioTvImageMetadataInterfaceBase_Sentinel1.txt +otb_add_test(NAME ioTvImageMetadataInterfaceBaseTest_SENTINEL1 COMMAND otbMetadataTestDriver + --compare-ascii ${EPSILON_9} ${BASELINE_FILES}/ioTvImageMetadataInterfaceBase_SENTINEL1.txt + ${TEMP}/ioTvImageMetadataInterfaceBase_SENTINEL1.txt otbImageMetadataInterfaceBaseTest LARGEINPUT{SENTINEL1/S1A_S6_SLC__1SSV_20150619T195043/measurement/s1a-s6-slc-vv-20150619t195043-20150619t195101-006447-00887d-001.tiff} - ${TEMP}/ioTvImageMetadataInterfaceBase_Sentinel1.txt + ${TEMP}/ioTvImageMetadataInterfaceBase_SENTINEL1.txt + ) + +otb_add_test(NAME ioTvImageMetadataInterfaceBaseTest_RADARSAT2 COMMAND otbMetadataTestDriver + --compare-ascii ${EPSILON_9} ${BASELINE_FILES}/ioTvImageMetadataInterfaceBase_RADARSAT2.txt + ${TEMP}/ioTvImageMetadataInterfaceBase_RADARSAT2.txt + otbImageMetadataInterfaceBaseTest + LARGEINPUT{RADARSAT2/ALTONA/Fine_Quad-Pol_Dataset/PK6621_DK406_FQ9_20080405_124900_HH_VV_HV_VH_SLC_Altona/imagery_HV.tif} + ${TEMP}/ioTvImageMetadataInterfaceBase_RADARSAT2.txt ) otb_add_test(NAME ioTuSentinel1ImageMetadataInterfaceNew COMMAND otbMetadataTestDriver otbSentinel1ImageMetadataInterfaceNew ) +otb_add_test(NAME ioTuRadarsat2ImageMetadataInterfaceNew COMMAND otbMetadataTestDriver + otbRadarsat2ImageMetadataInterfaceNew ) + otb_add_test(NAME ioTuDefaultImageMetadataInterfaceFactoryNew COMMAND otbMetadataTestDriver otbDefaultImageMetadataInterfaceFactoryNew ) @@ -375,4 +387,12 @@ otb_add_test(NAME ioTvSarCalibrationLookupDataTest_SENTINEL1 COMMAND otbMetadata otbSarCalibrationLookupDataTest ${INPUTDATA}/SENTINEL1_SLC_S6_1S_extract_300_300.tif?&geom=${INPUTDATA}/SENTINEL1_SLC_S6_1S_extract_300_300.geom ${TEMP}/ioTvSarCalibrationLookupDataTest_SENTINEL1.txt + ) + +otb_add_test(NAME ioTvSarCalibrationLookupDataTest_RADARSAT2 COMMAND otbMetadataTestDriver + --compare-ascii ${NOTOL} ${BASELINE_FILES}/ioTvSarCalibrationLookupDataTest_RADARSAT2.txt + ${TEMP}/ioTvSarCalibrationLookupDataTest_RADARSAT2.txt + otbSarCalibrationLookupDataTest + ${INPUTDATA}/RADARSAT2_ALTONA_300_300_VV.tif?&geom=${INPUTDATA}/RADARSAT2_ALTONA_300_300_VV.geom + ${TEMP}/ioTvSarCalibrationLookupDataTest_RADARSAT2.txt ) \ No newline at end of file diff --git a/Modules/Core/Metadata/test/otbMetadataTestDriver.cxx b/Modules/Core/Metadata/test/otbMetadataTestDriver.cxx index 9b48c72a5bb07d49db1b90cf2e8bc0da4e95aa5e..ea205e1d08d67b76de16468be0578a459cb549ec 100644 --- a/Modules/Core/Metadata/test/otbMetadataTestDriver.cxx +++ b/Modules/Core/Metadata/test/otbMetadataTestDriver.cxx @@ -24,4 +24,5 @@ void RegisterTests() REGISTER_TEST(otbImageMetadataInterfaceTest2); REGISTER_TEST(otbNoDataHelperTest); REGISTER_TEST(otbSarCalibrationLookupDataTest); + REGISTER_TEST(otbRadarsat2ImageMetadataInterfaceNew); } diff --git a/Modules/Core/Metadata/test/otbRadarsat2ImageMetadataInterfaceNew.cxx b/Modules/Core/Metadata/test/otbRadarsat2ImageMetadataInterfaceNew.cxx new file mode 100644 index 0000000000000000000000000000000000000000..191ac66e7a3628638cba3443631d207d263f6178 --- /dev/null +++ b/Modules/Core/Metadata/test/otbRadarsat2ImageMetadataInterfaceNew.cxx @@ -0,0 +1,32 @@ +/*========================================================================= + + Program: ORFEO Toolbox + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved. + See OTBCopyright.txt for details. + + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + + + +#include "itkMacro.h" +#include <iostream> +#include "otbRadarsat2ImageMetadataInterface.h" + +int otbRadarsat2ImageMetadataInterfaceNew(int itkNotUsed(argc), char * itkNotUsed(argv) []) +{ + otb::Radarsat2ImageMetadataInterface::Pointer object = otb::Radarsat2ImageMetadataInterface::New(); + + std::cout << object << std::endl; + + return EXIT_SUCCESS; +} diff --git a/Modules/Radiometry/SARCalibration/include/otbSarRadiometricCalibrationFunction.h b/Modules/Radiometry/SARCalibration/include/otbSarRadiometricCalibrationFunction.h index 541afff72d4dc35ffc3ae3055abda78f4ef74846..1331f740d5e4991b9d77d540019f003922baf2a6 100644 --- a/Modules/Radiometry/SARCalibration/include/otbSarRadiometricCalibrationFunction.h +++ b/Modules/Radiometry/SARCalibration/include/otbSarRadiometricCalibrationFunction.h @@ -18,13 +18,11 @@ #ifndef __otbSarRadiometricCalibrationFunction_h #define __otbSarRadiometricCalibrationFunction_h -#include "otbSarRadiometricCalibrationFunctor.h" #include "otbSarParametricMapFunction.h" - - +#include "otbSarCalibrationLookupData.h" +#include "otbMath.h" namespace otb { - /** * \class SarRadiometricCalibrationFunction * \brief Calculate the backscatter for the given pixel @@ -71,33 +69,31 @@ public: itkStaticConstMacro(ImageDimension, unsigned int, InputImageType::ImageDimension); - /** Datatype used for the evaluation */ typedef double RealType; - typedef otb::Functor::SarRadiometricCalibrationFunctor<RealType, RealType> FunctorType; - typedef typename FunctorType::RealType FunctorRealType; +// typedef otb::Functor::SarRadiometricCalibrationFunctor<RealType, RealType> FunctorType; +// typedef typename FunctorType::RealType FunctorRealType; typedef otb::SarParametricMapFunction<InputImageType> ParametricFunctionType; typedef typename ParametricFunctionType::Pointer ParametricFunctionPointer; typedef typename ParametricFunctionType::ConstPointer ParametricFunctionConstPointer; - /** Evaluate the function at non-integer positions */ - virtual OutputType Evaluate(const PointType& point) const; - /** Evalulate the function at specified index */ - virtual OutputType EvaluateAtIndex(const IndexType& index) const + virtual OutputType EvaluateAtIndex(const IndexType& index) const; + + /** Evaluate the function at non-integer positions */ + virtual OutputType Evaluate(const PointType& point) const { - PointType point; - this->GetInputImage()->TransformIndexToPhysicalPoint( index, point); - return this->Evaluate(point); + IndexType index; + this->ConvertPointToNearestIndex(point, index); + return this->EvaluateAtIndex(index); } - virtual OutputType EvaluateAtContinuousIndex( - const ContinuousIndexType& cindex) const + virtual OutputType EvaluateAtContinuousIndex(const ContinuousIndexType& cindex) const { - PointType point; - this->GetInputImage()->TransformContinuousIndexToPhysicalPoint( cindex, point); - return this->Evaluate(point); + IndexType index; + this->ConvertContinuousIndexToNearestIndex(cindex, index); + return this->EvaluateAtIndex(index); } /** Set the input image. @@ -108,10 +104,10 @@ public: /** Get/Set the Scale value */ - itkSetMacro(Scale, FunctorRealType); - itkGetMacro(Scale, FunctorRealType); + itkSetMacro(Scale, RealType); + itkGetMacro(Scale, RealType); - /** Get/Set the Offset value */ + /** Get/Set the Noise value */ itkSetObjectMacro(Noise, ParametricFunctionType); itkGetConstObjectMacro(Noise, ParametricFunctionType); itkGetObjectMacro(Noise, ParametricFunctionType); @@ -140,23 +136,66 @@ public: itkGetConstObjectMacro(RangeSpreadLoss, ParametricFunctionType); itkGetObjectMacro(RangeSpreadLoss, ParametricFunctionType); + /** Set the RescalingFactor value */ + itkSetMacro(RescalingFactor, RealType); + + /** Get/Set flag to indicate if these are used */ + itkSetMacro(ApplyAntennaPatternGain, bool); + itkGetMacro(ApplyAntennaPatternGain, bool); + + itkSetMacro(ApplyIncidenceAngleCorrection, bool); + itkGetMacro(ApplyIncidenceAngleCorrection, bool); + + itkSetMacro(ApplyRangeSpreadLossCorrection, bool); + itkGetMacro(ApplyRangeSpreadLossCorrection, bool); + + itkSetMacro(ApplyLookupDataCorrection, bool); + itkGetMacro(ApplyLookupDataCorrection, bool); + + itkSetMacro(ApplyRescalingFactor, bool); + itkGetMacro(ApplyRescalingFactor, bool); + + typedef SarCalibrationLookupData::Pointer LookupDataPointer; + + /** Set SetCalibrationLookupData instance */ + void SetCalibrationLookupData(LookupDataPointer lut) + { + m_Lut = lut; + } protected: + + /** ctor */ SarRadiometricCalibrationFunction(); + + /** default, empty, virtual dtor */ virtual ~SarRadiometricCalibrationFunction(){} + + /** print method */ void PrintSelf(std::ostream& os, itk::Indent indent) const; + /** Flags to indiciate if these values needs to be applied in calibration*/ + private: SarRadiometricCalibrationFunction(const Self &); //purposely not implemented void operator =(const Self&); //purposely not implemented - FunctorRealType m_Scale; - ParametricFunctionPointer m_Noise; + RealType m_Scale; bool m_EnableNoise; + RealType m_RescalingFactor; + bool m_ApplyAntennaPatternGain; + bool m_ApplyIncidenceAngleCorrection; + bool m_ApplyRangeSpreadLossCorrection; + bool m_ApplyLookupDataCorrection; + bool m_ApplyRescalingFactor; + ParametricFunctionPointer m_Noise; ParametricFunctionPointer m_AntennaPatternNewGain; ParametricFunctionPointer m_AntennaPatternOldGain; ParametricFunctionPointer m_IncidenceAngle; ParametricFunctionPointer m_RangeSpreadLoss; + LookupDataPointer m_Lut; + + }; } // end namespace otb diff --git a/Modules/Radiometry/SARCalibration/include/otbSarRadiometricCalibrationFunction.txx b/Modules/Radiometry/SARCalibration/include/otbSarRadiometricCalibrationFunction.txx index b04ee4c8fc450006826cf3db1f5ad80777ca518b..4e22a24c59b7c33f252a95064f96446eae88a47a 100644 --- a/Modules/Radiometry/SARCalibration/include/otbSarRadiometricCalibrationFunction.txx +++ b/Modules/Radiometry/SARCalibration/include/otbSarRadiometricCalibrationFunction.txx @@ -24,27 +24,38 @@ namespace otb { - /** * Constructor */ template <class TInputImage, class TCoordRep> SarRadiometricCalibrationFunction<TInputImage, TCoordRep> -::SarRadiometricCalibrationFunction(): - m_Scale(1.0) +::SarRadiometricCalibrationFunction() +: m_Scale(1.0) +, m_EnableNoise(false) +, m_RescalingFactor(1.0) +, m_ApplyAntennaPatternGain(true) +, m_ApplyIncidenceAngleCorrection(true) +, m_ApplyRangeSpreadLossCorrection(true) +, m_ApplyLookupDataCorrection(false) +, m_ApplyRescalingFactor(false) + { + /* intialize parametric functions */ m_Noise = ParametricFunctionType::New(); m_AntennaPatternNewGain = ParametricFunctionType::New(); m_AntennaPatternOldGain = ParametricFunctionType::New(); m_IncidenceAngle = ParametricFunctionType::New(); m_RangeSpreadLoss = ParametricFunctionType::New(); + /* intialize default values in paramerticFunction instances */ m_Noise->SetConstantValue(0.0); - m_EnableNoise = true; m_AntennaPatternNewGain->SetConstantValue(1.0); m_AntennaPatternOldGain->SetConstantValue(1.0); m_IncidenceAngle->SetConstantValue(CONST_PI_2); m_RangeSpreadLoss->SetConstantValue(1.0); + +// m_Lut = 0; //new LookupTableBase(); + } /** @@ -65,7 +76,7 @@ SarRadiometricCalibrationFunction<TInputImage, TCoordRep> } /** - * + * Print */ template <class TInputImage, class TCoordRep> void @@ -75,23 +86,16 @@ SarRadiometricCalibrationFunction<TInputImage, TCoordRep> this->Superclass::PrintSelf(os, indent); } -/** - * - */ +/* Function: EvaluateAtIndex. This computes the required values for each pixel +* whose index is given in indexType argument. To convert index to point it uses +* InputImage::TransformIndexToPhysicalPoint(). IncidenceAngle and similar are +* computed based on this calculated point in SarParametricFunction */ template <class TInputImage, class TCoordRep> typename SarRadiometricCalibrationFunction<TInputImage, TCoordRep> ::OutputType SarRadiometricCalibrationFunction<TInputImage, TCoordRep> -::Evaluate(const PointType& point) const +::EvaluateAtIndex(const IndexType& index) const { - IndexType index; - this->GetInputImage()->TransformPhysicalPointToIndex(point, index); - - if (!this->GetInputImage()) - { - itkDebugMacro( <<"ERROR with GetInputImage()"); - return (itk::NumericTraits<OutputType>::max()); - } if (!this->IsInsideBuffer(index)) { @@ -99,21 +103,69 @@ SarRadiometricCalibrationFunction<TInputImage, TCoordRep> return (itk::NumericTraits<OutputType>::max()); } - FunctorType functor; + /* convert index to point */ + PointType point; + if (m_ApplyAntennaPatternGain || m_ApplyIncidenceAngleCorrection || m_ApplyRangeSpreadLossCorrection) + this->GetInputImage()->TransformIndexToPhysicalPoint( index, point); + + /** digitalNumber: + * For complex pixel type, vcl_abs() returns the modulus. which is + * sqrt((I*I) + (Q*Q)). Where I and Q are real and imaginary part of the + * complex pixel. So to to get (I*I) + (Q*Q) in our calculation, the output + * of vcl_abs() is squared. See below (digitalNumber * digitalNumber) where + * digitalNumber is the output of vcl_abs() which is sqrt((I*I) + (Q*Q)). For + * non-complex pixel types, vcl_abs() simply returns absolute value. + */ + + RealType digitalNumber = static_cast<RealType>(vcl_abs(this->GetInputImage()->GetPixel(index))); + RealType sigma = m_Scale * digitalNumber * digitalNumber; + + /** substract noise if enabled. */ if (m_EnableNoise) { - functor.SetNoise(static_cast<FunctorRealType>(m_Noise->Evaluate(point))); + sigma -= static_cast<RealType>(m_Noise->Evaluate(point)); + } + + /** Apply incidence angle correction if needed */ + if (m_ApplyIncidenceAngleCorrection) + { + sigma *= vcl_sin(static_cast<RealType>(m_IncidenceAngle->Evaluate(point))); } - functor.SetScale(m_Scale); - functor.SetAntennaPatternNewGain(static_cast<FunctorRealType>(m_AntennaPatternNewGain->Evaluate(point))); - functor.SetAntennaPatternOldGain(static_cast<FunctorRealType>(m_AntennaPatternOldGain->Evaluate(point))); - functor.SetIncidenceAngle(static_cast<FunctorRealType>(m_IncidenceAngle->Evaluate(point))); - functor.SetRangeSpreadLoss(static_cast<FunctorRealType>(m_RangeSpreadLoss->Evaluate(point))); - const RealType value = static_cast<RealType>(vcl_abs(this->GetInputImage()->GetPixel(index))); - RealType result = functor(value); + /** Apply old and new antenna pattern gain. */ + if (m_ApplyAntennaPatternGain) + { + sigma *= static_cast<RealType>(m_AntennaPatternNewGain->Evaluate(point)); + sigma /= static_cast<RealType>(m_AntennaPatternOldGain->Evaluate(point)); + } + + /** Apply range spread loss if needed. */ + if (m_ApplyRangeSpreadLossCorrection) + { + sigma *= static_cast<RealType>(m_RangeSpreadLoss->Evaluate(point)); + } + + /** Lookup value has effect on for some sensors which does not required the + * above values (incidence angle, rangespreadloss etc.. */ + if (m_ApplyLookupDataCorrection) + { + RealType lutVal = static_cast<RealType>(m_Lut->GetValue(index[0], index[1])); + sigma /= lutVal * lutVal; + } + + /** rescaling factor has effect only with CosmoSkymed Products */ + if (m_ApplyRescalingFactor) + { + sigma /= m_RescalingFactor; + } + + + if(sigma < 0.0) + { + sigma = 0.0; + } - return static_cast<OutputType>(result); + return static_cast<OutputType>(sigma); } } // end namespace otb diff --git a/Modules/Radiometry/SARCalibration/include/otbSarRadiometricCalibrationFunctor.h b/Modules/Radiometry/SARCalibration/include/otbSarRadiometricCalibrationFunctor.h deleted file mode 100644 index db02de332b500272b71d92b3844816cf81d6f628..0000000000000000000000000000000000000000 --- a/Modules/Radiometry/SARCalibration/include/otbSarRadiometricCalibrationFunctor.h +++ /dev/null @@ -1,161 +0,0 @@ -/*========================================================================= - - Program: ORFEO Toolbox - Language: C++ - Date: $Date$ - Version: $Revision$ - - - Copyright (c) Centre National d'Etudes Spatiales. All rights reserved. - See OTBCopyright.txt for details. - - - This software is distributed WITHOUT ANY WARRANTY; without even - the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - PURPOSE. See the above copyright notices for more information. - -=========================================================================*/ - -#ifndef __otbSarRadiometricCalibrationFunctor_h -#define __otbSarRadiometricCalibrationFunctor_h - -#include "otbMath.h" -#include "itkNumericTraits.h" - -namespace otb -{ - -namespace Functor -{ -/** - * \class SarRadiometricCalibrationFunctor - * \brief Compute the backscatter value. - * \f$ \sigma^{0} = (scale * DN^{2} + offset) * sin( \theta_{inc}) * OldGain / NewGain * RangeSpreadLoss \f$ - * - * - * \ingroup OTBSARCalibration - */ -template<class TInput, class TOutput> -class ITK_EXPORT SarRadiometricCalibrationFunctor -{ -public: - typedef TInput InputType; - typedef TOutput OutputType; - typedef typename itk::NumericTraits<InputType>::AbsType RealType; - - SarRadiometricCalibrationFunctor() - { - m_Noise = 0.0; - m_Scale = 1.0; - m_IncidenceAngle = CONST_PI_2; - m_AntennaPatternOldGain = 1.0; - m_AntennaPatternNewGain = 1.0; - m_RangeSpreadLoss = 1.0; - }; - - ~SarRadiometricCalibrationFunctor(){}; - - inline TOutput operator ()(const TInput& value) const - { - RealType digitalNumber = static_cast<RealType> (vcl_abs(value)); - RealType sigma; - - sigma = m_Scale * (digitalNumber * digitalNumber - m_Noise); - sigma *= vcl_sin(m_IncidenceAngle); - sigma *= m_AntennaPatternOldGain; - sigma /= m_AntennaPatternNewGain; - sigma *= m_RangeSpreadLoss; - - if(sigma < 0.0) - { - sigma = 0.0; - } - - return static_cast<OutputType>(sigma); - } - - /** Set offset method */ - void SetNoise(RealType value) - { - m_Noise = value; - } - - /** Get offset method */ - RealType GetNoise() const - { - return m_Noise; - } - - /** Set scale method */ - void SetScale(RealType value) - { - m_Scale = value; - } - - /** Get scale method */ - RealType GetScale() const - { - return m_Scale; - } - - /** Set antennaPatternNewGain method */ - void SetAntennaPatternNewGain(RealType value) - { - m_AntennaPatternNewGain = value; - } - - /** Get antennaPatternNewGain method */ - RealType GetAntennaPatternNewGain() const - { - return m_AntennaPatternNewGain; - } - - /** Set antennaPatternOldGain method */ - void SetAntennaPatternOldGain(RealType value) - { - m_AntennaPatternOldGain = value; - } - - /** Get antennaPatternOldGain method */ - RealType GetAntennaPatternOldGain() const - { - return m_AntennaPatternOldGain; - } - - /** Set incidenceAngle method */ - void SetIncidenceAngle(RealType value) - { - m_IncidenceAngle = value; - } - - /** Get incidenceAngle method */ - RealType GetIncidenceAngle() const - { - return m_IncidenceAngle; - } - - /** Set rangeSpreadLoss method */ - void SetRangeSpreadLoss(RealType value) - { - m_RangeSpreadLoss = value; - } - - /** Get scale method */ - RealType GetRangeSpreadLoss() const - { - return m_RangeSpreadLoss; - } - -private: - RealType m_Noise; - RealType m_Scale; - RealType m_AntennaPatternNewGain; - RealType m_AntennaPatternOldGain; - RealType m_IncidenceAngle; - RealType m_RangeSpreadLoss; -}; -} - -} - -#endif diff --git a/Modules/Radiometry/SARCalibration/include/otbSarRadiometricCalibrationToImageFilter.h b/Modules/Radiometry/SARCalibration/include/otbSarRadiometricCalibrationToImageFilter.h index 1212e9ae682de9b3f46e885d24efee34ebef12ba..523cdbccb1a8a4d3c37938df7435d87e696c7820 100644 --- a/Modules/Radiometry/SARCalibration/include/otbSarRadiometricCalibrationToImageFilter.h +++ b/Modules/Radiometry/SARCalibration/include/otbSarRadiometricCalibrationToImageFilter.h @@ -28,9 +28,29 @@ namespace otb { /** \class SarRadiometricCalibrationToImageFilter - * \brief Evaluates the SarRadiometricCalibrationFunction onto a source image + * \brief Evaluates the SarRadiometricCalibrationFunction onto a source image + * The BeforeThreadedGenerateData create a SarImageMetadataInterface based on + * input metadata dictionary. The nature of product(TerrSARX, Sentinel1, etc..) + * are thus detected automatically from this. The filter then reads necessary + * parameters required to perform SarCalibration in a generic way. * - * The function has to inherit from itkImageFunction + * BeforeThreadedGenerateData() instanciate a SarRadiometricCalibrationFunction + * and pass the values taken from SarImageMetadataInterface instance to it. This + * is where the actual computation of sigma (backscatter) occurs. + * + * Noise, Antenna pattern gain (old && new), range spread loss, incidence angle + * data members used in this class are all instances of SarPrametricFunction + * class. Each have a Evaluate() method and a special + * EvaluateParametricCoefficient() which computes the actual value. + * + * The technical details and more discussion of SarCalibration can be found in jira + * story #863. + * + * \see \c otb::SarParametricFunction + * \see \c otb::SarCalibrationLookupBase + * References (Retreived on 08-Sept-2015) + * Sentinel1 - https://sentinel.esa.int/web/sentinel/sentinel-1-sar-wiki/-/wiki/Sentinel%20One/Application+of+Radiometric+Calibration+LUT + * Radarsat2 - http://gs.mdacorporation.com/products/sensor/radarsat2/RS2_Product_Description.pdf * * \ingroup ImageFilters * @@ -76,20 +96,37 @@ public: typedef typename FunctionType::ParametricFunctionConstPointer ParametricFunctionConstPointer; typedef typename FunctionType::ParametricFunctionType ParametricFunctionType; + + /** Enable/disable the noise flag in SarRadiometricCalibrationFunction */ void SetEnableNoise(bool inArg) { this->GetFunction()->SetEnableNoise(inArg); } + + itkSetMacro(LookupSelected, short); + itkGetConstMacro(LookupSelected, short); + protected: + /** Default ctor */ SarRadiometricCalibrationToImageFilter(); + + /** Empty, default virtual dtor */ virtual ~SarRadiometricCalibrationToImageFilter() {} + /** Generate output information */ + virtual void GenerateOutputInformation(); + /** Update the function list and input parameters*/ virtual void BeforeThreadedGenerateData(); + private: + SarRadiometricCalibrationToImageFilter(const Self &); //purposely not implemented void operator =(const Self&); //purposely not implemented + + short m_LookupSelected; + }; } // end namespace otb diff --git a/Modules/Radiometry/SARCalibration/include/otbSarRadiometricCalibrationToImageFilter.txx b/Modules/Radiometry/SARCalibration/include/otbSarRadiometricCalibrationToImageFilter.txx index 15b09c7fd73a1381545b48a64bcd16593fd24b38..ad0f5b47e035d1218ea856d7788567f40c67f9f9 100644 --- a/Modules/Radiometry/SARCalibration/include/otbSarRadiometricCalibrationToImageFilter.txx +++ b/Modules/Radiometry/SARCalibration/include/otbSarRadiometricCalibrationToImageFilter.txx @@ -22,8 +22,8 @@ #define __otbSarRadiometricCalibrationToImageFilter_txx #include "otbSarRadiometricCalibrationToImageFilter.h" - #include "otbSarImageMetadataInterfaceFactory.h" +#include "otbSarCalibrationLookupData.h" namespace otb { @@ -34,7 +34,33 @@ namespace otb template<class TInputImage, class TOutputImage> SarRadiometricCalibrationToImageFilter<TInputImage, TOutputImage> ::SarRadiometricCalibrationToImageFilter() +: m_LookupSelected(0) { + +} + +template<class TInputImage, class TOutputImage> +void +SarRadiometricCalibrationToImageFilter<TInputImage, TOutputImage> +::GenerateOutputInformation( ) +{ + Superclass::GenerateOutputInformation(); + + // Retrieving input/output pointers + InputImagePointer inputPtr = this->GetInput(); + + if (inputPtr.IsNull()) + { + itkExceptionMacro(<< "At least one input is missing." + << " Input is missing :" << inputPtr.GetPointer() ) + } + + OutputImagePointer outputPtr = this->GetOutput(); + if (outputPtr.IsNull()) + { + itkExceptionMacro(<< "At least one output is missing." + << " Output is missing :" << outputPtr.GetPointer() ) + } } template<class TInputImage, class TOutputImage> @@ -45,60 +71,104 @@ SarRadiometricCalibrationToImageFilter<TInputImage, TOutputImage> // will SetInputImage on the function Superclass::BeforeThreadedGenerateData(); + /** cretate a SarImageMetadataInterface instance from + * GetMetaDataDictionary(). This will return the appropriate IMI depending on + * the Sensor information & co available in GetMetaDataDictionary() */ SarImageMetadataInterface::Pointer imageMetadataInterface = SarImageMetadataInterfaceFactory::CreateIMI( this->GetInput()->GetMetaDataDictionary()); + /** Get the SarRadiometricCalibrationFunction function instance. */ FunctionPointer function = this->GetFunction(); - function->SetScale(imageMetadataInterface->GetRadiometricCalibrationScale()); + /** check if there is a calibration lookupdata is available with the + * product. eg. Sentinel1. This means + * A. The computation of the backscatter is based on this lookup value which + * depends on the given product.* + * B. The other value such as antenna pattern gain, rangespread loss, incidence + * angle has no effect in calibration */ + + bool apply = imageMetadataInterface->HasCalibrationLookupDataFlag(); + /* Below lines will toggle the necessary flags which can help skip some + * computation. For example, if there is lookup value and ofcourse antenna + * pattern gain is not required. Even if we try to compute the value with + * SarParametricFuntion we get 1. This is the safe side. But as we are so sure + * we skip all those calls to EvaluateParametricCoefficient and also the + * Evalute(). For the function the value is 1 by default. + */ + function->SetApplyAntennaPatternGain(!apply); + function->SetApplyIncidenceAngleCorrection(!apply); + function->SetApplyRangeSpreadLossCorrection(!apply); + function->SetApplyRescalingFactor(!apply); + function->SetApplyLookupDataCorrection(apply); - ParametricFunctionPointer noise; - ParametricFunctionPointer antennaPatternNewGain; - ParametricFunctionPointer antennaPatternOldGain; - ParametricFunctionPointer incidenceAngle; - ParametricFunctionPointer rangeSpreadLoss; - - noise = function->GetNoise(); - noise->SetPointSet(imageMetadataInterface->GetRadiometricCalibrationNoise()); - noise->SetPolynomalSize(imageMetadataInterface->GetRadiometricCalibrationNoisePolynomialDegree()); - noise->EvaluateParametricCoefficient(); - - antennaPatternNewGain = function->GetAntennaPatternNewGain(); - antennaPatternNewGain->SetPointSet(imageMetadataInterface->GetRadiometricCalibrationAntennaPatternNewGain()); - antennaPatternNewGain->SetPolynomalSize(imageMetadataInterface->GetRadiometricCalibrationAntennaPatternNewGainPolynomialDegree()); - antennaPatternNewGain->EvaluateParametricCoefficient(); - - antennaPatternOldGain = function->GetAntennaPatternOldGain(); - antennaPatternOldGain->SetPointSet(imageMetadataInterface->GetRadiometricCalibrationAntennaPatternOldGain()); - antennaPatternOldGain->SetPolynomalSize(imageMetadataInterface->GetRadiometricCalibrationAntennaPatternOldGainPolynomialDegree()); - antennaPatternOldGain->EvaluateParametricCoefficient(); - - incidenceAngle = function->GetIncidenceAngle(); - incidenceAngle->SetPointSet(imageMetadataInterface->GetRadiometricCalibrationIncidenceAngle()); - - typename ParametricFunctionType::PointType point; - point.Fill(0); - typename ParametricFunctionType::PointSetType::PixelType pointValue; - pointValue = itk::NumericTraits<typename ParametricFunctionType::PointSetType::PixelType>::Zero; - unsigned int nbRecords = imageMetadataInterface->GetRadiometricCalibrationIncidenceAngle()->GetNumberOfPoints(); - - // Fill the linear system - for (unsigned int i = 0; i < nbRecords; ++i) - { - imageMetadataInterface->GetRadiometricCalibrationIncidenceAngle()->GetPoint(i, &point); - imageMetadataInterface->GetRadiometricCalibrationIncidenceAngle()->GetPointData(i, &pointValue); - } - incidenceAngle->SetPolynomalSize(imageMetadataInterface->GetRadiometricCalibrationIncidenceAnglePolynomialDegree()); - - incidenceAngle->EvaluateParametricCoefficient(); - rangeSpreadLoss = function->GetRangeSpreadLoss(); - rangeSpreadLoss->SetPointSet(imageMetadataInterface->GetRadiometricCalibrationRangeSpreadLoss()); - rangeSpreadLoss->SetPolynomalSize(imageMetadataInterface->GetRadiometricCalibrationRangeSpreadLossPolynomialDegree()); - rangeSpreadLoss->EvaluateParametricCoefficient(); + function->SetScale(imageMetadataInterface->GetRadiometricCalibrationScale()); + /* Compute noise if enabled */ + if( function->GetEnableNoise()) + { + ParametricFunctionPointer noise; + noise = function->GetNoise(); + noise->SetPointSet(imageMetadataInterface->GetRadiometricCalibrationNoise()); + noise->SetPolynomalSize(imageMetadataInterface->GetRadiometricCalibrationNoisePolynomialDegree()); + noise->EvaluateParametricCoefficient(); + } + + /* Compute old and new antenna pattern gain */ + if(function->GetApplyAntennaPatternGain()) + { + ParametricFunctionPointer antennaPatternNewGain; + antennaPatternNewGain = function->GetAntennaPatternNewGain(); + antennaPatternNewGain->SetPointSet(imageMetadataInterface->GetRadiometricCalibrationAntennaPatternNewGain()); + antennaPatternNewGain->SetPolynomalSize(imageMetadataInterface->GetRadiometricCalibrationAntennaPatternNewGainPolynomialDegree()); + antennaPatternNewGain->EvaluateParametricCoefficient(); + + ParametricFunctionPointer antennaPatternOldGain; + antennaPatternOldGain = function->GetAntennaPatternOldGain(); + antennaPatternOldGain->SetPointSet(imageMetadataInterface->GetRadiometricCalibrationAntennaPatternOldGain()); + antennaPatternOldGain->SetPolynomalSize(imageMetadataInterface->GetRadiometricCalibrationAntennaPatternOldGainPolynomialDegree()); + antennaPatternOldGain->EvaluateParametricCoefficient(); + } + + /* Compute incidence angle */ + if (function->GetApplyIncidenceAngleCorrection()) + { + ParametricFunctionPointer incidenceAngle; + incidenceAngle = function->GetIncidenceAngle(); + incidenceAngle->SetPointSet(imageMetadataInterface->GetRadiometricCalibrationIncidenceAngle()); + incidenceAngle->SetPolynomalSize(imageMetadataInterface->GetRadiometricCalibrationIncidenceAnglePolynomialDegree()); + incidenceAngle->EvaluateParametricCoefficient(); + } + + /* Compute Range spread Loss */ + if (function->GetApplyRangeSpreadLossCorrection()) + { + ParametricFunctionPointer rangeSpreadLoss; + rangeSpreadLoss = function->GetRangeSpreadLoss(); + rangeSpreadLoss->SetPointSet(imageMetadataInterface->GetRadiometricCalibrationRangeSpreadLoss()); + rangeSpreadLoss->SetPolynomalSize(imageMetadataInterface->GetRadiometricCalibrationRangeSpreadLossPolynomialDegree()); + rangeSpreadLoss->EvaluateParametricCoefficient(); + } + + /** Get the lookupdata instance. unlike the all the above this is not a +* parametricFunction instance. But rather an internal class in IMI called +* SarCalibrationLookupData. +* +*NOTE: As the computation of lookup data for sensors is not universal. One must +*provide a sub-class. +See Also: otbSentinel1ImageMetadataInterface, otbTerraSarImageMetadataInterface, +*otbRadarsat2ImageMetadataInterface */ + if (function->GetApplyLookupDataCorrection()) + { + function->SetCalibrationLookupData(imageMetadataInterface->GetCalibrationLookupData(this->GetLookupSelected())); + } + + /** This was introduced for cosmoskymed which required a rescaling factor */ + if (function->GetApplyRescalingFactor()) + { + function->SetRescalingFactor(imageMetadataInterface->GetRescalingFactor()); + } } - } // end namespace otb #endif diff --git a/Modules/Radiometry/SARCalibration/test/CMakeLists.txt b/Modules/Radiometry/SARCalibration/test/CMakeLists.txt index 0e3ddd573154ea1c3c393d1206cee83df23c20fc..09dde97aa2a6309a7c4cf555618952eeb1df4f07 100644 --- a/Modules/Radiometry/SARCalibration/test/CMakeLists.txt +++ b/Modules/Radiometry/SARCalibration/test/CMakeLists.txt @@ -18,8 +18,6 @@ otbSarRadiometricCalibrationToImageFilterCompareTest.cxx otbSarBrightnessFunctor.cxx otbSarBrightnessFunctionWithoutNoise.cxx otbSarRadiometricCalibrationFunction.cxx -otbSarRadiometricCalibrationFunctor.cxx -otbSarRadiometricCalibrationFunctorWithoutNoise.cxx otbSarRadiometricCalibrationFunctionWithoutNoise.cxx otbTerraSarBrightnessImageComplexFilterTest.cxx otbSarRadiometricCalibrationToImageFilterWithComplexPixelTest.cxx @@ -127,6 +125,28 @@ otb_add_test(NAME raTvSarRadiometricCalibrationToImageWithComplexPixelFilterWith 1000 1000 250 250 # Extract ) +#Sentinel-1 L1, SLC +otb_add_test(NAME raTvSarRadiometricCalibrationToImageWithComplexPixelFilterWithoutNoise_SENTINEL1 COMMAND otbSARCalibrationTestDriver + --compare-image ${EPSILON_12} + ${BASELINE}/raTvSarRadiometricCalibrationToImageWithComplexPixelFilterWithoutNoise_SENTINEL1_VV.tif + ${TEMP}/raTvSarRadiometricCalibrationToImageWithComplexPixelFilterWithoutNoise_SENTINEL1_VV.tif + otbSarRadiometricCalibrationToImageFilterWithComplexPixelTestWithoutNoise + LARGEINPUT{SENTINEL1/S1A_S6_SLC__1SSV_20150619T195043/measurement/s1a-s6-slc-vv-20150619t195043-20150619t195101-006447-00887d-001.tiff} + ${TEMP}/raTvSarRadiometricCalibrationToImageWithComplexPixelFilterWithoutNoise_SENTINEL1_VV.tif + 1100 1900 450 450 # Extract + ) + +#Radarsat2 +otb_add_test(NAME raTvSarRadiometricCalibrationToImageWithComplexPixelFilterWithoutNoise_RADARSAT2 COMMAND otbSARCalibrationTestDriver + --compare-image ${EPSILON_12} + ${BASELINE}/raTvSarRadiometricCalibrationToImageWithComplexPixelFilterWithoutNoise_RADARSAT2_HV.tif + ${TEMP}/raTvSarRadiometricCalibrationToImageWithComplexPixelFilterWithoutNoise_RADARSAT2_HV.tif + otbSarRadiometricCalibrationToImageFilterWithComplexPixelTestWithoutNoise + LARGEINPUT{RADARSAT2/ALTONA/Fine_Quad-Pol_Dataset/PK6621_DK406_FQ9_20080405_124900_HH_VV_HV_VH_SLC_Altona/imagery_HV.tif} + ${TEMP}/raTvSarRadiometricCalibrationToImageWithComplexPixelFilterWithoutNoise_RADARSAT2_HV.tif + 11 11 650 750 # Extract + ) + otb_add_test(NAME raTuSarBrightnessFunctorWithoutNoise COMMAND otbSARCalibrationTestDriver otbSarBrightnessFunctorWithoutNoise ) @@ -190,13 +210,6 @@ otb_add_test(NAME raTvSarRadiometricCalibrationFunction COMMAND otbSARCalibratio ${TEMP}/raTvSarRadiometricCalibrationFunctionOutputAsciiWithNoise.txt ) -otb_add_test(NAME raTuSarRadiometricCalibrationFunctor COMMAND otbSARCalibrationTestDriver - otbSarRadiometricCalibrationFunctor - ) - -otb_add_test(NAME raTuSarRadiometricCalibrationFunctorWithoutNoise COMMAND otbSARCalibrationTestDriver - otbSarRadiometricCalibrationFunctorWithoutNoise - ) otb_add_test(NAME raTvSarRadiometricCalibrationFunctionWithoutNoise COMMAND otbSARCalibrationTestDriver --compare-ascii ${NOTOL} @@ -259,4 +272,3 @@ otb_add_test(NAME raTvSarBrightnessToImageFilter COMMAND otbSARCalibrationTestD ${TEMP}/raTvSarBrightnessToImageFilter_TSX_PANGKALANBUUN_HH.tif 1000 1000 250 250 # Extract ) - diff --git a/Modules/Radiometry/SARCalibration/test/otbSARCalibrationTestDriver.cxx b/Modules/Radiometry/SARCalibration/test/otbSARCalibrationTestDriver.cxx index 19236b9438f890df8aefde837c12ad00692c636c..873a912bbe6538f0583e348a02184b4bcca4e6f9 100644 --- a/Modules/Radiometry/SARCalibration/test/otbSARCalibrationTestDriver.cxx +++ b/Modules/Radiometry/SARCalibration/test/otbSARCalibrationTestDriver.cxx @@ -17,8 +17,6 @@ void RegisterTests() REGISTER_TEST(otbSarBrightnessFunctor); REGISTER_TEST(otbSarBrightnessFunctionWithoutNoise); REGISTER_TEST(otbSarRadiometricCalibrationFunction); - REGISTER_TEST(otbSarRadiometricCalibrationFunctor); - REGISTER_TEST(otbSarRadiometricCalibrationFunctorWithoutNoise); REGISTER_TEST(otbSarRadiometricCalibrationFunctionWithoutNoise); REGISTER_TEST(otbTerraSarBrightnessImageComplexFilterTest); REGISTER_TEST(otbSarRadiometricCalibrationToImageFilterWithComplexPixelTest); diff --git a/Modules/ThirdParty/OssimPlugins/src/ossim/ossimRadarSat2Model.cpp b/Modules/ThirdParty/OssimPlugins/src/ossim/ossimRadarSat2Model.cpp index c7e78de798ce0b89b77360089f69facb77572dbf..56719938ac1d516ddc7a71a7d42c73c8944072b8 100644 --- a/Modules/ThirdParty/OssimPlugins/src/ossim/ossimRadarSat2Model.cpp +++ b/Modules/ThirdParty/OssimPlugins/src/ossim/ossimRadarSat2Model.cpp @@ -47,21 +47,24 @@ RTTI_DEF1(ossimRadarSat2Model, "ossimRadarSat2Model", ossimGeometricSarSensorMod ossimRadarSat2Model::ossimRadarSat2Model() - : - ossimGeometricSarSensorModel(), - _n_srgr(0), - _srgr_update(), - _SrGr_R0() + : ossimGeometricSarSensorModel() + , _n_srgr(0) + , _srgr_update() + , _SrGr_R0() + , theAcquisitionDateUTCString("") + , theProductionDateUTCString("") { } ossimRadarSat2Model::ossimRadarSat2Model(const ossimRadarSat2Model& rhs) - : - ossimGeometricSarSensorModel(rhs), - _n_srgr(rhs._n_srgr), - _srgr_update(rhs._srgr_update), - _SrGr_R0(rhs._SrGr_R0) + : ossimGeometricSarSensorModel(rhs) + , _n_srgr(rhs._n_srgr) + , _srgr_update(rhs._srgr_update) + , _SrGr_R0(rhs._SrGr_R0) + , theProductionDateUTCString(rhs.theProductionDateUTCString) + , theAcquisitionDateUTCString(rhs.theAcquisitionDateUTCString) { + } ossimRadarSat2Model::~ossimRadarSat2Model() @@ -81,15 +84,15 @@ ossimObject* ossimRadarSat2Model::dup() const double ossimRadarSat2Model::getSlantRangeFromGeoreferenced(double col) const { if (_n_srgr==0) return(-1) ; - + double relativeGroundRange, slantRange = 0.0 ; - + // in the case of Georeferenced images, _refPoint->get_distance() // contains the ground range relativeGroundRange = _refPoint->get_distance() + _sensor->get_col_direction() * (col-_refPoint->get_pix_col())* theGSD.x; //relativeGroundRange = 1 + _sensor->get_col_direction() * (col-_refPoint->get_pix_col())* theGSD.x; //relativeGroundRange = (8.78400000e+03)*theGSD.x; - + if ( traceDebug() ) { ossimNotify(ossimNotifyLevel_DEBUG) @@ -100,15 +103,15 @@ double ossimRadarSat2Model::getSlantRangeFromGeoreferenced(double col) const << "\n_refPoint->get_pix_col() : " << _refPoint->get_pix_col() << "\n relativeGroundRange : " << relativeGroundRange << endl; } - + int numSet = FindSRGRSetNumber((_refPoint->get_ephemeris())->get_date()) ; /** * @todo : could be improved (date choice) */ - + for (int i=0 ; i < static_cast<int>(_SrGr_coeffs[numSet].size()); i++) { - + slantRange += _SrGr_coeffs[numSet][i]*pow(relativeGroundRange,i) ; } @@ -160,6 +163,8 @@ bool ossimRadarSat2Model::open(const ossimFilename& file) if (result) { + _productXmlFile = xmlFile; + if (traceDebug()) { ossimNotify(ossimNotifyLevel_DEBUG) @@ -204,13 +209,27 @@ bool ossimRadarSat2Model::open(const ossimFilename& file) result = rsDoc.getSatellite(xdoc, theSensorID); } + if (result) + { // Set the base class gsd: result = rsDoc.initGsd(xdoc, theGSD); + } + if (result) { theMeanGSD = (theGSD.x + theGSD.y)/2.0; } + if (result) + { + result = rsDoc.getAcquistionDate(xdoc, theAcquisitionDateUTCString); + } + + if (result) + { + result = rsDoc.getProductionDate(xdoc, theProductionDateUTCString); + } + if (result) { result = initSRGR(xdoc, rsDoc); @@ -226,7 +245,7 @@ bool ossimRadarSat2Model::open(const ossimFilename& file) if (result) { result = initRefPoint(xdoc, rsDoc); - + if (result) { result = InitRefNoiseLevel(xdoc); @@ -246,7 +265,6 @@ bool ossimRadarSat2Model::open(const ossimFilename& file) if (result) { - _productXmlFile = xmlFile; ossimSupportFilesList::instance()->add(_productXmlFile); } else @@ -273,7 +291,7 @@ bool ossimRadarSat2Model::open(const ossimFilename& file) << "ul, ur, lr, ll " << ul << ", " << ur << ", " << lr << " , " << ll << endl; } - + setGroundRect(ul, ur, lr, ll); // ossimSensorModel method. // OSSIM preferences specifies whether a coarse grid needs to be generated: @@ -336,7 +354,7 @@ std::ostream& ossimRadarSat2Model::print(std::ostream& out) const } ossimGeometricSarSensorModel::print(out); - + // Reset flags. out.setf(f); @@ -523,7 +541,7 @@ bool ossimRadarSat2Model::InitRefPoint(const ossimKeywordlist &kwl, date->set_decimal(time - floor(time)) ; } delete date;//FIXME to confirm - + if(_platformPosition != 0) { Ephemeris * ephemeris = _platformPosition->Interpolate((JSDDateTime)*date); @@ -928,7 +946,7 @@ bool ossimRadarSat2Model::initRefPoint(const ossimXmlDocument* xdoc, double distance = 1; - // Only set distance to + // Only set distance to if (!_isProductGeoreferenced) { if ( !rsDoc.getSlantRangeNearEdge(xdoc, s) ) @@ -936,9 +954,9 @@ bool ossimRadarSat2Model::initRefPoint(const ossimXmlDocument* xdoc, if (traceDebug()) { ossimNotify(ossimNotifyLevel_DEBUG) - + << MODULE << "getSlantRangeNearEdge error! exiting\n"; - } + } return false; } distance = s.toDouble(); @@ -981,7 +999,8 @@ bool ossimRadarSat2Model::initRefPoint(const ossimXmlDocument* xdoc, bool ossimRadarSat2Model::InitLut( const ossimXmlDocument* xmlDocument, RadarSat2NoiseLevel& noise) { - static const char MODULE[] = "ossimRadarSat2Model::initLut"; + static const char MODULE[] = "ossimRadarSat2Model::InitLut"; + if (traceDebug()) { ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " entered...\n"; @@ -992,8 +1011,8 @@ bool ossimRadarSat2Model::InitLut( const ossimXmlDocument* xmlDocument, std::vector<ossimRefPtr<ossimXmlNode> > xml_nodes; std::vector<ossimRefPtr<ossimXmlNode> >::iterator node; ossimFilename lutXmlFile; - - incidenceAngleCorrectionName = noise.get_incidenceAngleCorrectionName(); + + incidenceAngleCorrectionName = noise.get_incidenceAngleCorrectionName(); xpath = "/product/imageAttributes/lookupTable"; xml_nodes.clear(); @@ -1009,8 +1028,8 @@ bool ossimRadarSat2Model::InitLut( const ossimXmlDocument* xmlDocument, << std::endl; } return false; - } - + } + node = xml_nodes.begin(); while (node != xml_nodes.end()) { @@ -1024,56 +1043,67 @@ bool ossimRadarSat2Model::InitLut( const ossimXmlDocument* xmlDocument, //--- // Instantiate the XML parser: //--- - ossimXmlDocument* xmlLutDocument = new ossimXmlDocument(); - if ( xmlLutDocument->openFile(lutXmlFile) ) + ossimRefPtr<ossimXmlDocument> xmlLutDocument; + xmlLutDocument = new ossimXmlDocument(); + if ( xmlLutDocument.get()->openFile(lutXmlFile) ) { - std::vector<ossimRefPtr<ossimXmlNode> > xml_lutNodes; - ossimString s; - - xpath = "/lut/offset"; - xml_lutNodes.clear(); - xmlLutDocument->findNodes(xpath, xml_lutNodes); - if(xml_lutNodes.size() == 0) - { - setErrorStatus(); - if(traceDebug()) - { - ossimNotify(ossimNotifyLevel_DEBUG) + const ossimRefPtr<ossimXmlNode> lutRoot = xmlLutDocument.get()->getRoot(); //->findFirstNode("lut"); + + if(! lutRoot.get()) + { + setErrorStatus(); + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) + << MODULE << " DEBUG:" + << "\nCould not find: lut" << std::endl; + } + return false; + } + + ossimString offsetVal = lutRoot->getChildTextValue("offset"); + if( !offsetVal.empty()) + { + noise.set_offset(offsetVal.toFloat64()); + } + else + { + setErrorStatus(); + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG:" - << "\nCould not find: " << xpath - << std::endl; - } - return false; - } - ossim_float64 offset = xml_lutNodes[0]->getText().toFloat64(); - noise.set_offset(offset); - - xpath = "/lut/gains"; - xml_lutNodes.clear(); - xmlLutDocument->findNodes(xpath, xml_lutNodes); - if(xml_lutNodes.size() == 0) - { - setErrorStatus(); - if(traceDebug()) - { - ossimNotify(ossimNotifyLevel_DEBUG) + << "\nCould not find: offset" << std::endl; + } + return false; + } + + ossimString gainVal = lutRoot->getChildTextValue("gains"); + if( !gainVal.empty()) + { + noise.set_gain(gainVal); + } + else + { + setErrorStatus(); + if(traceDebug()) + { + ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " DEBUG:" - << "\nCould not find: " << xpath - << std::endl; - } - return false; - } - noise.set_gain(xml_lutNodes[0]->getText()); - } + << "\nCould not find: gains" << std::endl; + } + return false; + } + } } } - ++node; + ++node; } if (traceDebug()) { ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " leaving...\n"; - } + } return true; } @@ -1095,8 +1125,8 @@ bool ossimRadarSat2Model::InitRefNoiseLevel( } _noiseLevel.clear(); - - + + xpath = "/product/sourceAttributes/radarParameters/referenceNoiseLevel"; xml_nodes.clear(); xmlDocument->findNodes(xpath, xml_nodes); @@ -1111,14 +1141,14 @@ bool ossimRadarSat2Model::InitRefNoiseLevel( << std::endl; } return false; - } - + } + node = xml_nodes.begin(); while (node != xml_nodes.end()) { - - ev.set_incidenceAngleCorrectionName( (*node)->getAttributeValue("incidenceAngleCorrection") ); - + + ev.set_incidenceAngleCorrectionName( (*node)->getAttributeValue("incidenceAngleCorrection") ); + sub_nodes.clear(); xpath = "pixelFirstNoiseValue"; (*node)->findChildNodes(xpath, sub_nodes); @@ -1185,10 +1215,10 @@ bool ossimRadarSat2Model::InitRefNoiseLevel( } return false; } - ev.set_units( sub_nodes[0]->getAttributeValue("units") ); + ev.set_units( sub_nodes[0]->getAttributeValue("units") ); - std::vector<ossimString> s2; + std::vector<ossimString> s2; std::vector<ossim_float64> noiseLevelValues; s2.clear(); noiseLevelValues.clear(); @@ -1197,7 +1227,7 @@ bool ossimRadarSat2Model::InitRefNoiseLevel( { noiseLevelValues.push_back( s2[i].toFloat64() ); } - ev.set_noiseLevelValues( noiseLevelValues ); + ev.set_noiseLevelValues( noiseLevelValues ); InitLut(xmlDocument, ev); @@ -1206,11 +1236,11 @@ bool ossimRadarSat2Model::InitRefNoiseLevel( ++node; } - + if (traceDebug()) { ossimNotify(ossimNotifyLevel_DEBUG)<< MODULE << " leaving...\n"; - } + } return true; } @@ -1234,6 +1264,33 @@ bool ossimRadarSat2Model::saveState(ossimKeywordlist& kwl, kwl.add(prefix, PRODUCT_XML_FILE_KW, _productXmlFile.c_str()); kwl.add(prefix, NUMBER_SRGR_COEFFICIENTS_KW, _n_srgr); + kwl.add("support_data.", + "calibration_lookup_flag", + "true", + true); + + + if(! theProductionDateUTCString.empty()) + kwl.add("support_data.", + ossimKeywordNames::DATE_KW, + theProductionDateUTCString.c_str(), + true); + + if(! theAcquisitionDateUTCString.empty()) + kwl.add("support_data.", + ossimKeywordNames::IMAGE_DATE_KW, + theAcquisitionDateUTCString.c_str(), + true); + + //RK ...fix this part as part of refractoring + //if(theSLC)// numBands*=2; // real and imaginary + + + kwl.add("support_data.", + ossimKeywordNames::NUMBER_BANDS_KW, + 2, + true); + // Make sure all the arrays are equal in size. const ossim_uint32 COUNT = static_cast<ossim_uint32>(_n_srgr); @@ -1282,10 +1339,10 @@ bool ossimRadarSat2Model::saveState(ossimKeywordlist& kwl, if (result) { for(ossim_uint32 i = 0; i < _noiseLevel.size(); ++i) - { + { _noiseLevel[i].saveState(kwl, prefix); } - + } //--- @@ -1485,9 +1542,9 @@ bool ossimRadarSat2Model::loadState (const ossimKeywordlist &kwl, if(result) { for(ossim_uint32 i = 0; i < _noiseLevel.size(); ++i) - { + { _noiseLevel[i].loadState(kwl, prefix); - } + } } if (traceDebug()) diff --git a/Modules/ThirdParty/OssimPlugins/src/ossim/ossimRadarSat2Model.h b/Modules/ThirdParty/OssimPlugins/src/ossim/ossimRadarSat2Model.h index 2269a0266027a81dd1d39aae9c33b85b67a02a14..606e41af9bc8e6b4791e22fd288b9935a4015149 100644 --- a/Modules/ThirdParty/OssimPlugins/src/ossim/ossimRadarSat2Model.h +++ b/Modules/ThirdParty/OssimPlugins/src/ossim/ossimRadarSat2Model.h @@ -169,6 +169,11 @@ private: */ int _n_srgr; + //RK remove this part soon and use kwl directly. + ossimString theAcquisitionDateUTCString; + + ossimString theProductionDateUTCString; + /** * @brief Slant Range FOR EACH Ground Range coefficient sets update times */ diff --git a/Modules/ThirdParty/OssimPlugins/src/ossim/ossimRadarSat2ProductDoc.cpp b/Modules/ThirdParty/OssimPlugins/src/ossim/ossimRadarSat2ProductDoc.cpp index 65a03bea50565382b7fb2fb3e82ff5616e0934dc..569f21e79fd9b945a5c54f7aa616d12db2976ab4 100644 --- a/Modules/ThirdParty/OssimPlugins/src/ossim/ossimRadarSat2ProductDoc.cpp +++ b/Modules/ThirdParty/OssimPlugins/src/ossim/ossimRadarSat2ProductDoc.cpp @@ -465,7 +465,7 @@ bool ossimRadarSat2ProductDoc::initGsd(const ossimXmlDocument* xdoc, ossimString s; if ( getSampledPixelSpacing(xdoc, s) ) { - gsd.x = s.toFloat64(); + gsd.x = ossimString::toFloat64(s); } else { @@ -473,7 +473,7 @@ bool ossimRadarSat2ProductDoc::initGsd(const ossimXmlDocument* xdoc, } if ( getSampledLineSpacing(xdoc, s) ) { - gsd.y = s.toFloat64(s); + gsd.y = ossimString::toFloat64(s); } else { @@ -496,6 +496,20 @@ bool ossimRadarSat2ProductDoc::initGsd(const ossimXmlDocument* xdoc, return result; } + + +bool ossimRadarSat2ProductDoc::getAcquistionDate(const ossimXmlDocument* xdoc, ossimString& adate) +{ + ossimString path = "/product/sourceAttributes/rawDataStartTime"; + return ossim::getPath(path, xdoc, adate); +} + +bool ossimRadarSat2ProductDoc::getProductionDate(const ossimXmlDocument* xdoc, ossimString& pdate) +{ + ossimString path = "/product/imageGenerationParameters/generalProcessingInformation/processingTime"; + return ossim::getPath(path, xdoc, pdate); +} + bool ossimRadarSat2ProductDoc::initTiePoints(const ossimXmlDocument* xdoc, std::list<ossimGpt>& gcp, std::list<ossimDpt>& icp) const @@ -889,15 +903,15 @@ bool ossimRadarSat2ProductDoc::getImageFile(const ossimXmlDocument* xdoc, { bool result = false; ossimString fileName; - + ossimString path = "/product/imageAttributes/fullResolutionImageData"; - + if ( ossim::getPath(path, xdoc, fileName) ) { result = true; s = fileName; } - + return result; } diff --git a/Modules/ThirdParty/OssimPlugins/src/ossim/ossimRadarSat2ProductDoc.h b/Modules/ThirdParty/OssimPlugins/src/ossim/ossimRadarSat2ProductDoc.h index 56bf0a7ab75915bd15c3281189bb72eeac80a10f..ae376b08f88bcab27af8d9c9b303b64bf12e5bed 100644 --- a/Modules/ThirdParty/OssimPlugins/src/ossim/ossimRadarSat2ProductDoc.h +++ b/Modules/ThirdParty/OssimPlugins/src/ossim/ossimRadarSat2ProductDoc.h @@ -51,7 +51,7 @@ typedef struct vector<double> lineDenominatorCoefficients; vector<double> pixelNumeratorCoefficients; vector<double> pixelDenominatorCoefficients; - + }RPCModel; namespace ossimplugins @@ -59,17 +59,17 @@ namespace ossimplugins class PlatformPosition; class RefPoint; class SensorParams; - + /** @brief Class to encapsulate parsing RadarSat2 product.xml file. */ class OSSIM_PLUGINS_DLL ossimRadarSat2ProductDoc { public: /** @brief default constructor */ ossimRadarSat2ProductDoc(); - + /** @brief destructor */ ~ossimRadarSat2ProductDoc(); - + /** * @brief Checks for node /product/sourceAttributes/satellite containing * RADARSAT-2. @@ -77,9 +77,9 @@ public: * @return true if present, false if not. */ bool isRadarSat2(const ossimXmlDocument* xdoc) const; - + RPCModel getRpcData(const ossimXmlDocument* xdoc) const; - + /** * @brief Method to initialize PlatformPosition object from * RadarSat "product.xml" file. @@ -89,7 +89,7 @@ public: */ bool initPlatformPosition(const ossimXmlDocument* xdoc, PlatformPosition* pos) const; - + /** * @brief Method to initialize SensorParams object from * RadarSat "product.xml" file. @@ -99,7 +99,7 @@ public: */ bool initSensorParams(const ossimXmlDocument* xdoc, SensorParams* sp) const; - + /** * @brief Method to initialize image size from * RadarSat "product.xml" file. @@ -109,7 +109,7 @@ public: */ bool initImageSize(const ossimXmlDocument* xdoc, ossimIpt& imageSize) const; - + /** * @brief Method to initialize gsd from * RadarSat "product.xml" file. @@ -119,7 +119,11 @@ public: */ bool initGsd(const ossimXmlDocument* xdoc, ossimDpt& gsd) const; - + + bool getAcquistionDate(const ossimXmlDocument* xdoc, ossimString& adate); + + bool getProductionDate(const ossimXmlDocument* xdoc, ossimString& pdate); + /** * @brief Method to initialize image tie points from * RadarSat "product.xml" file. @@ -132,7 +136,7 @@ public: std::list<ossimDpt>& icp) const; bool getSatellite(const ossimXmlDocument* xdoc, ossimString& s) const; - + bool getSensor(const ossimXmlDocument* xdoc, ossimString& s) const; @@ -222,7 +226,7 @@ public: bool getIncidenceAngleFarRange(const ossimXmlDocument* xdoc, ossimString& s) const; - + bool getSatelliteHeight(const ossimXmlDocument* xdoc, ossimString& s) const; }; diff --git a/Modules/ThirdParty/OssimPlugins/src/ossim/ossimSentinel1Model.cpp b/Modules/ThirdParty/OssimPlugins/src/ossim/ossimSentinel1Model.cpp index 9f45f1625222efb4dbd33b6c6f130686d26ac808..f0bd0d5b477546e035d4ee3dac1e748b9ca096af 100644 --- a/Modules/ThirdParty/OssimPlugins/src/ossim/ossimSentinel1Model.cpp +++ b/Modules/ThirdParty/OssimPlugins/src/ossim/ossimSentinel1Model.cpp @@ -42,7 +42,6 @@ namespace ossimplugins :ossimSarModel(rhs) , theOCN(rhs.theOCN) , theSLC(rhs.theSLC) - { }