From 061a3ff38c39f7ec6023176f403d43bdd59f589e Mon Sep 17 00:00:00 2001 From: Guillaume Pasero <guillaume.pasero@c-s.fr> Date: Mon, 5 May 2014 19:21:58 +0200 Subject: [PATCH] ENH: add specific superimpose mode for PHR (WIP) --- Applications/Projections/otbSuperimpose.cxx | 203 +++++++++++++++++--- 1 file changed, 171 insertions(+), 32 deletions(-) diff --git a/Applications/Projections/otbSuperimpose.cxx b/Applications/Projections/otbSuperimpose.cxx index 536b8b4ea3..e21247efd7 100644 --- a/Applications/Projections/otbSuperimpose.cxx +++ b/Applications/Projections/otbSuperimpose.cxx @@ -24,9 +24,16 @@ #include "otbBCOInterpolateImageFunction.h" #include "itkNearestNeighborInterpolateImageFunction.h" +#include "otbPleiadesImageMetadataInterface.h" + +#include "itkScalableAffineTransform.h" + // Elevation handler #include "otbWrapperElevationParametersHandler.h" +#include "otbDateTimeAdapter.h" +#include "otbStreamingResampleImageFilter.h" + namespace otb { @@ -68,6 +75,14 @@ public: typedef otb::GenericRSResampleImageFilter<FloatVectorImageType, FloatVectorImageType> ResamplerType; + typedef itk::ScalableAffineTransform<double, 2> TransformType; + + typedef otb::ImageKeywordlist ImageKeywordlistType; + + typedef otb::StreamingResampleImageFilter + <FloatVectorImageType, + FloatVectorImageType> BasicResamplerType; + private: void DoInit() { @@ -117,7 +132,10 @@ private: AddChoice("interpolator.linear", "Linear interpolation"); SetParameterDescription("interpolator.linear","Linear interpolation leads to average image quality but is quite fast"); - + AddParameter(ParameterType_Empty, "phroptim", "PHR optimised method"); + SetParameterDescription("phroptim", "Use an optimised method for Pleiade bundle P+XS"); + DisableParameter("phroptim"); + AddRAMParameter(); // Doc example parameter settings @@ -128,7 +146,29 @@ private: void DoUpdateParameters() { - // Nothing to do here : all parameters are independent + if (!HasUserValue("phroptim") && + HasValue("inr") && + HasValue("inm")) + { + FloatVectorImageType* refImage = GetParameterImage("inr"); + FloatVectorImageType* movingImage = GetParameterImage("inm"); + bool isRefPHR = false; + bool isMovingPHR = false; + + otb::PleiadesImageMetadataInterface::Pointer phrIMI = + otb::PleiadesImageMetadataInterface::New(); + phrIMI->SetMetaDataDictionary(refImage->GetMetaDataDictionary()); + isRefPHR = phrIMI->CanRead(); + + phrIMI->SetMetaDataDictionary(movingImage->GetMetaDataDictionary()); + isMovingPHR = phrIMI->CanRead(); + + if (isRefPHR && isMovingPHR) + { + EnableParameter("phroptim"); + otbAppLogINFO(" Enable the PHR optimization"); + } + } } @@ -140,6 +180,8 @@ private: // Resample filter m_Resampler = ResamplerType::New(); + + m_BasicResampler = BasicResamplerType::New(); // Get Interpolator switch ( GetParameterInt("interpolator") ) @@ -148,12 +190,14 @@ private: { LinInterpolatorType::Pointer interpolator = LinInterpolatorType::New(); m_Resampler->SetInterpolator(interpolator); + m_BasicResampler->SetInterpolator(interpolator); } break; case Interpolator_NNeighbor: { NNInterpolatorType::Pointer interpolator = NNInterpolatorType::New(); m_Resampler->SetInterpolator(interpolator); + m_BasicResampler->SetInterpolator(interpolator); } break; case Interpolator_BCO: @@ -161,6 +205,7 @@ private: BCOInterpolatorType::Pointer interpolator = BCOInterpolatorType::New(); interpolator->SetRadius(GetParameterInt("interpolator.bco.radius")); m_Resampler->SetInterpolator(interpolator); + m_BasicResampler->SetInterpolator(interpolator); } break; } @@ -174,41 +219,135 @@ private: FloatVectorImageType::IndexType start = refImage->GetLargestPossibleRegion().GetIndex(); FloatVectorImageType::SizeType size = refImage->GetLargestPossibleRegion().GetSize(); FloatVectorImageType::PointType origin = refImage->GetOrigin(); - - if(IsParameterEnabled("lms")) - { - float defScalarSpacing = vcl_abs(GetParameterFloat("lms")); - otbAppLogDEBUG("Generating coarse deformation field (spacing="<<defScalarSpacing<<")"); - FloatVectorImageType::SpacingType defSpacing; - - defSpacing[0] = defScalarSpacing; - defSpacing[1] = defScalarSpacing; - - if (spacing[0]<0.0) defSpacing[0] *= -1.0; - if (spacing[1]<0.0) defSpacing[1] *= -1.0; - - m_Resampler->SetDisplacementFieldSpacing(defSpacing); - } - + FloatVectorImageType::PixelType defaultValue; itk::NumericTraits<FloatVectorImageType::PixelType>::SetLength(defaultValue, movingImage->GetNumberOfComponentsPerPixel()); - - m_Resampler->SetInput(movingImage); - m_Resampler->SetInputKeywordList(movingImage->GetImageKeywordlist()); - m_Resampler->SetInputProjectionRef(movingImage->GetProjectionRef()); - m_Resampler->SetOutputOrigin(origin); - m_Resampler->SetOutputSpacing(spacing); - m_Resampler->SetOutputSize(size); - m_Resampler->SetOutputStartIndex(start); - m_Resampler->SetOutputKeywordList(refImage->GetImageKeywordlist()); - m_Resampler->SetOutputProjectionRef(refImage->GetProjectionRef()); - m_Resampler->SetEdgePaddingValue(defaultValue); - - // Set the output image - SetParameterOutputImage("out", m_Resampler->GetOutput()); + + if (IsParameterEnabled("phroptim")) + { + // Setup a simple affine transform using PHR support data + + ImageKeywordlistType kwlPan; + ImageKeywordlistType kwlXS; + + itk::ExposeMetaData<ImageKeywordlistType>( + refImage->GetMetaDataDictionary(), + MetaDataKey::OSSIMKeywordlistKey, + kwlPan); + + itk::ExposeMetaData<ImageKeywordlistType>( + movingImage->GetMetaDataDictionary(), + MetaDataKey::OSSIMKeywordlistKey, + kwlXS); + + // Compute time delta + std::string strStartTimePan = kwlPan.GetMetadataByKey("support_data.time_range_start"); + std::string strStartTimeXS = kwlXS.GetMetadataByKey("support_data.time_range_start"); + + DateTimeAdapter::Pointer startTimePan = DateTimeAdapter::New(); + DateTimeAdapter::Pointer startTimeXS = DateTimeAdapter::New(); + + startTimePan->SetFromIso8601(strStartTimePan); + startTimeXS->SetFromIso8601(strStartTimeXS); + + double timeDelta = startTimeXS->GetDeltaInSeconds(startTimePan); + + // Retrieve line period in Pan + std::string tmpStr = kwlPan.GetMetadataByKey("support_data.line_period"); + double linePeriodPan = atof(tmpStr.c_str()); + + // Retrieve column start + tmpStr = kwlPan.GetMetadataByKey("support_data.swath_first_col"); + int colStartPan = atoi(tmpStr.c_str()); + tmpStr = kwlXS.GetMetadataByKey("support_data.swath_first_col"); + int colStartXS = atoi(tmpStr.c_str()); + + // Compute shift between MS and P (in Pan pixels) + int lineShift_MS_P =int(vcl_floor((timeDelta/(linePeriodPan/1000)) + 0.5)); + int colShift_MS_P = colStartXS*4 - colStartPan; + + // Apply the scaling + TransformType::Pointer transform = TransformType::New(); + transform->Scale(4.0); + + // Resample filter assumes the origin is attached to the pixel center + // in order to keep the top left corners unchanged, apply a 3/2 pixels + // shift in each direction + TransformType::OutputVectorType offset; + offset[0] = 1.5 - static_cast<double>(colShift_MS_P); + offset[1] = 1.5 - static_cast<double>(lineShift_MS_P); + transform->Translate(offset); + + // Invert the transform as the resampler filter expect an output-to-input + // transform (we have computed the input-to-output transform) + TransformType::Pointer realTransform = TransformType::New(); + transform->GetInverse(realTransform); + m_BasicResampler->SetTransform(realTransform); + + m_BasicResampler->SetInput(movingImage); + + m_BasicResampler->SetOutputOrigin(origin); + m_BasicResampler->SetOutputSpacing(spacing); + m_BasicResampler->SetOutputSize(size); + m_BasicResampler->SetOutputStartIndex(start); + + m_BasicResampler->SetEdgePaddingValue(defaultValue); + + // Set the output image + SetParameterOutputImage("out", m_BasicResampler->GetOutput()); + + // DEBUG + otbAppLogINFO("Panchro start (in s) : "<< startTimePan->GetSeconds()); + otbAppLogINFO("MS start (in s) : "<< startTimeXS->GetSeconds()); + otbAppLogINFO(" Time delta (in s) : "<< timeDelta); + otbAppLogINFO("Line period P (in ms): "<< linePeriodPan); + otbAppLogINFO("Line shift : "<< lineShift_MS_P); + otbAppLogINFO("Col shift : "<< colShift_MS_P); + //DisableParameter("out"); + //return; + } + else + { + if(IsParameterEnabled("lms")) + { + float defScalarSpacing = vcl_abs(GetParameterFloat("lms")); + otbAppLogDEBUG("Generating coarse deformation field (spacing="<<defScalarSpacing<<")"); + FloatVectorImageType::SpacingType defSpacing; + + defSpacing[0] = defScalarSpacing; + defSpacing[1] = defScalarSpacing; + + if (spacing[0]<0.0) defSpacing[0] *= -1.0; + if (spacing[1]<0.0) defSpacing[1] *= -1.0; + + m_Resampler->SetDisplacementFieldSpacing(defSpacing); + } + + // Setup transform through projRef and Keywordlist + m_Resampler->SetInputKeywordList(movingImage->GetImageKeywordlist()); + m_Resampler->SetInputProjectionRef(movingImage->GetProjectionRef()); + + m_Resampler->SetOutputKeywordList(refImage->GetImageKeywordlist()); + m_Resampler->SetOutputProjectionRef(refImage->GetProjectionRef()); + + m_Resampler->SetInput(movingImage); + + m_Resampler->SetOutputOrigin(origin); + m_Resampler->SetOutputSpacing(spacing); + m_Resampler->SetOutputSize(size); + m_Resampler->SetOutputStartIndex(start); + + m_Resampler->SetEdgePaddingValue(defaultValue); + + // Set the output image + SetParameterOutputImage("out", m_Resampler->GetOutput()); + } } ResamplerType::Pointer m_Resampler; + + BasicResamplerType::Pointer m_BasicResampler; + }; } // end namespace Wrapper -- GitLab