Commit de58687e authored by Cédric Traizet's avatar Cédric Traizet
Browse files

Merge branch 'sar_io' into 'develop'

Fixes in Sar metadata IOs

See merge request !861
parents 97259b15 70579cfd
Pipeline #8863 passed with stages
in 143 minutes and 9 seconds
......@@ -69,8 +69,15 @@ public:
void Print(std::ostream& os) const;
std::string ToJSON(bool multiline=false) const;
/** Keywordlist export */
void ToKeywordlist(MetaData::Keywordlist & kwl, const std::string & prefix) const;
/** Keywordlist import */
static GCP FromKeywordlist(const MetaData::Keywordlist & kwl, const std::string & prefix);
};
namespace Projection
{
......@@ -86,6 +93,12 @@ struct OTBMetadata_EXPORT GCPParam
// JSON export
std::string ToJSON(bool multiline=false) const;
/** Keywordlist export */
void ToKeywordlist(MetaData::Keywordlist & kwl, const std::string & prefix) const;
/** Keywordlist import */
void FromKeywordlist(const MetaData::Keywordlist & kwl, const std::string & prefix);
};
/** \struct RPCParam
......
......@@ -22,6 +22,53 @@
#include <iostream>
namespace
{
constexpr int STRING_PRECISION = 20;
// the precision of std::to_string is limited to 6 digits
template <typename T>
std::string to_string_with_precision(const T value)
{
std::ostringstream out;
out.precision(STRING_PRECISION);
out << std::fixed << value;
return out.str();
}
template<class T>
void KeywordlistToVector(std::vector<T> & vector,
const otb::MetaData::Keywordlist & kwl,
const std::string & prefix)
{
vector.clear();
const auto size = std::stoi(kwl.at(prefix + ".number"));
for (int i = 0; i < size; i++)
{
auto t = T::FromKeywordlist(kwl, prefix + "_" + to_string_with_precision(i) + ".");
vector.push_back(t);
}
}
template <class T>
void VectorToKeywordList(otb::MetaData::Keywordlist & kwl,
const std::vector<T> & input,
const std::string & prefix)
{
int i = 0;
for (const auto & elem: input)
{
elem.ToKeywordlist(kwl, prefix + "_" + to_string_with_precision(i) + ".");
i++;
}
kwl.insert({prefix + ".number" , to_string_with_precision(i)});
}
}
namespace otb
{
......@@ -58,6 +105,36 @@ std::string GCP::ToJSON(bool multiline) const
return oss.str();
}
void GCP::ToKeywordlist(MetaData::Keywordlist & kwl, const std::string & prefix) const
{
kwl.insert({prefix + "Id", m_Id});
kwl.insert({prefix + "Info", m_Info});
kwl.insert({prefix + "Row", to_string_with_precision(m_GCPRow)});
kwl.insert({prefix + "Col", to_string_with_precision(m_GCPCol)});
kwl.insert({prefix + "X", to_string_with_precision(m_GCPX)});
kwl.insert({prefix + "Y", to_string_with_precision(m_GCPY)});
kwl.insert({prefix + "Z", to_string_with_precision(m_GCPZ)});
}
GCP GCP::FromKeywordlist(const MetaData::Keywordlist & kwl, const std::string & prefix)
{
//Info is optional in GCPs, the key might not be in the keywordlist
std::string info;
auto infoFound = kwl.find(prefix + "Info");
if (infoFound != kwl.end())
{
info = infoFound->second;
}
return GCP(kwl.at(prefix + "Id"),
info,
std::stod(kwl.at(prefix + "Row")),
std::stod(kwl.at(prefix + "Col")),
std::stod(kwl.at(prefix + "X")),
std::stod(kwl.at(prefix + "Y")),
std::stod(kwl.at(prefix + "Z")));
}
namespace Projection
{
std::string GCPParam::ToJSON(bool multiline) const
......@@ -77,6 +154,18 @@ std::string GCPParam::ToJSON(bool multiline) const
return oss.str();
}
void GCPParam::ToKeywordlist(MetaData::Keywordlist & kwl, const std::string & prefix) const
{
kwl.insert({prefix + "GCPProjection", GCPProjection});
VectorToKeywordList(kwl, GCPs, prefix + "GCP");
}
void GCPParam::FromKeywordlist(const MetaData::Keywordlist & kwl, const std::string & prefix)
{
GCPProjection = kwl.at(prefix + "GCPProjection");
KeywordlistToVector(GCPs, kwl, prefix + "GCP");
}
std::string RPCParam::ToJSON(bool multiline) const
{
std::ostringstream oss;
......
......@@ -392,7 +392,6 @@ void SARCalib::ToKeywordlist(MetaData::Keywordlist & kwl, const std::string & pr
// MetaData::Time
std::ostringstream oss;
oss << calibrationStartTime;
std::cout << "***** " << oss.str() << std::endl;
kwl.insert({prefix + "CalibrationStartTime", oss.str()});
oss.str("");
oss << calibrationStopTime;
......
......@@ -265,14 +265,16 @@ NoiseVectorLists ReadNoiseVectorListsFromXML(const MetadataSupplierInterface& md
}
std::string azimuthNoisePrefix = "noise.noiseAzimuthVectorList.";
std::string azimuthVectorName = "noiseAzimuthVector_";
std::string azimuthVectorName = "noiseAzimuthVector";
std::string azimuthLUTName = "noiseAzimuthLut";
const int azimuthCount = mds.GetAs<int>(0, azimuthNoisePrefix + "count");
for (int i = 0; i < azimuthCount; i++)
{
const auto prefix = azimuthNoisePrefix + azimuthVectorName + std::to_string(i+1) + ".";
const auto prefix = azimuthCount == 1
? azimuthNoisePrefix + azimuthVectorName + "."
: azimuthNoisePrefix + azimuthVectorName + "_" + std::to_string(i+1) + ".";
Sentinel1AzimuthNoiseStruct azimuthNoiseVector;
azimuthNoiseVector.firstAzimuthLine = mds.GetAs<int>(prefix + "firstAzimuthLine");
......
......@@ -41,7 +41,6 @@
#include "ogr_spatialref.h"
#include "ogr_srs_api.h"
#include "itksys/RegularExpression.hxx"
#include "otbGDALDriverManagerWrapper.h"
......@@ -1314,15 +1313,6 @@ void GDALImageIO::InternalWriteImageInformation(const void* buffer)
m_Imd.Bands = bandRangeMetadata;
}
// TODO : this should be a warning instead of an exception
// For complex pixels the number of bands is twice the number of components (in GDAL sense)
if ( !m_Imd.Bands.empty()
&& static_cast<std::size_t>(m_NbBands) != m_Imd.Bands.size()
&& !((m_Imd.Bands.size() == static_cast<std::size_t>(2 * m_NbBands)) && this->GetPixelType() == COMPLEX))
{
itkExceptionMacro(<< "Number of bands in metadata inconsistent with actual image.");
}
if ((m_Dimensions[0] == 0) && (m_Dimensions[1] == 0))
{
itkExceptionMacro(<< "Dimensions are not defined.");
......@@ -1550,6 +1540,18 @@ void GDALImageIO::InternalWriteImageInformation(const void* buffer)
MetaData::Keywordlist SARKwl;
const auto & param = boost::any_cast<const otb::SARParam&>(m_Imd[MDGeom::SAR]);
param.ToKeywordlist(SARKwl, "SAR.");
// Write GCP as metadata (not GDAL gcps) because SAR sensor images needs GCPs and
// might also have a geotransform (e.g. after a ROI extraction), which is undefined
// in GDAL. Note that the geotransform is not applied to the GCPs in this case
if (m_Imd.Has(MDGeom::GCP))
{
const Projection::GCPParam & gcpParam =
boost::any_cast<const Projection::GCPParam&>(m_Imd[MDGeom::GCP]);
gcpParam.ToKeywordlist(SARKwl, "SAR.");
}
for (auto & key: SARKwl)
{
dataset->SetMetadataItem(key.first.c_str(), key.second.c_str());
......@@ -1907,6 +1909,12 @@ void GDALImageIO::ExportMetadata()
// be prefixed by: MDGeomNames[MDGeom::SensorGeometry] + '.'
ImageMetadataBase::Keywordlist kwl;
m_Imd.ToKeywordlist(kwl);
if (m_Imd.Has(MDGeom::SARCalib))
{
const auto & param = boost::any_cast<const otb::SARCalib&>(m_Imd[MDGeom::SARCalib]);
param.ToKeywordlist(kwl, "SARCalib.");
}
KeywordlistToMetadata(kwl);
int bIdx = 0;
......@@ -1939,6 +1947,10 @@ void GDALImageIO::ImportMetadata()
otb::SARParam sar;
sar.FromKeywordlist(kwl, "SAR.");
m_Imd.Add(MDGeom::SAR, sar);
otb::Projection::GCPParam gcps;
gcps.FromKeywordlist(kwl, "SAR.");
m_Imd.Add(MDGeom::GCP, gcps);
}
catch(const std::exception& e)
{
......@@ -1946,6 +1958,20 @@ void GDALImageIO::ImportMetadata()
}
}
// Decode SAR metadata
if (kwl.find("SARCalib") != kwl.end())
{
try
{
otb::SARCalib sarCalib;
sarCalib.FromKeywordlist(kwl, "SARCalib.");
m_Imd.Add(MDGeom::SARCalib, sarCalib);
}
catch(const std::exception& e)
{
otbLogMacro(Warning, << "Input image has SAR calibration metadata, but OTB was not able to read it: " << e.what());
}
}
m_Imd.FromKeywordlist(kwl);
// Parsing the bands
......@@ -1955,7 +1981,6 @@ void GDALImageIO::ImportMetadata()
GDALMetadataToKeywordlist(m_Dataset->GetDataSet()->GetRasterBand(band+1)->GetMetadata(), kwl);
m_Imd.Bands[band].FromKeywordlist(kwl);
}
}
void GDALImageIO::KeywordlistToMetadata(ImageMetadataBase::Keywordlist kwl, int band)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment