Skip to content
Snippets Groups Projects
Commit 3dc5c2a1 authored by Julien Michel's avatar Julien Michel
Browse files

ENH: Adding a new filter to change the no data value of the image (replaces...

ENH: Adding a new filter to change the no data value of the image (replaces the no data metadata, and all occurences in pixel values
parent 407cd39e
No related branches found
No related tags found
No related merge requests found
......@@ -19,13 +19,13 @@
#include "otbWrapperApplicationFactory.h"
#include "otbImageToNoDataMaskFilter.h"
#include "otbChangeNoDataValueFilter.h"
namespace otb
{
namespace Wrapper
{
class NoDataMask : public Application
{
public:
......@@ -42,7 +42,8 @@ public:
/** Filters typedef */
typedef otb::ImageToNoDataMaskFilter<FloatVectorImageType,UInt8ImageType> FilterType;
typedef otb::ChangeNoDataValueFilter<FloatVectorImageType,FloatVectorImageType> ChangeNoDataFilterType;
private:
void DoInit()
{
......@@ -64,21 +65,35 @@ private:
AddParameter(ParameterType_OutputImage, "out", "Output Image");
SetParameterDescription("out", "Output image");
AddParameter(ParameterType_Int,"inv","Inside Value");
SetParameterDescription("inv","Value given in the output mask to pixels that are not no data pixels");
SetDefaultParameterInt("inv",1);
AddParameter(ParameterType_Int,"outv","Outside Value");
SetParameterDescription("outv","Value given in the output mask to pixels that are no data pixels");
SetDefaultParameterInt("outv",0);
AddParameter(ParameterType_Choice,"mode","No-data handling mode");
SetParameterDescription("mode","Allows to choose between different no-data handling options");
AddChoice("mode.buildmask","Build a no-data Mask");
AddParameter(ParameterType_Float,"mode.buildmask.inv","Inside Value");
SetParameterDescription("mode.buildmask.inv","Value given in the output mask to pixels that are not no data pixels");
SetDefaultParameterInt("mode.buildmask.inv",1);
AddParameter(ParameterType_Float,"mode.buildmask.outv","Outside Value");
SetParameterDescription("mode.buildmask.outv","Value given in the output mask to pixels that are no data pixels");
SetDefaultParameterInt("mode.buildmask.outv",0);
AddChoice("mode.changevalue","Change the no-data value");
AddParameter(ParameterType_Float,"mode.changevalue.newv","The new no-data value");
SetParameterDescription("mode.changevalue.newv","The new no-data value");
SetDefaultParameterInt("mode.changevalue.newv",0);
SetParameterString("mode","buildmask");
AddRAMParameter();
// Doc example parameter settings
SetDocExampleParameterValue("in", "QB_Toulouse_Ortho_XS.tif");
SetDocExampleParameterValue("out", "QB_Toulouse_Ortho_XS_nodatamask.tif uint8");
SetDocExampleParameterValue("inv", "255");
SetDocExampleParameterValue("outv", "0");
SetDocExampleParameterValue("mode.buildmask.inv", "255");
SetDocExampleParameterValue("mode.buildmask.outv", "0");
}
void DoUpdateParameters()
......@@ -89,15 +104,33 @@ private:
void DoExecute()
{
FloatVectorImageType::Pointer inputPtr = this->GetParameterImage("in");
m_Filter = FilterType::New();
m_Filter->SetInsideValue(this->GetParameterInt("inv"));
m_Filter->SetOutsideValue(this->GetParameterInt("outv"));
m_Filter->SetInput(this->GetParameterImage("in"));
SetParameterOutputImage("out",m_Filter->GetOutput());
m_Filter->SetInsideValue(this->GetParameterFloat("mode.buildmask.inv"));
m_Filter->SetOutsideValue(this->GetParameterFloat("mode.buildmask.outv"));
m_Filter->SetInput(inputPtr);
m_ChangeNoDataFilter = ChangeNoDataFilterType::New();
m_ChangeNoDataFilter->SetInput(inputPtr);
std::vector<double> newNoData(inputPtr->GetNumberOfComponentsPerPixel(),GetParameterFloat("mode.changevalue.newv"));
m_ChangeNoDataFilter->SetNewNoDataValues(newNoData);
if(GetParameterString("mode") == "buildmask")
{
SetParameterOutputImage("out",m_Filter->GetOutput());
}
else if(GetParameterString("mode") == "changevalue")
{
SetParameterOutputImage("out",m_ChangeNoDataFilter->GetOutput());
}
}
FilterType::Pointer m_Filter;
ChangeNoDataFilterType::Pointer m_ChangeNoDataFilter;
};
}
......
......@@ -51,6 +51,36 @@ std::vector<bool> & flags, const std::vector<double> & values) {
return false;
}
}
/**
*/
template<typename T> T ChangeNoData(const T & pixel, const
std::vector<bool> & flags,
const std::vector<double> & values,
const std::vector<double> & newValues) {
assert(flags.size()>0);
assert(values.size()>0);
assert(newValues.size()>0);
if(vnl_math_isnan(pixel))
{
return static_cast<T>(newValues[0]);
}
if(flags[0])
{
if (pixel == values[0])
{
return static_cast<T>(newValues[0]);
}
}
else
{
return pixel;
}
}
/**
* Specialization of IsNoData function to handle itk::VariableLengthVector
*/
......@@ -69,6 +99,34 @@ template <typename T> bool IsNoData(const itk::VariableLengthVector<T> & pixel,
return false;
}
template <typename T> itk::VariableLengthVector<T> ChangeNoData(const itk::VariableLengthVector<T> & pixel,
const std::vector<bool> & flags,
const std::vector<double> & values,
const std::vector<double> & newValues)
{
assert(flags.size()>=pixel.Size());
assert(values.size()>=pixel.Size());
assert(newValues.size()>=pixel.Size());
itk::VariableLengthVector<T> outPixel(pixel.Size());
for(unsigned int i = 0; i < pixel.Size();++i)
{
if(vnl_math_isnan(pixel[i]) || (flags[i] && (pixel[i] == values[i])))
{
outPixel[i] = newValues[i];
}
else
{
outPixel[i] = pixel[i];
}
}
return outPixel;
}
} // End namespace otb
......
/*=========================================================================
Program: ORFEO Toolbox
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
See OTBCopyright.txt for details.
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.
=========================================================================*/
#ifndef __otbChangeNoDataValueFilter_h
#define __otbChangeNoDataValueFilter_h
#include "itkUnaryFunctorImageFilter.h"
#include "itkMetaDataObject.h"
#include "otbMetaDataKey.h"
#include "otbNoDataHelper.h"
namespace otb
{
namespace Functor
{
template <typename TInputPixel, typename TOutputPixel>
class ChangeNoDataFunctor
{
public:
ChangeNoDataFunctor():
m_Flags(),
m_Values(),
m_NewValues()
{}
virtual ~ChangeNoDataFunctor(){}
inline TOutputPixel operator()(const TInputPixel& in) const
{
return otb::ChangeNoData(in,m_Flags,m_Values,m_NewValues);
}
std::vector<bool> m_Flags;
std::vector<double> m_Values;
std::vector<double> m_NewValues;
};
} // End namespace Functor
template <typename TInputImage, typename TOutputImage>
class ChangeNoDataValueFilter
: public itk::UnaryFunctorImageFilter<TInputImage,
TOutputImage,
Functor::ChangeNoDataFunctor<typename TInputImage::PixelType,
typename TOutputImage::PixelType> >
{
public:
typedef Functor::ChangeNoDataFunctor<typename TInputImage::PixelType,typename TOutputImage::PixelType> FunctorType;
typedef ChangeNoDataValueFilter Self;
typedef itk::UnaryFunctorImageFilter<TInputImage,
TOutputImage,
FunctorType> Superclass;
typedef itk::SmartPointer<Self> Pointer;
typedef itk::SmartPointer<const Self> ConstPointer;
/** Type macro */
itkNewMacro(Self);
/** Creation through object factory macro */
itkTypeMacro(ChangeNoDataValueFilter, itk::ImageToImageFilter);
void SetNewNoDataValues(std::vector<double> & newValues)
{
this->GetFunctor().m_NewValues = newValues;
}
protected:
ChangeNoDataValueFilter()
{}
virtual ~ChangeNoDataValueFilter()
{}
virtual void BeforeThreadedGenerateData()
{
std::vector<bool> noDataValueAvailable;
bool ret = itk::ExposeMetaData<std::vector<bool> >(this->GetInput()->GetMetaDataDictionary(),MetaDataKey::NoDataValueAvailable,noDataValueAvailable);
if(!ret)
{
noDataValueAvailable.resize(this->GetInput()->GetNumberOfComponentsPerPixel(),false);
}
this->GetFunctor().m_Flags = noDataValueAvailable;
std::vector<double> noDataValues;
ret = itk::ExposeMetaData<std::vector<double> >(this->GetInput()->GetMetaDataDictionary(),MetaDataKey::NoDataValue,noDataValues);
if(!ret)
{
noDataValues.resize(this->GetInput()->GetNumberOfComponentsPerPixel(),0);
}
this->GetFunctor().m_Values = noDataValues;
}
virtual void GenerateOutputInformation()
{
Superclass::GenerateOutputInformation();
std::vector<bool> newAvail(this->GetFunctor().m_NewValues.size(),true);
itk::EncapsulateMetaData<std::vector<bool> >(this->GetOutput()->GetMetaDataDictionary(),MetaDataKey::NoDataValueAvailable,newAvail);
itk::EncapsulateMetaData<std::vector<double> >(this->GetOutput()->GetMetaDataDictionary(),MetaDataKey::NoDataValue,this->GetFunctor().m_NewValues);
}
private:
ChangeNoDataValueFilter(const Self&); // purposely not implemented
void operator =(const Self&); // purposely not implemented
};
} // End namespace otb
#endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment