Commit 6fc71709 authored by remi cresson's avatar remi cresson

ADD: new app to compute images stack density

parent a5aded1b
cmake_minimum_required (VERSION 2.8)
OTB_CREATE_APPLICATION(NAME TimeSeriesStats
SOURCES otbTimeSeriesStats.cxx
LINK_LIBRARIES OTBCommon)
\ No newline at end of file
/*=========================================================================
Copyright (c) Remi Cresson (IRSTEA). All rights reserved.
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.
=========================================================================*/
#include "itkFixedArray.h"
#include "itkObjectFactory.h"
#include "otbWrapperApplicationFactory.h"
// Application engine
#include "otbStandardFilterWatcher.h"
#include "itkFixedArray.h"
// LayerStack
#include "otbImageListToVectorImageFilter.h"
#include "otbMultiToMonoChannelExtractROI.h"
#include "otbImageList.h"
// Extract multichannel
#include "otbMultiChannelExtractROI.h"
// Input images list
#include "otbWrapperInputImageListParameter.h"
// Functors for NDVI operations
#include "otbUnaryFunctorImageFilter.h"
#include "otbTimeSeriesFunctor.h"
// Dates
#include "otbDates.h"
namespace otb
{
namespace Wrapper
{
class TimeSeriesStats : public Application
{
public:
/** Standard class typedefs. */
typedef TimeSeriesStats Self;
typedef Application Superclass;
typedef itk::SmartPointer<Self> Pointer;
typedef itk::SmartPointer<const Self> ConstPointer;
/** Standard macro */
itkNewMacro(Self);
itkTypeMacro(TimeSeriesStats, Application);
/** Typedefs for image concatenation */
typedef otb::ImageList<FloatImageType> ImageListType;
typedef ImageListToVectorImageFilter<ImageListType, FloatVectorImageType> ListConcatenerFilterType;
typedef MultiToMonoChannelExtractROI<FloatVectorImageType::InternalPixelType,
FloatImageType::PixelType> ExtractROIFilterType;
typedef ObjectList<ExtractROIFilterType> ExtractROIFilterListType;
/** Typedefs for temporal correlation */
typedef unsigned char LabelValueType;
typedef otb::VectorImage<LabelValueType> LabelVectorImageType;
typedef otb::dates::SingleDate DateType;
typedef otb::Functor::MultitemporalDensityFunctor<FloatVectorImageType::PixelType,
LabelVectorImageType::PixelType> DensityFunctorType;
typedef otb::UnaryFunctorImageFilter<FloatVectorImageType,
LabelVectorImageType, DensityFunctorType> DensityFilterType;
void DoUpdateParameters()
{
// Nothing to do here : all parameters are independent
}
void DoInit()
{
// Documentation
SetName("TimeSeriesStats");
SetDocName("TimeSeriesStats");
SetDescription("Compute time series statistics");
SetDocLongDescription("This application computes time series statistics.");
SetDocLimitations("None");
SetDocAuthors("Remi Cresson");
// Input time series images
AddParameter(ParameterType_InputImageList, "il", "Input time series");
SetParameterDescription ("il", "The user can specify multiple input images, or one big stack of images.");
// Input nodata
AddParameter(ParameterType_Float, "nodata", "Input no-data value");
MandatoryOff ("nodata");
SetDefaultParameterFloat ("nodata", 0.0);
// Output image
AddParameter(ParameterType_OutputImage, "out", "Output label image");
SetParameterDescription ("out", "Output label image");
SetDefaultOutputPixelType ("out", ImagePixelType_uint8);
AddRAMParameter();
}
/*
* Execute the process
*/
void DoExecute()
{
// Get the input image list
FloatVectorImageListType::Pointer inList = this->GetParameterImageList("il");
if( inList->Size() < 2 )
{
otbAppLogFATAL("At least two images are required.");
}
if ( inList->Size() >= itk::NumericTraits<LabelValueType>::max())
{
otbAppLogFATAL("The maximum number of input images must be below " <<
itk::NumericTraits<LabelValueType>::max() << ". Consider changing LabelValueType.");
}
// Create one stack for input NDVI images list
m_Concatener = ListConcatenerFilterType::New();
m_ImageList = ImageListType::New();
m_ExtractorList = ExtractROIFilterListType::New();
// Split each input vector image into image
// and generate an mono channel image list
inList->GetNthElement(0)->UpdateOutputInformation();
FloatVectorImageType::SizeType size = inList->GetNthElement(0)->GetLargestPossibleRegion().GetSize();
for( unsigned int i=0; i<inList->Size(); i++ )
{
FloatVectorImageType::Pointer vectIm = inList->GetNthElement(i);
vectIm->UpdateOutputInformation();
if( size != vectIm->GetLargestPossibleRegion().GetSize() )
{
itkExceptionMacro("Input Image size mismatch...");
}
for( unsigned int j=0; j<vectIm->GetNumberOfComponentsPerPixel(); j++)
{
ExtractROIFilterType::Pointer extractor = ExtractROIFilterType::New();
extractor->SetInput( vectIm );
extractor->SetChannel( j+1 );
extractor->UpdateOutputInformation();
m_ExtractorList->PushBack( extractor );
m_ImageList->PushBack( extractor->GetOutput() );
}
}
// Concatenate the images
m_Concatener->SetInput( m_ImageList );
m_Concatener->UpdateOutputInformation();
// Count images
m_TemporalFilter = DensityFilterType::New();
m_TemporalFilter->SetInput(m_Concatener->GetOutput());
m_TemporalFilter->GetFunctor().SetInputNoDataValue(GetParameterFloat("nodata"));
SetParameterOutputImage("out", m_TemporalFilter->GetOutput());
} // DoExecute()
ListConcatenerFilterType::Pointer m_Concatener;
ExtractROIFilterListType::Pointer m_ExtractorList;
ImageListType::Pointer m_ImageList;
DensityFilterType::Pointer m_TemporalFilter;
}; // end of class
} // namespace wrapper
} // namespace otb
OTB_APPLICATION_EXPORT( otb::Wrapper::TimeSeriesStats )
/*=========================================================================
Copyright (c) Remi Cresson (IRSTEA). All rights reserved.
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.
=========================================================================*/
namespace otb
{
namespace Functor
{
/** \class MultitemporalDensityFunctor
* \brief This functor computes the number of images in the input stack
*
* \ingroup Functor
*/
template <class TInputPixel, class TOutputLabel>
class MultitemporalDensityFunctor
{
typedef typename TInputPixel::ValueType InputValueType;
typedef typename TOutputLabel::ValueType OutputLabelValueType;
public:
/** Return the index name */
virtual std::string GetName() const
{
return "Number of images in the stack";
}
unsigned int GetOutputSize(){
return outputPixelSize;
}
// Constructor
MultitemporalDensityFunctor() {
/*
* Pixel components:
* 1: number of images
*/
outputPixelSize = 1;
// input no-data value
m_InputNoDataValue = 0;
}
// Destructor
virtual ~MultitemporalDensityFunctor(){}
// No data set/get
void SetInputNoDataValue(InputValueType value) { m_InputNoDataValue = value; }
InputValueType GetInputNoDataValue() { return m_InputNoDataValue; }
/*
* Compute the output pixel
*/
inline TOutputLabel operator()(const TInputPixel & pixel) const
{
// Output pixel
TOutputLabel outLabel;
outLabel.SetSize(outputPixelSize);
outLabel.Fill(itk::NumericTraits<OutputLabelValueType>::Zero);
int n = pixel.GetSize();
// Comput nb. of valid pixels
for (int i = 0 ; i < n; i++)
{
if (pixel[i] != m_InputNoDataValue)
outLabel[0]++;
}
return outLabel;
}
private:
// no data values
InputValueType m_InputNoDataValue;
int outputPixelSize;
}; // MultitemporalDensityFunctor
}
}
......@@ -4,6 +4,7 @@ otb_module(TimeSeriesUtils
DEPENDS
OTBIndices
OTBStatistics
OTBApplicationEngine
TEST_DEPENDS
OTBTestKernel
......
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