Commit a748291a authored by Cédric Traizet's avatar Cédric Traizet

Merge branch 'functor_image_filter_neighborhood' into 'develop'

Refactor FunctorImageFilter with neighborhood

See merge request orfeotoolbox/otb!373
parents 355e02f6 6e97bf05
......@@ -47,9 +47,6 @@ public:
typedef DoubleVectorImageType VectorImageType;
typedef DoubleImageType ImageType;
/** Filter typedefs */
typedef otb::LocalRxDetectorFilter<VectorImageType, ImageType> LocalRxDetectorFilterType; //TODO remove this
private:
void DoInit() override
{
......@@ -108,30 +105,19 @@ private:
auto inputImage = GetParameterDoubleVectorImage("in");
inputImage->UpdateOutputInformation();
// The localRxDetectionFilter can be replaced by a functorImageFilter using the appropriate
// functor. However using functorImageFilter with neighborhood is buggy (see issue #1802). Still,
// the functor has been implemented and localRxDetectionFilter will be deprecated when the
// bug is corrected.
#if 1 // Using localRxDetectionFilter
auto localRxDetectionFilter = LocalRxDetectorFilterType::New();
localRxDetectionFilter->SetInput(inputImage);
Functor::LocalRxDetectionFunctor<double> detectorFunctor;
unsigned int externalRadius = GetParameterInt("er");
unsigned int internalRadius = GetParameterInt("ir");
localRxDetectionFilter->SetInternalRadius(internalRadius);
localRxDetectionFilter->SetExternalRadius(externalRadius);
#else // Using a functorImageFilter
Functor::LocalRxDetectionFunctor<double> detectorFunctor;
detectorFunctor.SetInternalRadius(GetParameterInt("ir"), GetParameterInt("ir"));
detectorFunctor.SetInternalRadius(internalRadius, internalRadius);
// Create a functorImageFilter with the localRx functor and the appropriate
// external radius.
auto localRxDetectionFilter = otb::NewFunctorFilter
(detectorFunctor ,{{GetParameterInt("er"),GetParameterInt("er")}});
(detectorFunctor ,{{externalRadius,externalRadius}});
localRxDetectionFilter->SetInputs(inputImage);
#endif
SetParameterOutputImage("out", localRxDetectionFilter->GetOutput());
RegisterPipeline();
......
......@@ -27,7 +27,6 @@ otb_module(OTBAppHyperspectral
OTBEndmembersExtraction
OTBUnmixing
OTBAnomalyDetection
OTBFunctor
TEST_DEPENDS
OTBTestKernel
OTBCommandLine
......
......@@ -29,6 +29,8 @@
#include "itkFixedArray.h"
#include "itkDefaultConvertPixelTraits.h"
#include <type_traits>
#include "itkConstNeighborhoodIterator.h"
#include "otbImage.h"
namespace otb
{
......@@ -42,12 +44,11 @@ namespace otb
*/
template <class T> struct IsNeighborhood : std::false_type {};
/// Partial specialisation for itk::Neighborhood<T>
template <class T> struct IsNeighborhood<itk::Neighborhood<T>> : std::true_type {};
/// Partial specialisation for const ConstNeighborhoodIterator<Image::T> &
template <class T> struct IsNeighborhood<const itk::ConstNeighborhoodIterator<Image<T>>&> : std::true_type {};
/// Partial specialisation for const itk::Neighborhood<T> &
template <class T> struct IsNeighborhood<const itk::Neighborhood<T>&> : std::true_type {};
/// Partial specialisation for const ConstNeighborhoodIterator<VectorImage::T> &
template <class T> struct IsNeighborhood<const itk::ConstNeighborhoodIterator<VectorImage<T>>&> : std::true_type {};
/**
* \struct IsSuitableType
......@@ -76,9 +77,9 @@ template <class T> struct IsSuitableType<itk::RGBAPixel<T>> : IsSuitableType<T>:
* \struct PixelTypeDeduction
* \brief Helper struct to derive PixelType from template parameter.
*
* T -> PixelType = T
* itk::Neighborhood<T> -> PixelType = T
* const itk::Neighborhood<T>& -> PixelType = T
* T -> PixelType = T
* const ConstNeighborhoodIterator<Image::T>& -> PixelType = T
* const ConstNeighborhoodIterator<VectorImage::T>& -> PixelType = itk::VariableLengthVector<T>
*/
template <class T> struct PixelTypeDeduction
{
......@@ -87,14 +88,22 @@ template <class T> struct PixelTypeDeduction
using PixelType = T;
};
/// Partial specialisation for itk::Neighborhood<T>
template <class T> struct PixelTypeDeduction<itk::Neighborhood<T>>
/// Partial specialisation for itk::ConstNeighborhoodIterator<Image<T>>
template <class T> struct PixelTypeDeduction<itk::ConstNeighborhoodIterator<Image<T>>>
{
static_assert(IsSuitableType<T>::value,
"T can not be used as a template parameter for Image or VectorImage classes.");
using PixelType = T;
};
/// Partial specialisation for itk::ConstNeighborhoodIterator<VectorImage<T>>
template <class T> struct PixelTypeDeduction<itk::ConstNeighborhoodIterator<VectorImage<T>>>
{
static_assert(IsSuitableType<T>::value,
"T can not be used as a template parameter for Image or VectorImage classes.");
using PixelType = itk::VariableLengthVector<T>;
};
/**
* \struct ImageTypeDeduction
* \brief Helper struct to derive ImageType from template parameter
......@@ -227,9 +236,9 @@ template <typename C, typename R, typename... T, typename TNameMap> struct Funct
*
* \tparam Functor can be any operator() (const or non-const) that matches the following:
* - Accepts any number of arguments of T,
* (const) itk::VariableLengthVector<T> (&),(const)
* itk::Neighborhood<T> (&), (const)
* itk::Neighborhood<itk::VariableLengthVector<T>> (&) with T a scalar type
* (const) itk::VariableLengthVector<T> (&),const
* itk::ConstNeighborhoodIterator<VectorImage<T>> &, (const)
* itk::ConstNeighborhoodIterator<Image<T>> & with T a scalar type
* - returns T or itk::VariableLengthVector<T>, with T a scalar type
* or returns void and has first parameter as output (i.e. T& or itk::VariableLengthVector<T>&)
*
......@@ -239,7 +248,7 @@ template <typename C, typename R, typename... T, typename TNameMap> struct Funct
*
* \param[in] the Functor to build the filter from
* \param[in] radius The size of neighborhood to use, if there is any
* itk::Neighborhood<T> in the operator() arguments.
* ConstNeighborhoodIterator<VectorImage<T>> in the operator() arguments.
* \return A ready to use OTB filter, which accepts n input image of
* type derived from the operator() arguments, and producing an image
* correpsonding to the operator() return type.
......@@ -256,9 +265,9 @@ template <typename Functor, typename TNameMap = void> auto NewFunctorFilter(Func
*
* \tparam TFunction can be any operator() (const or non-const) that matches the following:
* - Accepts any number of arguments of T,
* (const) itk::VariableLengthVector<T> (&),(const)
* itk::Neighborhood<T> (&), (const)
* itk::Neighborhood<itk::VariableLengthVector<T>> (&) with T a scalar type
* (const) itk::VariableLengthVector<T> (&),const
* itk::ConstNeighborhoodIterator<Image<T>> &, const
* itk::ConstNeighborhoodIterator<VectorImage<T>> & with T a scalar type
* - returns T or itk::VariableLengthVector<T>, with T a scalar type
* or returns void and has first parameter as output (i.e. T& or itk::VariableLengthVector<T>&)
*
......@@ -422,7 +431,7 @@ private:
* \param[in] numberOfOutputBands The number of output bands that
* this filter will return
* \param radius The size of neighborhood to use, if there is any
* itk::Neighborhood<T> in the operator() arguments.
* ConstNeighborhoodIterator in the operator() arguments.
* \return A ready to use OTB filter, which accepts n input image of
* type derived from the operator() arguments, and producing an image
* correpsonding to the operator() return type.
......
......@@ -138,7 +138,7 @@ template <typename T> struct GetProxy<itk::ConstNeighborhoodIterator<T> >
{
static decltype(auto) Get(const itk::ConstNeighborhoodIterator<T> & t)
{
return t.GetNeighborhood();
return t;
}
};
......
......@@ -22,7 +22,6 @@
#include "otbFunctorImageFilter.h"
#include "otbImage.h"
#include "otbVectorImage.h"
#include "itkNeighborhood.h"
#include "otbVariadicAddFunctor.h"
#include "otbVariadicConcatenateFunctor.h"
#include "otbVariadicNamedInputsImageFilter.h"
......@@ -45,13 +44,14 @@ template <typename T> struct TypesCheck
using RGBPixelType = itk::RGBPixel<ScalarType>;
using RGBAPixelType = itk::RGBAPixel<ScalarType>;
using VectorImageType = otb::VectorImage<ScalarType>;
using NeighborhoodType = itk::Neighborhood<ScalarType>;
using VectorNeighborhoodType = itk::Neighborhood<VectorType>;
using NeighborhoodType = itk::ConstNeighborhoodIterator<ImageType>;
using VectorNeighborhoodType = itk::ConstNeighborhoodIterator<VectorImageType>;
// Test IsNeighborhood struct
template <typename U> struct CheckIsNeighborhood
{
static constexpr bool value = !otb::IsNeighborhood<U>::value && otb::IsNeighborhood<itk::Neighborhood<U> >::value;
static constexpr bool value = !otb::IsNeighborhood<U>::value
&& otb::IsNeighborhood<const itk::ConstNeighborhoodIterator<Image<U>>& >::value;
};
static_assert(CheckIsNeighborhood<T>::value,"");
......@@ -64,7 +64,7 @@ template <typename T> struct TypesCheck
template<typename U> struct CheckPixelTypeDeduction
{
static constexpr bool value = std::is_same<typename PixelTypeDeduction<U>::PixelType,U>::value
&& std::is_same<typename PixelTypeDeduction<itk::Neighborhood<U>>::PixelType,U>::value;
&& std::is_same<typename PixelTypeDeduction<itk::ConstNeighborhoodIterator<Image<U>>>::PixelType,U>::value;
};
static_assert(CheckPixelTypeDeduction<T>::value,"");
......@@ -259,13 +259,15 @@ template<typename TOut, typename TIn> struct BandExtraction
// This Functor computes the mean in neighborhood
template<typename TOut, typename TIn> struct Mean
{
auto operator()(const itk::Neighborhood<TIn> & in) const
auto operator()(const itk::ConstNeighborhoodIterator<otb::Image<TIn>> & in) const
{
TOut out(0);
for(auto it = in.Begin(); it!=in.End();++it)
out+=static_cast<TOut>(*it);
for (auto idx = 0u; idx < in.Size(); idx++)
{
out+=static_cast<TOut>(in.GetPixel(idx));
}
out/=in.Size();
return out;
......@@ -277,16 +279,17 @@ template<typename TOut, typename TIn> struct Mean
// For each channel, returns the maximum value in neighborhood
template<typename T> struct MaxInEachChannel
{
auto operator()(const itk::Neighborhood<itk::VariableLengthVector<T>> & in) const
auto operator()(const itk::ConstNeighborhoodIterator<otb::VectorImage<T>> & in) const
{
auto out = in.GetCenterValue();
auto out = in.GetCenterPixel();
for(auto it = in.Begin(); it!=in.End(); ++it)
for (auto idx = 0u; idx < in.Size(); idx++)
{
auto pixel = in.GetPixel(idx);
for(auto band = 0u; band < out.Size();++band)
{
if((*it)[band]>out[band])
out[band] = (*it)[band];
if(pixel[band] < out[band])
out[band] = in.GetPixel(idx)[band];
}
}
return out;
......@@ -397,12 +400,11 @@ int otbFunctorImageFilter(int itkNotUsed(argc), char * itkNotUsed(argv) [])
// test FunctorImageFilter with a lambda that returns a
// VariableLengthVector
// Converts a neighborhood to a VariableLengthVector
auto Lambda2 = [](const itk::Neighborhood<double>& in) {
auto Lambda2 = [](const itk::ConstNeighborhoodIterator<otb::Image<double>>& in) {
itk::VariableLengthVector<double> out(in.Size());
std::size_t idx{0};
for (auto it = in.Begin(); it != in.End(); ++it, ++idx)
for (size_t idx = 0; idx < in.Size(); idx++)
{
out[idx] = *it;
out[idx] = in.GetPixel(idx);
}
return out;
};
......
......@@ -24,96 +24,14 @@
#include "itkImageToImageFilter.h"
#include "itkConstShapedNeighborhoodIterator.h"
#include "itkNeighborhoodAlgorithm.h"
#include "itkImageRegionIterator.h"
#include "itkListSample.h"
#include "itkCovarianceSampleFilter.h"
#include "itkProgressReporter.h"
#include "itkConstNeighborhoodIterator.h"
#include "otbVectorImage.h"
namespace otb
{
/** \class otbLocalRxDetectorFilter
* \brief Local-RX detector algorithm with multichannel VectorImage data as input
*
*
* \ingroup ImageFilters
*
* \ingroup OTBAnomalyDetection
*/
template <class TInputImage, class TOutputImage>
class ITK_EXPORT LocalRxDetectorFilter:
public itk::ImageToImageFilter<TInputImage, TOutputImage>
{
public:
/** Standard class typedefs. */
typedef LocalRxDetectorFilter Self;
typedef itk::ImageToImageFilter< TInputImage, TOutputImage > Superclass;
typedef itk::SmartPointer<Self> Pointer;
typedef itk::SmartPointer<const Self> ConstPointer;
/** Type macro */
itkNewMacro(Self);
/** Creation through object factory macro */
itkTypeMacro(LocalRxDetectorFilter, ImageToImageFilter);
/** typedef related to input and output images */
typedef TInputImage InputImageType;
typedef typename InputImageType::Pointer InputPointerType;
typedef typename InputImageType::ConstPointer InputConstPointerType;
typedef typename InputImageType::IndexType InputIndexType;
typedef typename InputImageType::SizeType InputSizeType;
typedef TOutputImage OutputImageType;
typedef typename OutputImageType::Pointer OutputPointerType;
typedef typename OutputImageType::IndexType OutputIndexType;
typedef typename OutputImageType::OffsetType OutputOffsetType;
typedef typename OutputImageType::SizeType OutputSizeType;
typedef typename OutputImageType::RegionType OutputImageRegionType;
/** typedef related to iterators */
typedef itk::ConstShapedNeighborhoodIterator<InputImageType> ConstShapedNeighborhoodIteratorType;
typedef itk::NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<InputImageType> VectorFaceCalculatorType;
typedef itk::NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<OutputImageType> FaceCalculatorType;
typedef itk::ImageRegionIterator<OutputImageType> ImageRegionIteratorType;
/** typedef related to statistics */
typedef typename InputImageType::PixelType VectorMeasurementType;
typedef itk::Statistics::ListSample<VectorMeasurementType> ListSampleType;
typedef itk::Statistics::CovarianceSampleFilter<ListSampleType> CovarianceCalculatorType;
typedef typename CovarianceCalculatorType::MeasurementVectorRealType MeasurementVectorRealType;
typedef typename CovarianceCalculatorType::MatrixType MatrixType;
/** Getter and Setter */
itkSetMacro(InternalRadius, int);
itkGetMacro(InternalRadius, int);
itkSetMacro(ExternalRadius, int);
itkGetMacro(ExternalRadius, int);
/** Main computation method */
void GenerateInputRequestedRegion() override;
// virtual void GenerateData();
void BeforeThreadedGenerateData() override;
void ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId) override;
protected:
LocalRxDetectorFilter();
~LocalRxDetectorFilter() override {}
void PrintSelf(std::ostream& os, itk::Indent indent) const override;
private:
LocalRxDetectorFilter(const Self&) = delete;
void operator=(const Self&) = delete;
int m_InternalRadius;
int m_ExternalRadius;
};
/** \class LocalRxDetectionFunctor
* \brief This functor computes a local Rx score on an input neighborhood. Pixel of the neighborhood
* inside the internal radius are not considered during the computation of local statistics.
......@@ -163,14 +81,14 @@ public:
return m_InternalRadiusY;
};
auto operator()(const itk::Neighborhood<itk::VariableLengthVector<TInput>> & in) const
auto operator()(const itk::ConstNeighborhoodIterator<otb::VectorImage<TInput>> & in) const
{
// Create a list sample with the pixels of the neighborhood located between
// the two radius.
typename ListSampleType::Pointer listSample = ListSampleType::New();
// The pixel on whih we will compute the Rx score, we load it now to get the input vector size.
auto centerPixel = in.GetCenterValue();
auto centerPixel = in.GetCenterPixel();
listSample->SetMeasurementVectorSize(centerPixel.Size());
OffsetType off;
......@@ -188,7 +106,7 @@ public:
off[0] = x;
if ((abs(x) > internalRadiusX) || (abs(y) > internalRadiusY))
{
listSample->PushBack(in[off]);
listSample->PushBack(in.GetPixel(off));
}
}
}
......@@ -224,12 +142,8 @@ public:
}
};
} // end namespace functor
} // end namespace functor
} // end namespace otb
#ifndef OTB_MANUAL_INSTANTIATION
#include "otbLocalRxDetectorFilter.hxx"
#endif
#endif
/*
* Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES)
*
* This file is part of Orfeo Toolbox
*
* https://www.orfeo-toolbox.org/
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef otbLocalRxDetectorFilter_hxx
#define otbLocalRxDetectorFilter_hxx
#include "otbLocalRxDetectorFilter.h"
namespace otb
{
/**
*
*/
template <class TInputImage, class TOutputImage>
LocalRxDetectorFilter<TInputImage, TOutputImage>
::LocalRxDetectorFilter()
: m_InternalRadius(1), m_ExternalRadius(2)
{
}
/**
*
*/
template <class TInputImage, class TOutputImage>
void
LocalRxDetectorFilter<TInputImage, TOutputImage>
::PrintSelf(std::ostream& os, itk::Indent indent) const
{
Superclass::PrintSelf(os, indent);
os << indent << "Internal Radius: " << m_InternalRadius << std::endl;
os << indent << "External Radius: " << m_ExternalRadius << std::endl;
}
/**
*
*/
template <class TInputImage, class TOutputImage>
void
LocalRxDetectorFilter<TInputImage, TOutputImage>
::BeforeThreadedGenerateData()
{
// Get the input and output pointers
OutputPointerType outputPtr = this->GetOutput();
// Fill the buffer with black pixels
outputPtr->FillBuffer(0);
}
/**
*
*/
template <class TInputImage, class TOutputImage>
void
LocalRxDetectorFilter<TInputImage, TOutputImage>
::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread,
itk::ThreadIdType threadId)
{
// Get the input and output pointers
InputConstPointerType inputPtr = this->GetInput();
OutputPointerType outputPtr = this->GetOutput();
// Support progress methods/callbacks
itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels());
// Compute input region for thread
typename TInputImage::RegionType inputRegionForThread;
inputRegionForThread = outputRegionForThread;
inputRegionForThread.PadByRadius(m_ExternalRadius);
inputRegionForThread.Crop(inputPtr->GetLargestPossibleRegion());
// Iterator on input region
typename ConstShapedNeighborhoodIteratorType::RadiusType radius;
radius.Fill(m_ExternalRadius);
VectorFaceCalculatorType vectorFaceCalculator;
typename VectorFaceCalculatorType::FaceListType vectorFaceList;
typename VectorFaceCalculatorType::FaceListType::iterator vectorFit;
vectorFaceList = vectorFaceCalculator(inputPtr, inputRegionForThread, radius);
vectorFit = vectorFaceList.begin(); // Only the first face is used
ConstShapedNeighborhoodIteratorType inputIt(radius, inputPtr, *vectorFit);
// Neighborhood Configuration
typename ConstShapedNeighborhoodIteratorType::OffsetType off;
for (int y = -m_ExternalRadius; y <= m_ExternalRadius; y++)
{
off[1] = y;
for (int x = -m_ExternalRadius; x <= m_ExternalRadius; x++)
{
off[0] = x;
if ((abs(x) > m_InternalRadius) || (abs(y) > m_InternalRadius))
{
inputIt.ActivateOffset(off);
}
}
}
// iterator on output region
FaceCalculatorType faceCalculator;
typename FaceCalculatorType::FaceListType faceList;
typename FaceCalculatorType::FaceListType::iterator fit;
faceList = faceCalculator(outputPtr, inputRegionForThread, radius);
fit = faceList.begin(); // Only the first face is used
ImageRegionIteratorType outputIt(outputPtr, *fit);
// Run Input Image
for (inputIt.GoToBegin(), outputIt.GoToBegin(); !inputIt.IsAtEnd(); ++inputIt, ++outputIt)
{
// Create ListSample
typename ListSampleType::Pointer listSample = ListSampleType::New();
listSample->SetMeasurementVectorSize(inputPtr->GetNumberOfComponentsPerPixel());
// Run neighborhood
typename ConstShapedNeighborhoodIteratorType::ConstIterator ci;
for (ci = inputIt.Begin(); !ci.IsAtEnd(); ++ci)
{
// Pushback element in listSample
listSample->PushBack(ci.Get());
}
// Compute mean & covariance matrix
typename CovarianceCalculatorType::Pointer covarianceCalculator = CovarianceCalculatorType::New();
covarianceCalculator->SetInput(listSample);
covarianceCalculator->Update();
MeasurementVectorRealType meanVector = covarianceCalculator->GetMean();
MatrixType covarianceMatrix = covarianceCalculator->GetCovarianceMatrix();
// Compute RX value
typename MatrixType::InternalMatrixType invCovMat = covarianceMatrix.GetInverse();
VectorMeasurementType testPixVec;
testPixVec = inputPtr->GetPixel(inputIt.GetIndex());
VectorMeasurementType meanVec(meanVector.GetNumberOfElements());
for(unsigned int i = 0; i < meanVector.GetNumberOfElements(); ++i)
{
meanVec.SetElement(i, meanVector.GetElement(i));
}
typename MatrixType::InternalMatrixType centeredTestPixMat(meanVector.GetNumberOfElements(), 1);
for (unsigned int i = 0; i < centeredTestPixMat.rows(); ++i)
{
centeredTestPixMat.put(i, 0, (testPixVec.GetElement(i) - meanVector.GetElement(i)));
}
typename MatrixType::InternalMatrixType rxValue = centeredTestPixMat.transpose() * invCovMat * centeredTestPixMat;
outputIt.Set(rxValue.get(0, 0));
}
}
/**
*
*/
template <class TInputImage, class TOutputImage>
void
LocalRxDetectorFilter<TInputImage, TOutputImage>
::GenerateInputRequestedRegion()
{
// call the superclass' implementation of this method
Superclass::GenerateInputRequestedRegion();
// get pointers to the input and output
InputPointerType inputPtr =
const_cast< InputImageType * >( this->GetInput());
OutputPointerType outputPtr = this->GetOutput();
if ( !inputPtr || !outputPtr )
{
return;
}
// get a copy of the input requested region (should equal the output
// requested region)
typename TInputImage::RegionType inputRequestedRegion;
inputRequestedRegion = inputPtr->GetRequestedRegion();
// pad the input requested region by the operator radius
inputRequestedRegion.PadByRadius( m_ExternalRadius );
// crop the input requested region at the input's largest possible region
if ( inputRequestedRegion.Crop(inputPtr->GetLargestPossibleRegion()) )
{
inputPtr->SetRequestedRegion( inputRequestedRegion );
return;
}
else
{
// Couldn't crop the region (requested region is outside the largest
// possible region). Throw an exception.
// store what we tried to request (prior to trying to crop)
inputPtr->SetRequestedRegion( inputRequestedRegion );
// build an exception
itk::InvalidRequestedRegionError e(__FILE__, __LINE__);
e.SetLocation(ITK_LOCATION);
e.SetDescription("Requested region is (at least partially) outside the largest possible region.");
e.SetDataObject(inputPtr);
throw e;
}
}
} // end namespace otb
#endif
......@@ -28,7 +28,7 @@ detection which have shown success for multispectral and hyperspectral images
otb_module(OTBAnomalyDetection
DEPENDS
OTBITK
OTBFunctor
TEST_DEPENDS
OTBTestKernel
OTBImageIO
......
......@@ -19,56 +19,58 @@
*/
#include "otbImageFileReader.h"
#include "otbImage.h"
#include "otbVectorImage.h"
#include "otbImageFileWriter.h"
#include "otbLocalRxDetectorFilter.h"
#include "itkUnaryFunctorImageFilter.h"
#include "itkRescaleIntensityImageFilter.h"
#include "otbFunctorImageFilter.h"
int LocalRXDetectorTest(int itkNotUsed(argc), char * argv[])
{
typedef double PixelType;
typedef otb::VectorImage<PixelType, 2> VectorImageType;
typedef otb::Image<PixelType, 2> ImageType;
typedef otb::LocalRxDetectorFilter<VectorImageType, ImageType> LocalRxDetectorFilterType;
typedef double PixelType;
typedef otb::VectorImage<PixelType, 2> VectorImageType;
typedef otb::Image<PixelType, 2> ImageType;
typedef otb::Functor::LocalRxDetectionFunctor<PixelType> LocalRxDetectorFunctorType;
typedef otb::ImageFileReader<VectorImageType> ReaderType;
typedef otb::ImageFileReader<VectorImageType> ReaderType;
typedef unsigned char WritePixelType;
typedef otb::Image<WritePixelType> WriteImageType;
typedef otb::ImageFileWriter<WriteImageType> WriterType;
typedef itk::RescaleIntensityImageFilter<ImageType, WriteImageType> RescalerType;
typedef unsigned char WritePixelType;
typedef otb::Image<WritePixelType> WriteImageType;
typedef otb::ImageFileWriter<WriteImageType> WriterType;
typedef itk::RescaleIntensityImageFilter<ImageType, WriteImageType> RescalerType;
/////////// PARAMETERS ///////////
/////////// PARAMETERS ///////////
const char * filename = argv[1];
const char * outputFilename = argv[2];
const unsigned int externalRadius = atoi(argv[3]);
const unsigned int internalRadius = atoi(argv[4]);
//////// RX Filtering /////////
const char * filename = argv[1];
const char * outputFilename = argv[2];
const int externalRadius = atoi(argv[3]);