Commit cbd4bc0f authored by Guillaume Pasero's avatar Guillaume Pasero

RM: remove deprecated classes (the otb::MachineLearningModel framework should be used instead)

parent 938a62a9
/*
* Copyright (C) 2005-2017 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 otbSVMClassifier_h
#define otbSVMClassifier_h
#include "vcl_deprecated_header.h"
#include "itkSampleClassifierFilter.h"
#include "otbSVMModel.h"
#include "itkVectorImage.h"
#include "itkListSample.h"
namespace otb
{
/** \class SVMClassifier
* \brief SVM-based classifier
*
* The first template argument is the type of the target sample data
* that this classifier will assign a class label for each measurement
* vector. The second one is the pixel type of the labels to be
* produced by the classifier.
*
* Before you call the GenerateData method to start the classification
* process, you should plug in all necessary parts ( a SVM model and a
* target sample data).
*
* The classification result is stored in a vector of Subsample object.
* Each class has its own class sample (Subsample object) that has
* InstanceIdentifiers for all measurement vectors belong to the class.
* The InstanceIdentifiers come from the target sample data. Therefore,
* the Subsample objects act as separate class masks.
*
* \deprecated
*
* \sa MachineLearningModel
* \sa LibSVMMachineLearningModel
* \sa ImageClassificationFilter
*
*
* \ingroup OTBSVMLearning
*/
template<class TSample, class TLabel>
class ITK_EXPORT SVMClassifier :
public itk::Statistics::SampleClassifierFilter<TSample>
{
public:
/** Standard class typedef*/
typedef SVMClassifier Self;
typedef itk::Statistics::SampleClassifierFilter<TSample> Superclass;
typedef itk::SmartPointer<Self> Pointer;
typedef itk::SmartPointer<const Self> ConstPointer;
/** Standard macros */
itkTypeMacro(SVMClassifier, itk::Statistics::SampleClassifier);
itkNewMacro(Self);
/** Output type for GetClassSample method */
typedef itk::Statistics::MembershipSample<TSample> OutputType;
typedef itk::VariableLengthVector<float> HyperplanesDistancesType;
typedef itk::Statistics::ListSample<HyperplanesDistancesType> HyperplanesDistancesListSampleType;
/** typedefs from TSample object */
typedef typename TSample::MeasurementType MeasurementType;
typedef typename TSample::MeasurementVectorType MeasurementVectorType;
/** typedefs from Superclass */
typedef typename Superclass::MembershipFunctionVectorObjectPointer
MembershipFunctionPointerVector; //FIXME adopt new naming convention
/** typedef for label type */
typedef TLabel ClassLabelType;
/** Returns the classification result */
OutputType* GetOutput();
void SetOutput(OutputType* output);
using Superclass::SetOutput;
/** Returns the hyperplanes distances */
HyperplanesDistancesListSampleType * GetHyperplanesDistancesOutput();
/** Type definitions for the SVM Model. */
typedef SVMModel<MeasurementType, ClassLabelType> SVMModelType;
typedef typename SVMModelType::Pointer SVMModelPointer;
/** Set the model */
itkSetObjectMacro(Model, SVMModelType);
/** Get the number of classes. */
itkGetObjectMacro(Model, SVMModelType);
void Update() ITK_OVERRIDE;
protected:
SVMClassifier();
~SVMClassifier() ITK_OVERRIDE {}
void PrintSelf(std::ostream& os, itk::Indent indent) const ITK_OVERRIDE;
/** Starts the classification process */
void GenerateData() ITK_OVERRIDE;
virtual void DoClassification();
private:
/** Output pointer (MembershipSample) */
typename OutputType::Pointer m_Output;
/** Hyperplanes distances output */
typename HyperplanesDistancesListSampleType::Pointer m_HyperplanesDistancesOutput;
SVMModelPointer m_Model;
}; // end of class
} // end of namespace otb
#ifndef OTB_MANUAL_INSTANTIATION
#include "otbSVMClassifier.txx"
#endif
#endif
/*
* Copyright (C) 2005-2017 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 otbSVMClassifier_txx
#define otbSVMClassifier_txx
#include "otbSVMClassifier.h"
#include "otbMacro.h"
namespace otb
{
template<class TSample, class TLabel>
SVMClassifier<TSample, TLabel>
::SVMClassifier()
{
m_Output = OutputType::New();
m_HyperplanesDistancesOutput = HyperplanesDistancesListSampleType::New();
}
template<class TSample, class TLabel>
void
SVMClassifier<TSample, TLabel>
::PrintSelf(std::ostream& os, itk::Indent indent) const
{
Superclass::PrintSelf(os, indent);
}
template<class TSample, class TLabel>
void
SVMClassifier<TSample, TLabel>
::Update()
{
this->GenerateData();
}
template<class TSample, class TLabel>
void
SVMClassifier<TSample, TLabel>
::GenerateData()
{
if (!m_Model)
{
itkExceptionMacro("No model, can not do classification.");
}
if (m_Model->GetNumberOfSupportVectors() == 0)
{
itkExceptionMacro(<< "SVM model does not contain any support vector, can not perform classification.");
}
m_Output->SetSample(this->GetInput());
// m_Output->Resize(this->GetSample()->Size());
//FIXME check if this is necessary (work at the decision rule
//Evaluate() level?)
unsigned int numberOfClasses = this->GetNumberOfClasses();
m_Output->SetNumberOfClasses(numberOfClasses);
this->DoClassification();
}
template<class TSample, class TLabel>
typename SVMClassifier<TSample, TLabel>::OutputType*
SVMClassifier<TSample, TLabel>
::GetOutput()
{
return m_Output;
}
template<class TSample, class TLabel>
void
SVMClassifier<TSample, TLabel>
::SetOutput(OutputType * output)
{
m_Output = output;
}
template<class TSample, class TLabel>
typename SVMClassifier<TSample, TLabel>::HyperplanesDistancesListSampleType *
SVMClassifier<TSample, TLabel>
::GetHyperplanesDistancesOutput()
{
return m_HyperplanesDistancesOutput;
}
template<class TSample, class TLabel>
void
SVMClassifier<TSample, TLabel>
::DoClassification()
{
itk::TimeProbe probe;
typename TSample::ConstIterator iter = this->GetInput()->Begin();
typename TSample::ConstIterator end = this->GetInput()->End();
typename OutputType::ConstIterator iterO = m_Output->Begin();
typename OutputType::ConstIterator endO = m_Output->End();
typename TSample::MeasurementVectorType measurements;
// sample Measurement vector size
int numberOfComponentsPerSample = iter.GetMeasurementVector().Size();
// The size of the hyperplane distance vector is the number of hyperplanes
m_HyperplanesDistancesOutput->SetMeasurementVectorSize(m_Model->GetNumberOfHyperplane());
otbMsgDevMacro(<< "Starting iterations ");
while (iter != end && iterO != endO)
{
int i = 0;
typename SVMModelType::MeasurementType modelMeasurement;
measurements = iter.GetMeasurementVector();
// otbMsgDevMacro( << "Loop on components " << svm_type );
for (i = 0; i < numberOfComponentsPerSample; ++i)
{
modelMeasurement.push_back(measurements[i]);
}
ClassLabelType classLabel = m_Model->EvaluateLabel(modelMeasurement);
typename SVMModelType::DistancesVectorType hdistances = m_Model->EvaluateHyperplanesDistances(modelMeasurement);
HyperplanesDistancesType distances = hdistances;
m_HyperplanesDistancesOutput->PushBack(distances);
// Julien: Event if we support larger type for class labels,
// the AddInstance method wait for an unsigned int, so we cast it here.
m_Output->AddInstance(static_cast<unsigned int>(classLabel), iterO.GetInstanceIdentifier());
++iter;
++iterO;
}
}
} // end of namespace otb
#endif
/*
* Copyright (C) 2005-2017 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 otbSVMImageClassificationFilter_h
#define otbSVMImageClassificationFilter_h
#include "vcl_deprecated_header.h"
#include "itkInPlaceImageFilter.h"
#include "otbSVMModel.h"
namespace otb
{
/** \class SVMImageClassificationFilter
* \brief This filter performs the classification of a VectorImage using a SVM Model.
*
* This filter is streamed and threaded, allowing to classify huge images
* while fully using several core.
*
* \deprecated
*
* \sa MachineLearningModel
* \sa LibSVMMachineLearningModel
* \sa ImageClassificationFilter
*
* \ingroup Streamed
* \ingroup Threaded
*
* \ingroup OTBSVMLearning
*/
template <class TInputImage, class TOutputImage, class TMaskImage = TOutputImage>
class ITK_EXPORT SVMImageClassificationFilter
: public itk::InPlaceImageFilter<TInputImage, TOutputImage>
{
public:
/** Standard typedefs */
typedef SVMImageClassificationFilter Self;
typedef itk::InPlaceImageFilter<TInputImage, TOutputImage> Superclass;
typedef itk::SmartPointer<Self> Pointer;
typedef itk::SmartPointer<const Self> ConstPointer;
/** Type macro */
itkNewMacro(Self);
/** Creation through object factory macro */
itkTypeMacro(SVMImageClassificationFilter, InPlaceImageFilter);
/** The max dimension of the sample to classify.
* This filter internally uses itk::FixedArray as input for the classifier,
* so the max sample size has to be fixed at compilation time.
*/
typedef TInputImage InputImageType;
typedef typename InputImageType::ConstPointer InputImageConstPointerType;
typedef typename InputImageType::InternalPixelType ValueType;
typedef TMaskImage MaskImageType;
typedef typename MaskImageType::ConstPointer MaskImageConstPointerType;
typedef typename MaskImageType::Pointer MaskImagePointerType;
typedef TOutputImage OutputImageType;
typedef typename OutputImageType::Pointer OutputImagePointerType;
typedef typename OutputImageType::RegionType OutputImageRegionType;
typedef typename OutputImageType::PixelType LabelType;
typedef SVMModel<ValueType, LabelType> ModelType;
typedef typename ModelType::Pointer ModelPointerType;
/** Set/Get the svm model */
itkSetObjectMacro(Model, ModelType);
itkGetObjectMacro(Model, ModelType);
/** Set/Get the default label */
itkSetMacro(DefaultLabel, LabelType);
itkGetMacro(DefaultLabel, LabelType);
/**
* If set, only pixels within the mask will be classified.
* \param mask The input mask.
*/
void SetInputMask(const MaskImageType * mask);
/**
* Get the input mask.
* \return The mask.
*/
const MaskImageType * GetInputMask(void);
protected:
/** Constructor */
SVMImageClassificationFilter();
/** Destructor */
~SVMImageClassificationFilter() ITK_OVERRIDE {}
/** Threaded generate data */
void ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId) ITK_OVERRIDE;
/** Before threaded generate data */
void BeforeThreadedGenerateData() ITK_OVERRIDE;
/**PrintSelf method */
void PrintSelf(std::ostream& os, itk::Indent indent) const ITK_OVERRIDE;
private:
SVMImageClassificationFilter(const Self &); //purposely not implemented
void operator =(const Self&); //purposely not implemented
/** The SVM model used for classification */
ModelPointerType m_Model;
/** Default label for invalid pixels (when using a mask) */
LabelType m_DefaultLabel;
};
} // End namespace otb
#ifndef OTB_MANUAL_INSTANTIATION
#include "otbSVMImageClassificationFilter.txx"
#endif
#endif
/*
* Copyright (C) 2005-2017 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 otbSVMImageClassificationFilter_txx
#define otbSVMImageClassificationFilter_txx
#include "otbSVMImageClassificationFilter.h"
#include "itkImageRegionIterator.h"
#include "itkProgressReporter.h"
namespace otb
{
/**
* Constructor
*/
template <class TInputImage, class TOutputImage, class TMaskImage>
SVMImageClassificationFilter<TInputImage, TOutputImage, TMaskImage>
::SVMImageClassificationFilter()
{
this->SetNumberOfRequiredInputs(2);
this->SetNumberOfRequiredInputs(1);
m_DefaultLabel = itk::NumericTraits<LabelType>::ZeroValue();
}
template <class TInputImage, class TOutputImage, class TMaskImage>
void
SVMImageClassificationFilter<TInputImage, TOutputImage, TMaskImage>
::SetInputMask(const MaskImageType * mask)
{
this->itk::ProcessObject::SetNthInput(1, const_cast<MaskImageType *>(mask));
}
template <class TInputImage, class TOutputImage, class TMaskImage>
const typename SVMImageClassificationFilter<TInputImage, TOutputImage, TMaskImage>
::MaskImageType *
SVMImageClassificationFilter<TInputImage, TOutputImage, TMaskImage>
::GetInputMask()
{
if (this->GetNumberOfInputs() < 2)
{
return ITK_NULLPTR;
}
return static_cast<const MaskImageType *>(this->itk::ProcessObject::GetInput(1));
}
template <class TInputImage, class TOutputImage, class TMaskImage>
void
SVMImageClassificationFilter<TInputImage, TOutputImage, TMaskImage>
::BeforeThreadedGenerateData()
{
if (!m_Model)
{
itkGenericExceptionMacro(<< "No model for classification");
}
}
template <class TInputImage, class TOutputImage, class TMaskImage>
void
SVMImageClassificationFilter<TInputImage, TOutputImage, TMaskImage>
::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId)
{
// Get the input pointers
InputImageConstPointerType inputPtr = this->GetInput();
MaskImageConstPointerType inputMaskPtr = this->GetInputMask();
OutputImagePointerType outputPtr = this->GetOutput();
// Progress reporting
itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels());
// Define iterators
typedef itk::ImageRegionConstIterator<InputImageType> InputIteratorType;
typedef itk::ImageRegionConstIterator<MaskImageType> MaskIteratorType;
typedef itk::ImageRegionIterator<OutputImageType> OutputIteratorType;
InputIteratorType inIt(inputPtr, outputRegionForThread);
OutputIteratorType outIt(outputPtr, outputRegionForThread);
// Eventually iterate on masks
MaskIteratorType maskIt;
if (inputMaskPtr)
{
maskIt = MaskIteratorType(inputMaskPtr, outputRegionForThread);
maskIt.GoToBegin();
}
bool validPoint = true;
// Walk the part of the image
for (inIt.GoToBegin(), outIt.GoToBegin(); !inIt.IsAtEnd() && !outIt.IsAtEnd(); ++inIt, ++outIt)
{
// Check pixel validity
if (inputMaskPtr)
{
validPoint = maskIt.Get() > 0;
++maskIt;
}
// If point is valid
if (validPoint)
{
// Classifify
typename ModelType::MeasurementType measure;
for (unsigned int i = 0; i < inIt.Get().Size(); ++i)
{
measure.push_back(inIt.Get()[i]);
}
outIt.Set(m_Model->EvaluateLabel(measure));
}
else
{
// else, set default value
outIt.Set(m_DefaultLabel);
}
progress.CompletedPixel();
}
}
/**
* PrintSelf Method
*/
template <class TInputImage, class TOutputImage, class TMaskImage>
void
SVMImageClassificationFilter<TInputImage, TOutputImage, TMaskImage>
::PrintSelf(std::ostream& os, itk::Indent indent) const
{
Superclass::PrintSelf(os, indent);
}
} // End namespace otb
#endif
/*
* Copyright (C) 2005-2017 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 otbSVMImageModelEstimator_h
#define otbSVMImageModelEstimator_h
#include "vcl_deprecated_header.h"
#include "itkImageModelEstimatorBase.h"
#include "itkImageRegionIterator.h"
#include "otbSVMModelEstimator.h"
namespace otb
{
/** \class SVMImageModelEstimator
* \brief Class for SVM model estimation from images used for classification.
*
*
* The basic functionality of the SVMImageModelEstimator is to
* generate the models used in SVM classification. It
* requires input images and a training image to be provided by the
* user. This object supports data handling of multiband images. The
* object accepts the input image as a VectorImage only, where each
* pixel is a vector and each element of the vector corresponds to an
* entry from 1 particular band of a multiband dataset. A single band
* image is treated as a vector image with a single element for every
* vector. The classified image is treated as a single band scalar
* image.
*
* \deprecated
*
* \sa MachineLearningModel
* \sa LibSVMMachineLearningModel
* \sa ImageClassificationFilter
*
* \ingroup ClassificationFilters
*
* \ingroup OTBSVMLearning
*/
template <class TInputImage, class TTrainingImage>
class ITK_EXPORT SVMImageModelEstimator :
public SVMModelEstimator<typename TInputImage::InternalPixelType, typename TTrainingImage::PixelType>
{
public:
/** Standard class typedefs. */
typedef SVMImageModelEstimator Self;
typedef SVMModelEstimator<typename TInputImage::PixelType::ComponentType,
typename TTrainingImage::PixelType>
Superclass;
typedef itk::SmartPointer<Self> Pointer;
typedef itk::SmartPointer<const Self> ConstPointer;
/** Method for creation through the object factory. */
itkNewMacro(Self);
/** Run-time type information (and related methods). */
itkTypeMacro(SVMImageModelEstimator, otb::SVMModelEstimator);
/** Type definition for the input image. */
typedef typename TInputImage::Pointer InputImagePointer;
/** Type definitions for the training image. */
typedef typename TTrainingImage::Pointer TrainingImagePointer;
/** Type definition for the vector associated with
* input image pixel type. */
typedef typename TInputImage::PixelType InputImagePixelType;
/** Type definitions for the vector holding
* training image pixel type. */
typedef typename TTrainingImage::PixelType TrainingImagePixelType;
/** Type definitions for the iterators for the input and training images. */
typedef
itk::ImageRegionIterator<TInputImage> InputImageIterator;
typedef
itk::ImageRegionIterator<TTrainingImage> TrainingImageIterator;
/** Set the input image */
void SetInputImage(const TInputImage * inputImage);
/** Set the training image */
void SetTrainingImage(const TTrainingImage * trainingImage);
/** Get the input image */
const TInputImage * GetInputImage();
/** Get the training image */
const TTrainingImage * GetTrainingImage();
protected:
/** Constructor */
SVMImageModelEstimator();
/** Destructor */
~SVMImageModelEstimator() ITK_OVERRIDE;
/** PrintSelf */
void PrintSelf(std::ostream& os, itk::Indent indent) const ITK_OVERRIDE;
/** Implement the prepare data step from SVMModelEstimator */
void PrepareData() ITK_OVERRIDE;
private:
SVMImageModelEstimator(const Self &); //purposely not implemented
void operator =(const Self&); //purposely not implemented
}; // class SVMImageModelEstimator
} // namespace otb
#ifndef OTB_MANUAL_INSTANTIATION
#include "otbSVMImageModelEstimator.txx"
#endif
#endif
/*
* Copyright (C) 2005-2017 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