Newer
Older
Cédric Traizet
committed
/*=========================================================================
Program: ORFEO Toolbox
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
See OTBCopyright.txt for details.
Cédric Traizet
committed
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.
Cédric Traizet
committed
=========================================================================*/
#include "otbWrapperApplication.h"
#include "otbWrapperApplicationFactory.h"
Cédric Traizet
committed
#include "itkUnaryFunctorImageFilter.h"
#include "otbChangeLabelImageFilter.h"
#include "otbStandardWriterWatcher.h"
#include "otbStatisticsXMLFileReader.h"
#include "otbShiftScaleVectorImageFilter.h"
Cédric Traizet
committed
#include "otbMultiToMonoChannelExtractROI.h"
#include "otbImageToVectorImageCastFilter.h"
Cédric Traizet
committed
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
namespace Functor
{
/**
* simple affine function : y = ax+b
*/
template<class TInput, class TOutput>
class AffineFunctor
{
public:
typedef double InternalType;
// constructor
AffineFunctor() : m_A(1.0),m_B(0.0) {}
// destructor
virtual ~AffineFunctor() {}
void SetA(InternalType a)
{
m_A = a;
}
void SetB(InternalType b)
{
m_B = b;
}
inline TOutput operator()(const TInput & x) const
{
return static_cast<TOutput>( static_cast<InternalType>(x)*m_A + m_B);
}
private:
InternalType m_A;
InternalType m_B;
};
}
Cédric Traizet
committed
Cédric Traizet
committed
class CbDimensionalityReduction : public Application
Cédric Traizet
committed
{
public:
Cédric Traizet
committed
/** Standard class typedefs. */
typedef CbDimensionalityReduction Self;
typedef Application Superclass;
typedef itk::SmartPointer<Self> Pointer;
typedef itk::SmartPointer<const Self> ConstPointer;
/** Standard macro */
itkNewMacro(Self);
itkTypeMacro(CbDimensionalityReduction, otb::Application);
/** Filters typedef */
typedef UInt8ImageType MaskImageType;
typedef itk::VariableLengthVector<FloatVectorImageType::InternalPixelType> MeasurementType;
typedef otb::StatisticsXMLFileReader<MeasurementType> StatisticsReader;
typedef otb::ShiftScaleVectorImageFilter<FloatVectorImageType, FloatVectorImageType> RescalerType;
typedef itk::UnaryFunctorImageFilter<
FloatImageType,
FloatImageType,
otb::Functor::AffineFunctor<float,float> > OutputRescalerType;
typedef otb::ImageDimensionalityReductionFilter<FloatVectorImageType, FloatVectorImageType, MaskImageType> DimensionalityReductionFilterType;
typedef DimensionalityReductionFilterType::Pointer DimensionalityReductionFilterPointerType;
typedef DimensionalityReductionFilterType::ModelType ModelType;
Cédric Traizet
committed
typedef ModelType::Pointer ModelPointerType;
typedef DimensionalityReductionFilterType::ValueType ValueType;
typedef DimensionalityReductionFilterType::LabelType LabelType;
typedef otb::DimensionalityReductionModelFactory<ValueType, LabelType> DimensionalityReductionModelFactoryType;
Cédric Traizet
committed
protected:
~CbDimensionalityReduction() ITK_OVERRIDE
{
DimensionalityReductionModelFactoryType::CleanFactories();
Cédric Traizet
committed
}
Cédric Traizet
committed
private:
Cédric Traizet
committed
void DoInit() ITK_OVERRIDE
{
SetName("DimensionalityReduction");
SetDescription("Performs dimensionality reduction of the input image according to a dimensionality reduction model file.");
Cédric Traizet
committed
// Documentation
SetDocName("DimensionalityReduction");
SetDocLongDescription("This application reduces the dimension of an input"
" image, based on a dimensionality reduction model file produced by"
" the DimensionalityReductionTrainer application. Pixels of the "
"output image will contain the reduced values from"
"the model. The input pixels"
Cédric Traizet
committed
" can be optionally centered and reduced according "
"to the statistics file produced by the "
Cédric Traizet
committed
SetDocLimitations("The input image must contain the feature bands used for"
Cédric Traizet
committed
"If a statistics file was used during training by the "
"TrainRegression, it is mandatory to use the same "
Cédric Traizet
committed
SetDocAuthors("OTB-Team");
SetDocSeeAlso("DimensionalityReductionTrainer, ComputeImagesStatistics");
Cédric Traizet
committed
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
AddDocTag(Tags::Learning);
AddParameter(ParameterType_InputImage, "in", "Input Image");
SetParameterDescription( "in", "The input image to predict.");
AddParameter(ParameterType_InputImage, "mask", "Input Mask");
SetParameterDescription( "mask", "The mask allow restricting "
"classification of the input image to the area where mask pixel values "
"are greater than 0.");
MandatoryOff("mask");
AddParameter(ParameterType_InputFilename, "model", "Model file");
SetParameterDescription("model", "A regression model file (produced by "
"TrainRegression application).");
AddParameter(ParameterType_InputFilename, "imstat", "Statistics file");
SetParameterDescription("imstat", "A XML file containing mean and standard"
" deviation to center and reduce samples before prediction "
"(produced by ComputeImagesStatistics application). If this file contains"
"one more band than the sample size, the last stat of last band will be"
"applied to expand the output predicted value");
MandatoryOff("imstat");
AddParameter(ParameterType_OutputImage, "out", "Output Image");
SetParameterDescription( "out", "Output image containing predicted values");
AddRAMParameter();
// Doc example parameter settings
SetDocExampleParameterValue("in", "QB_1_ortho.tif");
SetDocExampleParameterValue("imstat", "EstimateImageStatisticsQB1.xml");
SetDocExampleParameterValue("model", "clsvmModelQB1.svm");
SetDocExampleParameterValue("out", "clLabeledImageQB1.tif");
}
void DoUpdateParameters() ITK_OVERRIDE
{
// Nothing to do here : all parameters are independent
}
void DoExecute() ITK_OVERRIDE
{
// Load input image
FloatVectorImageType::Pointer inImage = GetParameterImage("in");
inImage->UpdateOutputInformation();
unsigned int nbFeatures = inImage->GetNumberOfComponentsPerPixel();
Cédric Traizet
committed
otbAppLogINFO("Loading model");
m_Model = DimensionalityReductionModelFactoryType::CreateDimensionalityReductionModel(GetParameterString("model"),
DimensionalityReductionModelFactoryType::ReadMode);
Cédric Traizet
committed
Cédric Traizet
committed
if (m_Model.IsNull())
{
otbAppLogFATAL(<< "Error when loading model " << GetParameterString("model") << " : unsupported model type");
}
m_Model->Load(GetParameterString("model"));
otbAppLogINFO("Model loaded");
// Classify
m_ClassificationFilter = DimensionalityReductionFilterType::New();
Cédric Traizet
committed
m_ClassificationFilter->SetModel(m_Model);
FloatVectorImageType::Pointer outputImage = m_ClassificationFilter->GetOutput();
Cédric Traizet
committed
// Normalize input image if asked
if(IsParameterEnabled("imstat") )
{
otbAppLogINFO("Input image normalization activated.");
// Normalize input image (optional)
StatisticsReader::Pointer statisticsReader = StatisticsReader::New();
MeasurementType meanMeasurementVector;
MeasurementType stddevMeasurementVector;
m_Rescaler = RescalerType::New();
Cédric Traizet
committed
// Load input image statistics
statisticsReader->SetFileName(GetParameterString("imstat"));
meanMeasurementVector = statisticsReader->GetStatisticVectorByName("mean");
stddevMeasurementVector = statisticsReader->GetStatisticVectorByName("stddev");
otbAppLogINFO( "mean used: " << meanMeasurementVector );
otbAppLogINFO( "standard deviation used: " << stddevMeasurementVector );
Cédric Traizet
committed
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
{
otbAppLogFATAL("Wrong number of components in statistics file : "<<meanMeasurementVector.Size());
}
// Rescale vector image
m_Rescaler->SetScale(stddevMeasurementVector);
m_Rescaler->SetShift(meanMeasurementVector);
m_Rescaler->SetInput(inImage);
m_ClassificationFilter->SetInput(m_Rescaler->GetOutput());
}
else
{
otbAppLogINFO("Input image normalization deactivated.");
m_ClassificationFilter->SetInput(inImage);
}
if(IsParameterEnabled("mask"))
{
otbAppLogINFO("Using input mask");
// Load mask image and cast into LabeledImageType
MaskImageType::Pointer inMask = GetParameterUInt8Image("mask");
m_ClassificationFilter->SetInputMask(inMask);
}
SetParameterOutputImage<FloatVectorImageType>("out", outputImage);
Cédric Traizet
committed
}
DimensionalityReductionFilterType::Pointer m_ClassificationFilter;
Cédric Traizet
committed
ModelPointerType m_Model;
RescalerType::Pointer m_Rescaler;
OutputRescalerType::Pointer m_OutRescaler;
Cédric Traizet
committed
};
Cédric Traizet
committed
Cédric Traizet
committed
OTB_APPLICATION_EXPORT(otb::Wrapper::CbDimensionalityReduction)