Commit afe528fb authored by Etienne Bougoin's avatar Etienne Bougoin

ENH: Reading TerraSarX Metadata incidence angles

parent a6cc36e3
......@@ -398,7 +398,6 @@ TerraSarImageMetadataInterface::GetNoise( const MetaDataDictionaryType & dict )
return noise;
}
unsigned int
TerraSarImageMetadataInterface::GetNumberOfNoiseRecords( const MetaDataDictionaryType & dict ) const
{
......@@ -553,7 +552,6 @@ TerraSarImageMetadataInterface::GetNoiseTimeUTCList( const MetaDataDictionaryTyp
return timeList;
}
TerraSarImageMetadataInterface::DoubleVectorType
TerraSarImageMetadataInterface::GetNoiseValidityRangeMaxList( const MetaDataDictionaryType & dict ) const
{
......@@ -586,8 +584,6 @@ TerraSarImageMetadataInterface::GetNoiseValidityRangeMaxList( const MetaDataDict
return maxList;
}
TerraSarImageMetadataInterface::DoubleVectorType
TerraSarImageMetadataInterface::GetNoiseValidityRangeMinList( const MetaDataDictionaryType & dict ) const
{
......@@ -654,7 +650,6 @@ TerraSarImageMetadataInterface::GetNoiseReferencePointList( const MetaDataDictio
return refPointList;
}
double
TerraSarImageMetadataInterface::GetRadarFrequency( const MetaDataDictionaryType & dict ) const
{
......@@ -679,4 +674,225 @@ TerraSarImageMetadataInterface::GetRadarFrequency( const MetaDataDictionaryType
return freq;
}
ossimplugins::IncidenceAngles*
TerraSarImageMetadataInterface::GetIncidenceAngles( const MetaDataDictionaryType & dict ) const
{
if( !this->CanRead( dict ) )
{
itkExceptionMacro(<<"Invalid Metadata, no TerraSar Image");
}
ImageKeywordlistType imageKeywordlist;
if (dict.HasKey(MetaDataKey::OSSIMKeywordlistKey))
{
itk::ExposeMetaData<ImageKeywordlistType>(dict, MetaDataKey::OSSIMKeywordlistKey, imageKeywordlist);
}
ossimKeywordlist kwl;
imageKeywordlist.convertToOSSIMKeywordlist(kwl);
ossimplugins::IncidenceAngles* incidenceAngles = new ossimplugins::IncidenceAngles();
incidenceAngles->loadState( kwl, "");
return incidenceAngles;
}
unsigned int
TerraSarImageMetadataInterface::GetNumberOfCornerIncidenceAngles( const MetaDataDictionaryType & dict ) const
{
ossimplugins::IncidenceAngles * ia = this->GetIncidenceAngles( dict );
ImageKeywordlistType imageKeywordlist;
if (dict.HasKey(MetaDataKey::OSSIMKeywordlistKey))
{
itk::ExposeMetaData<ImageKeywordlistType>(dict, MetaDataKey::OSSIMKeywordlistKey, imageKeywordlist);
}
ossimKeywordlist kwl;
imageKeywordlist.convertToOSSIMKeywordlist(kwl);
std::string key = "incidenceAngles.numberOfCornerIncidenceAngles";
ossimString nbCornerAngles = kwl.find(key.c_str());
delete ia;
return static_cast<unsigned int>(nbCornerAngles.toInt());
}
double
TerraSarImageMetadataInterface::GetMeanIncidenceAngles( const MetaDataDictionaryType & dict ) const
{
ossimplugins::IncidenceAngles * ia = this->GetIncidenceAngles( dict );
ImageKeywordlistType imageKeywordlist;
double sum = 0.;
if (dict.HasKey(MetaDataKey::OSSIMKeywordlistKey))
{
itk::ExposeMetaData<ImageKeywordlistType>(dict, MetaDataKey::OSSIMKeywordlistKey, imageKeywordlist);
}
ossimKeywordlist kwl;
imageKeywordlist.convertToOSSIMKeywordlist(kwl);
itk::OStringStream oss;
std::string key = "incidenceAngles.centerInfoIncidenceAngle.infoIncidenceAngle.incidenceAngle";
ossimString centerIncidenceAngle = kwl.find(key.c_str());
sum += centerIncidenceAngle.toDouble();
unsigned int nbAngles = this->GetNumberOfCornerIncidenceAngles(dict);
for(unsigned int i=0; i<nbAngles; i++)
{
oss.str("");
oss << "incidenceAngles.cornersInfoIncidenceAngle[" << i << "].infoIncidenceAngle.incidenceAngle";
ossimString tempVal = kwl.find(oss.str().c_str());
sum += tempVal.toDouble();
}
delete ia;
return (sum / (nbAngles + 1));
}
double
TerraSarImageMetadataInterface::GetCenterIncidenceAngle( const MetaDataDictionaryType & dict ) const
{
ossimplugins::IncidenceAngles * ia = this->GetIncidenceAngles( dict );
ImageKeywordlistType imageKeywordlist;
if (dict.HasKey(MetaDataKey::OSSIMKeywordlistKey))
{
itk::ExposeMetaData<ImageKeywordlistType>(dict, MetaDataKey::OSSIMKeywordlistKey, imageKeywordlist);
}
ossimKeywordlist kwl;
imageKeywordlist.convertToOSSIMKeywordlist(kwl);
std::string key = "incidenceAngles.centerInfoIncidenceAngle.infoIncidenceAngle.incidenceAngle";
ossimString tempVal = kwl.find(key.c_str());
delete ia;
return tempVal.toDouble();
}
TerraSarImageMetadataInterface::IndexType
TerraSarImageMetadataInterface::GetCenterIncidenceAngleIndex( const MetaDataDictionaryType & dict ) const
{
ossimplugins::IncidenceAngles * ia = this->GetIncidenceAngles( dict );
TerraSarImageMetadataInterface::IndexType it;
ImageKeywordlistType imageKeywordlist;
if (dict.HasKey(MetaDataKey::OSSIMKeywordlistKey))
{
itk::ExposeMetaData<ImageKeywordlistType>(dict, MetaDataKey::OSSIMKeywordlistKey, imageKeywordlist);
}
ossimKeywordlist kwl;
imageKeywordlist.convertToOSSIMKeywordlist(kwl);
std::string key = "incidenceAngles.centerInfoIncidenceAngle.infoIncidenceAngle.refRow";
ossimString tempVal = kwl.find(key.c_str());
it[0] = tempVal.toInt();
key = "incidenceAngles.centerInfoIncidenceAngle.infoIncidenceAngle.refColumn";
tempVal = kwl.find(key.c_str());
it[1] = tempVal.toInt();
delete ia;
return it;
}
TerraSarImageMetadataInterface::DoubleVectorType
TerraSarImageMetadataInterface::GetCornersIncidenceAngles( const MetaDataDictionaryType & dict ) const
{
ossimplugins::IncidenceAngles * ia = this->GetIncidenceAngles( dict );
ImageKeywordlistType imageKeywordlist;
TerraSarImageMetadataInterface::DoubleVectorType dv;
if (dict.HasKey(MetaDataKey::OSSIMKeywordlistKey))
{
itk::ExposeMetaData<ImageKeywordlistType>(dict, MetaDataKey::OSSIMKeywordlistKey, imageKeywordlist);
}
ossimKeywordlist kwl;
imageKeywordlist.convertToOSSIMKeywordlist(kwl);
itk::OStringStream oss;
unsigned int nbAngles = this->GetNumberOfCornerIncidenceAngles(dict);
for(unsigned int i=0; i<nbAngles; i++)
{
oss.str("");
oss << "incidenceAngles.cornersInfoIncidenceAngle[" << i << "].infoIncidenceAngle.incidenceAngle";
ossimString tempVal = kwl.find(oss.str().c_str());
dv.push_back(tempVal.toDouble());
}
delete ia;
return dv;
}
TerraSarImageMetadataInterface::IndexVectorType
TerraSarImageMetadataInterface::GetCornersIncidenceAnglesIndex( const MetaDataDictionaryType & dict ) const
{
ossimplugins::IncidenceAngles * ia = this->GetIncidenceAngles( dict );
ImageKeywordlistType imageKeywordlist;
TerraSarImageMetadataInterface::IndexVectorType iv;
if (dict.HasKey(MetaDataKey::OSSIMKeywordlistKey))
{
itk::ExposeMetaData<ImageKeywordlistType>(dict, MetaDataKey::OSSIMKeywordlistKey, imageKeywordlist);
}
ossimKeywordlist kwl;
imageKeywordlist.convertToOSSIMKeywordlist(kwl);
itk::OStringStream oss;
itk::OStringStream oss2;
unsigned int nbAngles = this->GetNumberOfCornerIncidenceAngles(dict);
for(unsigned int i=0; i<nbAngles; i++)
{
TerraSarImageMetadataInterface::IndexType it;
oss.str("");
oss << "incidenceAngles.cornersInfoIncidenceAngle[" << i << "].infoIncidenceAngle.refRow";
ossimString tempVal = kwl.find(oss.str().c_str());
it[0] = tempVal.toInt();
oss2.str("");
oss2 << "incidenceAngles.cornersInfoIncidenceAngle[" << i << "].infoIncidenceAngle.refColumn";
tempVal = kwl.find(oss2.str().c_str());
it[1] = tempVal.toInt();
iv.push_back(it);
}
delete ia;
return iv;
}
} // end namespace otb
......@@ -30,6 +30,7 @@
#include "otbImageKeywordlist.h"
#include "itkImageBase.h"
#include <otb/Noise.h>
#include <otb/IncidenceAngles.h>
#include <string>
namespace otb
......@@ -56,6 +57,8 @@ public:
itkTypeMacro(TerraSarImageMetadataInterface, itk::Object);
typedef itk::ImageBase< 2 > ImageType;
typedef ImageType::IndexType IndexType;
typedef std::vector<IndexType> IndexVectorType;
typedef itk::MetaDataDictionary MetaDataDictionaryType;
typedef MetaDataKey::VectorType VectorType;
typedef MetaDataKey::VariableLengthVectorType VariableLengthVectorType;
......@@ -99,10 +102,10 @@ public:
/** Get the noise structure */
ossimplugins::Noise * GetNoise( const MetaDataDictionaryType & ) const;
/** Get the number of noise records */
unsigned int GetNumberOfNoiseRecords( const MetaDataDictionaryType & ) const;
/** Get the polynomial degree list */
UIntVectorType GetNoisePolynomialDegrees( const MetaDataDictionaryType & ) const;
......@@ -124,6 +127,27 @@ public:
/** Get the radar frequency */
double GetRadarFrequency( const MetaDataDictionaryType & ) const;
/** Get the incidence angles structure */
ossimplugins::IncidenceAngles* GetIncidenceAngles( const MetaDataDictionaryType & ) const;
/** Get the number of corner incidence angles */
unsigned int GetNumberOfCornerIncidenceAngles( const MetaDataDictionaryType & ) const;
/** Get the Mean Incidence angles */
double GetMeanIncidenceAngles( const MetaDataDictionaryType & ) const;
/** Get the center incidence angle */
double GetCenterIncidenceAngle( const MetaDataDictionaryType & ) const;
/** Get the center index */
IndexType GetCenterIncidenceAngleIndex( const MetaDataDictionaryType & ) const;
/** Get the corners incidence angles */
DoubleVectorType GetCornersIncidenceAngles( const MetaDataDictionaryType & ) const;
/** Get the corners index */
IndexVectorType GetCornersIncidenceAnglesIndex( const MetaDataDictionaryType & ) const;
bool CanRead( const MetaDataDictionaryType & ) const;
protected:
......
......@@ -33,16 +33,21 @@ TerraSarBrightnessImageFilter<TInputImage,TOutputImage>
{
Superclass::BeforeThreadedGenerateData();
// Load metada
TerraSarImageMetadataInterface::Pointer lImageMetadata = otb::TerraSarImageMetadataInterface::New();
bool mdIsAvailable = lImageMetadata->CanRead(this->GetInput()->GetMetaDataDictionary());
// If the user doesn't set it AND the metadata is available, set calFactor using image metadata
if (this->GetCalFactor() == itk::NumericTraits<double>::min())
{
/** TODO : use a factory for RADAR image metadata interface */
TerraSarImageMetadataInterface::Pointer lImageMetadata = otb::TerraSarImageMetadataInterface::New();
if( !lImageMetadata->CanRead(this->GetInput()->GetMetaDataDictionary()) )
{
itkExceptionMacro(<<"Invalid input image. Only TerraSar images are supported");
}
this->SetCalFactor( lImageMetadata->GetCalibrationFactor(this->GetInput()->GetMetaDataDictionary()) );
if (mdIsAvailable)
{
this->SetCalFactor( lImageMetadata->GetCalibrationFactor(this->GetInput()->GetMetaDataDictionary()) );
}
else
{
itkExceptionMacro(<<"Invalid input image. Only TerraSar images are supproted");
}
}
}
......
......@@ -26,6 +26,7 @@
#include "otbUnaryFunctorWithIndexImageFilter.h"
#include "otbTerraSarFunctors.h"
#include "itkMetaDataDictionary.h"
//#include "itkUnaryFunctorImageFilter.h"
//#include "itkConstNeighborhoodIterator.h"
#include "otbMath.h"
......@@ -77,7 +78,7 @@ public:
typedef itk::MetaDataDictionary MetaDataDictionaryType;
typedef typename FunctorType::DoubleVectorType DoubleVectorType;
typedef typename FunctorType::DoubleVectorVectorType DoubleVectorVectorType;
typedef typename FunctorType::LIntVectorType LIntVectorType;
// typedef typename FunctorType::LIntVectorType LIntVectorType;
/** Accessors */
/** Calibration Factor */
......@@ -106,9 +107,9 @@ public:
* of the pixel in the image. */
void SetUseFastCalibrationMethod( bool b );
bool GetUseFastCalibrationMethod() const;
/** TimeUTC for each noise coefficient acquisition (in second). */
void SetTimeUTC( LIntVectorType vect );
LIntVectorType GetTimeUTC() const;
/** TimeUTC for each noise coefficient acquisition (in Julian day). */
void SetTimeUTC( DoubleVectorType vect );
DoubleVectorType GetTimeUTC() const;
/** Pulse Repetition Frequency */
void SetPRF( double val );
double GetPRF() const;
......
......@@ -18,10 +18,11 @@
#ifndef __otbTerraSarCalibrationImageFilter_txx
#define __otbTerraSarCalibrationImageFilter_txx
#include <algorithm>
#include "otbTerraSarCalibrationImageFilter.h"
#include "otbImageMetadataInterfaceFactory.h"
#include "otbImageMetadataInterfaceBase.h"
//#include "otbImageMetadataInterfaceFactory.h"
//#include "otbImageMetadataInterfaceBase.h"
#include "otbTerraSarImageMetadataInterface.h"
namespace otb
{
......@@ -41,27 +42,144 @@ TerraSarCalibrationImageFilter<TInputImage,TOutputImage>
{
Superclass::BeforeThreadedGenerateData();
if(this->GetFunctor().GetNoisePolynomialCoefficientsList().size() == 0)
itkExceptionMacro(<<"Empty NoisePolynomialCoefficientsList.");
// If the user doesn't set it AND the metadata is available, set calFactor using image metadata
// std::cout<<this->GetCalFactor()<<std::endl;
// if (this->GetCalFactor() == itk::NumericTraits<double>::min())
// {
// /** TODO : use a factory for RADAR image metadata interface */
// TerraSarImageMetadataInterface::Pointer lImageMetadata = otb::TerraSarImageMetadataInterface::New();
// if( !lImageMetadata->CanRead(this->GetInput()->GetMetaDataDictionary()) )
// {
// itkExceptionMacro(<<"Invalid input image. Only TerraSar images are supproted");
// }
// this->SetCalFactor( lImageMetadata->GetCalibrationFactor(this->GetInput()->GetMetaDataDictionary()) );
// }
// Load metadata
TerraSarImageMetadataInterface::Pointer lImageMetadata = otb::TerraSarImageMetadataInterface::New();
bool mdIsAvailable = lImageMetadata->CanRead(this->GetInput()->GetMetaDataDictionary());
// If the user doesn't set the data AND the metadata is available, set the data
// CalFactor
if (this->GetCalFactor() == itk::NumericTraits<double>::min())
{
if (mdIsAvailable)
{
this->SetCalFactor( lImageMetadata->GetCalibrationFactor(this->GetInput()->GetMetaDataDictionary()) );
}
else
{
itkExceptionMacro(<<"Invalid input image. Only TerraSar images are supproted");
}
}
if( this->GetFunctor().GetUseFastCalibrationMethod() == false )
// NoiseRangeValidityMin
if (this->GetNoiseRangeValidityMin() == itk::NumericTraits<double>::min())
{
if (mdIsAvailable)
{
unsigned int size = this->GetFunctor().GetNoisePolynomialCoefficientsList()[0].size();
for(unsigned int i=1; i<this->GetFunctor().GetNoisePolynomialCoefficientsList().size(); i++)
{
if( this->GetFunctor().GetNoisePolynomialCoefficientsList()[i].size() != size )
itkExceptionMacro(<<"Wrong noise polynomial coefficient, degrees mismatch.");
}
if( this->GetFunctor().GetTimeUTC().size() != this->GetFunctor().GetNoisePolynomialCoefficientsList().size() )
itkExceptionMacro(<<"Number of Time UTC and number of noise polynomials mismatch."<<this->GetFunctor().GetTimeUTC().size()<<" "<<this->GetFunctor().GetNoisePolynomialCoefficientsList().size());
DoubleVectorType vecTmp = lImageMetadata->GetNoiseValidityRangeMinList(this->GetInput()->GetMetaDataDictionary());
std::sort(vecTmp.begin(), vecTmp.end());
this->SetNoiseRangeValidityMin(vecTmp[0]);
}
else
{
itkExceptionMacro(<<"Invalid input image. Only TerraSar images are supproted");
}
}
// NoiseRangeValidityMax
if (this->GetNoiseRangeValidityMax() == itk::NumericTraits<double>::max())
{
if (mdIsAvailable)
{
DoubleVectorType vecTmp = lImageMetadata->GetNoiseValidityRangeMaxList(this->GetInput()->GetMetaDataDictionary());
std::sort(vecTmp.begin(), vecTmp.end());
this->SetNoiseRangeValidityMax(vecTmp[vecTmp.size()-1]);
}
else
{
itkExceptionMacro(<<"Invalid input image. Only TerraSar images are supproted");
}
}
if(this->GetFunctor().GetPRF() == 0.)
itkExceptionMacro(<<"PRF can't be null.");
// NoiseRangeValidityRef
if (this->GetNoiseRangeValidityRef() == itk::NumericTraits<double>::Zero)
{
if (mdIsAvailable)
{
double sum = 0;
// Get vector
DoubleVectorType noiseRefList = lImageMetadata->GetNoiseReferencePointList(this->GetInput()->GetMetaDataDictionary());
// Mean computation
for (int i=0; i<noiseRefList.size(); i++)
{
sum += noiseRefList[i];
}
this->SetNoiseRangeValidityRef( sum / noiseRefList.size() );
}
this->GetFunctor().SetImageSize( this->GetInput()->GetLargestPossibleRegion().GetSize() );
else
{
itkExceptionMacro(<<"Invalid input image. Only TerraSar images are supproted");
}
}
// NoisePolynomialCoefficient
if ( ((this->GetNoisePolynomialCoefficientsList())[0][0] == itk::NumericTraits<double>::Zero)
&& (this->GetNoisePolynomialCoefficientsList().size() == 1)
&& (this->GetNoisePolynomialCoefficientsList()[0].size() == 1) )
{
if (mdIsAvailable)
{
this->SetNoisePolynomialCoefficientsList(lImageMetadata->GetNoisePolynomialCoefficientsList(this->GetInput()->GetMetaDataDictionary()));
}
else
{
itkExceptionMacro(<<"Invalid input image. Only TerraSar images are supproted");
}
}
// Time UTC
if ((this->GetTimeUTC()[0] == itk::NumericTraits<double>::Zero) && (this->GetTimeUTC()[1] == 1.) && (this->GetTimeUTC().size() == 2))
{
if (mdIsAvailable)
{
this->SetTimeUTC(lImageMetadata->GetNoiseTimeUTCList(this->GetInput()->GetMetaDataDictionary()));
}
else
{
itkExceptionMacro(<<"Invalid input image. Only TerraSar images are supproted");
}
}
// Radar frequency (PRF)
if (this->GetPRF() == 1.)
{
if (mdIsAvailable)
{
this->SetPRF(lImageMetadata->GetRadarFrequency(this->GetInput()->GetMetaDataDictionary()));
}
else
{
itkExceptionMacro(<<"Invalid input image. Only TerraSar images are supproted");
}
}
// Incidence Angle
if (this->GetLocalIncidentAngle() == itk::NumericTraits<double>::Zero)
{
if (mdIsAvailable)
{
double mean = lImageMetadata->GetMeanIncidenceAngles(this->GetInput()->GetMetaDataDictionary());
this->SetLocalIncidentAngle(mean);
}
else
{
itkExceptionMacro(<<"Invalid input image. Only TerraSar images are supproted");
}
}
}
......@@ -201,7 +319,7 @@ TerraSarCalibrationImageFilter<TInputImage,TOutputImage>
template <class TInputImage, class TOutputImage>
void
TerraSarCalibrationImageFilter<TInputImage,TOutputImage>
::SetTimeUTC( LIntVectorType vect )
::SetTimeUTC( DoubleVectorType vect )
{
this->GetFunctor().SetTimeUTC( vect );
this->Modified();
......@@ -209,7 +327,7 @@ TerraSarCalibrationImageFilter<TInputImage,TOutputImage>
template <class TInputImage, class TOutputImage>
typename TerraSarCalibrationImageFilter<TInputImage,TOutputImage>::LIntVectorType
typename TerraSarCalibrationImageFilter<TInputImage,TOutputImage>::DoubleVectorType
TerraSarCalibrationImageFilter<TInputImage,TOutputImage>
::GetTimeUTC() const
{
......
......@@ -111,8 +111,8 @@ public:
SizeType GetImageSize() const { return m_ImageSize; };
void SetUseFastCalibrationMethod( bool b ) { m_UseFastCalibrationMethod = b; };
bool GetUseFastCalibrationMethod() const { return m_UseFastCalibrationMethod; };
void SetTimeUTC( LIntVectorType vect ) { m_TimeUTC = vect; };
LIntVectorType GetTimeUTC() const { return m_TimeUTC; };
void SetTimeUTC( DoubleVectorType vect ) { m_TimeUTC = vect; };
DoubleVectorType GetTimeUTC() const { return m_TimeUTC; };
void SetPRF( double val ) { m_PRF = val; m_InvPRF = 1./m_PRF; };
double GetPRF() const { return m_PRF; };
double GetInvPRF() const { return m_InvPRF; };
......@@ -146,8 +146,8 @@ private:
* will use all of them and applied it according to its acquisition UTC time and the coordinates
* of the pixel in the image. */
bool m_UseFastCalibrationMethod;
/** TimeUTC for each noise coefficient acquisition (in second). */
LIntVectorType m_TimeUTC;
/** TimeUTC for each noise coefficient acquisition (in Julian day). */
DoubleVectorType m_TimeUTC;
/** Pulse Repetition Frequency */
double m_PRF;
/** Inverse Pulse Repetition Frequency */
......
......@@ -75,17 +75,17 @@ template <class TInput, class TOutput>
TerraSarCalibrationImageFunctor<TInput, TOutput>
::TerraSarCalibrationImageFunctor()
{
m_CalFactor = 1.;
m_NoiseRangeValidityMin = 0.;
m_NoiseRangeValidityMax = 0.;
m_NoiseRangeValidityRef = 0.;
m_LocalIncidentAngle = 0.;
m_SinLocalIncidentAngle = 0.;
m_NoisePolynomialCoefficientsList = DoubleVectorVectorType( 1, DoubleVectorType(1, 0.) );
m_CalFactor = itk::NumericTraits<double>::min();
m_NoiseRangeValidityMin = itk::NumericTraits<double>::min();
m_NoiseRangeValidityMax = itk::NumericTraits<double>::max();
m_NoiseRangeValidityRef = itk::NumericTraits<double>::Zero;
m_LocalIncidentAngle = itk::NumericTraits<double>::Zero;
m_SinLocalIncidentAngle = itk::NumericTraits<double>::Zero;
m_NoisePolynomialCoefficientsList = DoubleVectorVectorType( 1, DoubleVectorType(1, itk::NumericTraits<double>::Zero) );
m_ImageSize.Fill(0);
m_UseFastCalibrationMethod = true;
m_TimeUTC = LIntVectorType(2, 0);
m_TimeUTC[1] = 1;
m_TimeUTC = DoubleVectorType(2, itk::NumericTraits<double>::Zero);