Commit 028c0e0a authored by Guillaume Pasero's avatar Guillaume Pasero
Browse files

Merge branch 'pansharp-composite' into develop

parents f60c144c 24f540d0
......@@ -16,25 +16,14 @@
=========================================================================*/
#include "otbWrapperApplicationFactory.h"
#include "otbWrapperCompositeApplication.h"
#include "otbMultiToMonoChannelExtractROI.h"
#include "otbGenericRSResampleImageFilter.h"
#include "otbGridResampleImageFilter.h"
#include "otbImportGeoInformationImageFilter.h"
#include "otbBCOInterpolateImageFunction.h"
#include "otbSimpleRcsPanSharpeningFusionImageFilter.h"
#include "itkFixedArray.h"
// Elevation handler
#include "otbWrapperElevationParametersHandler.h"
#include "otbPleiadesPToXSAffineTransformCalculator.h"
namespace otb
{
namespace Wrapper
{
class BundleToPerfectSensor : public Application
class BundleToPerfectSensor : public CompositeApplication
{
public:
/** Standard class typedefs. */
......@@ -46,7 +35,7 @@ public:
/** Standard macro */
itkNewMacro(Self);
itkTypeMacro(BundleToPerfectSensor, otb::Application);
itkTypeMacro(BundleToPerfectSensor, otb::Wrapper::CompositeApplication);
private:
......@@ -65,38 +54,27 @@ private:
AddDocTag(Tags::Geometry);
AddDocTag(Tags::Pansharpening);
AddParameter(ParameterType_InputImage, "inp", "Input PAN Image");
SetParameterDescription("inp"," Input panchromatic image.");
AddParameter(ParameterType_InputImage, "inxs", "Input XS Image");
SetParameterDescription("inxs"," Input XS image.");
AddParameter(ParameterType_OutputImage, "out", "Output image");
SetParameterDescription("out"," Output image.");
// Elevation
ElevationParametersHandler::AddElevationParameters(this, "elev");
// Superposition mode
AddParameter(ParameterType_Choice,"mode", "Mode");
SetParameterDescription("mode", "Superimposition mode");
AddChoice("mode.default", "Default mode");
SetParameterDescription("mode.default", "Default superimposition mode : "
"uses any projection reference or sensor model found in the images");
AddChoice("mode.phr", "Pleiades mode");
SetParameterDescription("mode.phr", "Pleiades superimposition mode, "
"designed for the case of a P+XS bundle in SENSOR geometry. It uses"
" a simple transform on the XS image : a scaling and a residual "
"translation.");
ClearApplications();
AddApplication("Superimpose", "superimpose", "Reproject XS onto Pan");
AddApplication("Pansharpening", "pansharp", "Fusion of XS and Pan");
ShareParameter("inp","superimpose.inr","Input PAN Image","Input panchromatic image.");
ShareParameter("inxs","superimpose.inm","Input XS Image","Input XS image.");
ShareParameter("out","pansharp.out");
ShareParameter("elev","superimpose.elev");
ShareParameter("mode","superimpose.mode");
ShareParameter("lms","superimpose.lms",
"Spacing of the deformation field",
"Spacing of the deformation field. Default is 10 times the PAN image spacing.");
ShareParameter("fv","superimpose.fv");
ShareParameter("ram","superimpose.ram");
Connect("pansharp.inp","superimpose.inr");
Connect("pansharp.ram","superimpose.ram");
GetInternalApplication("superimpose")->SetParameterString("interpolator","bco");
GetInternalApplication("pansharp")->SetParameterString("method","rcs");
AddParameter(ParameterType_Float, "lms", "Spacing of the deformation field");
SetParameterDescription("lms"," Spacing of the deformation field. Default is 10 times the PAN image spacing.");
AddRAMParameter();
MandatoryOff("lms");
// Doc example parameter settings
SetDocExampleParameterValue("inp", "QB_Toulouse_Ortho_PAN.tif");
SetDocExampleParameterValue("inxs", "QB_Toulouse_Ortho_XS.tif");
......@@ -106,150 +84,19 @@ private:
void DoUpdateParameters() ITK_OVERRIDE
{
if(!HasUserValue("mode") && HasValue("inp") && HasValue("inxs") && otb::PleiadesPToXSAffineTransformCalculator::CanCompute(GetParameterImage("inp"),GetParameterImage("inxs")))
{
otbAppLogWARNING("Forcing PHR mode with PHR data. You need to add \"-mode default\" to force the default mode with PHR images.");
SetParameterString("mode","phr");
}
UpdateInternalParameters("superimpose");
}
void DoExecute() ITK_OVERRIDE
{
FloatVectorImageType* panchroV = GetParameterImage("inp");
FloatVectorImageType* xs = GetParameterImage("inxs");
if ( panchroV->GetNumberOfComponentsPerPixel() != 1 )
{
itkExceptionMacro(<< "The panchromatic image must be a single channel image")
}
// Transform the PAN image to otb::Image
typedef otb::Image<FloatVectorImageType::InternalPixelType> InternalImageType;
typedef otb::MultiToMonoChannelExtractROI<float,float> ExtractFilterType;
ExtractFilterType::Pointer channelSelect = ExtractFilterType::New();
m_Ref.push_back(channelSelect.GetPointer());
channelSelect->SetChannel(1);
channelSelect->SetInput(panchroV);
channelSelect->UpdateOutputInformation();
InternalImageType::Pointer panchro = channelSelect->GetOutput();
typedef otb::BCOInterpolateImageFunction<FloatVectorImageType> InterpolatorType;
typedef otb::GenericRSResampleImageFilter<FloatVectorImageType, FloatVectorImageType> ResamplerType;
typedef otb::GridResampleImageFilter<FloatVectorImageType, FloatVectorImageType> BasicResamplerType;
typedef otb::ImportGeoInformationImageFilter<FloatVectorImageType,InternalImageType> ImportGeoInformationFilterType;
typedef otb::SimpleRcsPanSharpeningFusionImageFilter<InternalImageType, FloatVectorImageType, FloatVectorImageType> FusionFilterType;
ExecuteInternal("superimpose");
// Resample filter
ResamplerType::Pointer resampler = ResamplerType::New();
m_Ref.push_back(resampler.GetPointer());
BasicResamplerType::Pointer basicResampler = BasicResamplerType::New();
m_Ref.push_back(basicResampler.GetPointer());
ImportGeoInformationFilterType::Pointer geoImport = ImportGeoInformationFilterType::New();
m_Ref.push_back(geoImport.GetPointer());
InterpolatorType::Pointer interpolator = InterpolatorType::New();
resampler->SetInterpolator(interpolator);
basicResampler->SetInterpolator(interpolator);
// Fusion filter
FusionFilterType::Pointer fusionFilter = FusionFilterType::New();
m_Ref.push_back(fusionFilter.GetPointer());
fusionFilter->SetPanInput(panchro);
// Setup the DEM Handler
otb::Wrapper::ElevationParametersHandler::SetupDEMHandlerFromElevationParameters(this,"elev");
// Set up output image information
FloatVectorImageType::SpacingType spacing = panchro->GetSpacing();
FloatVectorImageType::IndexType start = panchro->GetLargestPossibleRegion().GetIndex();
FloatVectorImageType::SizeType size = panchro->GetLargestPossibleRegion().GetSize();
FloatVectorImageType::PointType origin = panchro->GetOrigin();
FloatVectorImageType::PixelType defaultValue;
itk::NumericTraits<FloatVectorImageType::PixelType>::SetLength(defaultValue, xs->GetNumberOfComponentsPerPixel());
GetInternalApplication("pansharp")->SetParameterInputImage("inxs",
GetInternalApplication("superimpose")->GetParameterOutputImage("out"));
if(GetParameterString("mode") == "default")
{
otbAppLogINFO("Using the default mode");
if(IsParameterEnabled("lms") && HasValue("lms"))
{
double defScalarSpacing = GetParameterFloat("lms");
otbAppLogINFO(<< "Generating coarse deformation field (spacing="<<defScalarSpacing<<")" << std::endl);
FloatVectorImageType::SpacingType defSpacing;
defSpacing[0] = defScalarSpacing;
defSpacing[1] = defScalarSpacing;
resampler->SetDisplacementFieldSpacing(defSpacing);
}
else
{
FloatVectorImageType::SpacingType defSpacing;
defSpacing[0]=10*spacing[0];
defSpacing[1]=10*spacing[1];
resampler->SetDisplacementFieldSpacing(defSpacing);
}
resampler->SetInput(xs);
resampler->SetOutputOrigin(origin);
resampler->SetOutputSpacing(spacing);
resampler->SetOutputSize(size);
resampler->SetOutputStartIndex(start);
resampler->SetOutputKeywordList(panchro->GetImageKeywordlist());
resampler->SetOutputProjectionRef(panchro->GetProjectionRef());
resampler->SetEdgePaddingValue(defaultValue);
fusionFilter->SetXsInput(resampler->GetOutput());
}
else if(GetParameterString("mode")=="phr")
{
otbAppLogINFO("Using the PHR mode");
otb::PleiadesPToXSAffineTransformCalculator::TransformType::OffsetType offset
= otb::PleiadesPToXSAffineTransformCalculator::ComputeOffset(GetParameterImage("inp"),
GetParameterImage("inxs"));
origin+=offset;
origin[0]=origin[0]/4;
origin[1]=origin[1]/4;
basicResampler->SetOutputOrigin(origin);
basicResampler->SetInput(xs);
basicResampler->SetOutputOrigin(origin);
FloatVectorImageType::SpacingType xsSpacing = GetParameterImage("inxs")->GetSpacing();
xsSpacing*=0.25;
basicResampler->SetOutputSpacing(xsSpacing);
basicResampler->SetOutputSize(size);
basicResampler->SetOutputStartIndex(start);
basicResampler->SetEdgePaddingValue(defaultValue);
geoImport->SetInput(basicResampler->GetOutput());
geoImport->SetSource(panchro);
fusionFilter->SetXsInput(geoImport->GetOutput());
// Set the profRef & Keywordlist from Pan into the resampled XS image
basicResampler->UpdateOutputInformation();
itk::MetaDataDictionary& dict = basicResampler->GetOutput()->GetMetaDataDictionary();
itk::EncapsulateMetaData<std::string>(dict, MetaDataKey::ProjectionRefKey,
panchro->GetProjectionRef());
itk::EncapsulateMetaData<ImageKeywordlist>(dict, MetaDataKey::OSSIMKeywordlistKey,
panchro->GetImageKeywordlist());
}
else
{
otbAppLogWARNING("Unknown mode");
}
SetParameterOutputImage("out", fusionFilter->GetOutput());
ExecuteInternal("pansharp");
}
std::vector<itk::ProcessObject::Pointer> m_Ref;
};
......
......@@ -10,6 +10,7 @@ otb_module(OTBAppFusion
OTBInterpolation
TEST_DEPENDS
OTBAppProjection
OTBTestKernel
OTBCommandLine
......
......@@ -104,6 +104,7 @@ private:
AddParameter(ParameterType_Float, "lms", "Spacing of the deformation field");
SetParameterDescription("lms","Generate a coarser deformation field with the given spacing");
SetDefaultParameterFloat("lms", 4.);
DisableParameter("lms");
MandatoryOff("lms");
AddParameter(ParameterType_Float, "fv", "Fill Value");
......@@ -219,20 +220,24 @@ private:
if(GetParameterString("mode")=="default")
{
FloatVectorImageType::SpacingType defSpacing;
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);
}
else
{
defSpacing[0]=10*spacing[0];
defSpacing[1]=10*spacing[1];
}
m_Resampler->SetDisplacementFieldSpacing(defSpacing);
// Setup transform through projRef and Keywordlist
m_Resampler->SetInputKeywordList(movingImage->GetImageKeywordlist());
......
......@@ -320,6 +320,7 @@ otb_test_application(NAME apTvPrSuperimpose
-inm ${INPUTDATA}/QB_Toulouse_Ortho_XS_ROI_170x230.tif
-elev.dem ${INPUTDATA}/DEM/srtm_directory
-out ${TEMP}/apTvPrSuperimpose.tif int16
-lms 4.0
VALID --compare-image ${EPSILON_7}
${BASELINE}/apTvPrSuperimpose.tif
${TEMP}/apTvPrSuperimpose.tif)
......
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