From 22724050b4f95b42da13ffe1c3b8461bed73e6e2 Mon Sep 17 00:00:00 2001 From: Julien Malik <julien.malik@c-s.fr> Date: Fri, 27 May 2011 08:52:37 +0200 Subject: [PATCH] ENH: add ParserConditionDataNodeFeatureFunction --- ...tbParserConditionDataNodeFeatureFunction.h | 116 +++++++++++++++ ...ParserConditionDataNodeFeatureFunction.txx | 129 +++++++++++++++++ Testing/Code/BasicFilters/CMakeLists.txt | 28 ++++ .../BasicFilters/otbBasicFiltersTests15.cxx | 2 + ...ParserConditionDataNodeFeatureFunction.cxx | 133 ++++++++++++++++++ 5 files changed, 408 insertions(+) create mode 100644 Code/BasicFilters/otbParserConditionDataNodeFeatureFunction.h create mode 100644 Code/BasicFilters/otbParserConditionDataNodeFeatureFunction.txx create mode 100644 Testing/Code/BasicFilters/otbParserConditionDataNodeFeatureFunction.cxx diff --git a/Code/BasicFilters/otbParserConditionDataNodeFeatureFunction.h b/Code/BasicFilters/otbParserConditionDataNodeFeatureFunction.h new file mode 100644 index 0000000000..82a4c63d93 --- /dev/null +++ b/Code/BasicFilters/otbParserConditionDataNodeFeatureFunction.h @@ -0,0 +1,116 @@ +/*========================================================================= + + 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 __otbParserConditionDataNodeFeatureFunction_h +#define __otbParserConditionDataNodeFeatureFunction_h + +#include "otbDataNodeImageFunction.h" +#include "otbDataNode.h" +#include "otbPolyLineImageConstIterator.h" +#include "otbMaskMuParserFunctor.h" + +namespace otb +{ +/** \class ParserConditionDataNodeFeatureFunction + * \brief Compute a ParserCondition based feature alongside a + * datanode. + * + * This function evaluate a condition alongside a datanode. + * The descriptor is the percentage of pixels iterated for which + * the condition is true. + * + * \ingroup Functions + * \sa DataNodeImageFunction + * \sa SpectralAngleDataNodeFeatureFunction + */ + +template < +class TImage, +class TCoordRep = double, +class TPrecision = double +> +class ITK_EXPORT ParserConditionDataNodeFeatureFunction : + public DataNodeImageFunction<TImage, std::vector<TPrecision>, TCoordRep, TPrecision> +{ +public: + /** Standard class typedefs. */ + typedef ParserConditionDataNodeFeatureFunction Self; + typedef DataNodeImageFunction<TImage, std::vector<TPrecision>, TCoordRep, TPrecision> + 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(ParserConditionDataNodeFeatureFunction, DataNodeImageFunction); + + /** Some typedefs. */ + typedef typename Superclass::DataNodeType DataNodeType; + typedef typename DataNodeType::LineType LineType; + + typedef TImage InputImageType; + typedef typename InputImageType::ConstPointer InputImageConstPointer; + typedef typename InputImageType::PixelType PixelType; + typedef typename InputImageType::InternalPixelType ScalarRealType; + typedef typename InputImageType::IndexType IndexType; + typedef typename InputImageType::IndexValueType IndexValueType; + + typedef TCoordRep CoordRepType; + + typedef TPrecision PrecisionType; + + typedef PolyLineImageConstIterator<InputImageType, LineType> + ImageLineIteratorType; + + typedef Functor::MaskMuParserFunctor<PixelType> ParserConditionFunctorType; + typedef typename ParserConditionFunctorType::Pointer ParserConditionFunctorPointer; + + typedef std::vector<PrecisionType> OutputType; + + virtual OutputType Evaluate( const DataNodeType& node ) const; + + std::string GetExpression(std::string expression) const + { + return m_ParserConditionFunctor->GetExpression(); + } + + void SetExpression(std::string expression) + { + m_ParserConditionFunctor->SetExpression(expression); + } + +protected: + ParserConditionDataNodeFeatureFunction(); + virtual ~ParserConditionDataNodeFeatureFunction() {} + void PrintSelf(std::ostream& os, itk::Indent indent) const; + +private: + ParserConditionDataNodeFeatureFunction(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + + /** ParserCondition Functor */ + ParserConditionFunctorPointer m_ParserConditionFunctor; +}; + +} +#ifndef OTB_MANUAL_INSTANTIATION +#include "otbParserConditionDataNodeFeatureFunction.txx" +#endif + +#endif diff --git a/Code/BasicFilters/otbParserConditionDataNodeFeatureFunction.txx b/Code/BasicFilters/otbParserConditionDataNodeFeatureFunction.txx new file mode 100644 index 0000000000..b151867fb1 --- /dev/null +++ b/Code/BasicFilters/otbParserConditionDataNodeFeatureFunction.txx @@ -0,0 +1,129 @@ +/*========================================================================= + + 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 __otbParserConditionDataNodeFeatureFunction_txx +#define __otbParserConditionDataNodeFeatureFunction_txx + +#include "otbParserConditionDataNodeFeatureFunction.h" + +namespace otb +{ + +/** + * Constructor + */ +template <class TImage, class TCoordRep, class TPrecision> +ParserConditionDataNodeFeatureFunction<TImage, TCoordRep, TPrecision> +::ParserConditionDataNodeFeatureFunction() +{ + m_ParserConditionFunctor = ParserConditionFunctorType::New(); +} + +/** + * Standard "PrintSelf" method + */ +template <class TImage, class TCoordRep, class TPrecision> +void +ParserConditionDataNodeFeatureFunction<TImage, TCoordRep, TPrecision> +::PrintSelf( std::ostream& os, itk::Indent indent) const +{ + Superclass::PrintSelf( os, indent ); + //os << indent << "ParserCondition : " << m_ParserConditionFunctor << std::endl; +} + +template <class TImage, class TCoordRep, class TPrecision> +typename ParserConditionDataNodeFeatureFunction<TImage, TCoordRep, TPrecision> +::OutputType + ParserConditionDataNodeFeatureFunction<TImage, TCoordRep, TPrecision> +::Evaluate( const DataNodeType& node ) const +{ + // The parser evaluation can't be const since the parser state + // changes at the first evaluation, but in fact we don't modify + // anything here. + // To fit with the rest of the framework, we try to keep the Evaluate + // function const + Self* _this = const_cast<Self*>(this); + ParserConditionFunctorType& parser = *(_this->m_ParserConditionFunctor); + // Ugly things over + + + const typename ImageLineIteratorType::PathType* path; + + switch (node.GetNodeType()) + { + case FEATURE_POINT: + { + itkExceptionMacro(<< "This DataNode type is not handle yet"); + break; + } + case FEATURE_LINE: + { + path = node.GetLine(); + break; + } + case FEATURE_POLYGON: + { + path = node.GetPolygonExteriorRing(); + break; + } + default: + { + itkExceptionMacro(<< "This DataNode type is not handle yet"); + break; + } + } + + ImageLineIteratorType lineIt(this->GetInputImage(), path); + lineIt.GoToBegin(); + + double nbValidPixel = 0.; + double nbVisitedPixel = 0.; + + while(!lineIt.IsAtEnd()) + { + if(this->IsInsideBuffer(lineIt.GetIndex())) + { + if( parser(this->GetInputImage()->GetPixel(lineIt.GetIndex())) ) + { + nbValidPixel += 1; + } + nbVisitedPixel += 1; + } + ++lineIt; + } + + OutputType output; +std::cout << "nbValidPixel " << nbValidPixel << std::endl; +std::cout << "nbVisitedPixel " << nbVisitedPixel << std::endl; + if(nbVisitedPixel == 0) + { + output.push_back(static_cast<PrecisionType>(0.)); + } + else + { + output.push_back(static_cast<PrecisionType>(nbValidPixel/nbVisitedPixel)); + } + + output.push_back(static_cast<PrecisionType>(nbValidPixel)); + output.push_back(static_cast<PrecisionType>(nbVisitedPixel)); +std::cout << "output " << output[0] << std::endl; + return output; +} + +} // end namespace otb + +#endif diff --git a/Testing/Code/BasicFilters/CMakeLists.txt b/Testing/Code/BasicFilters/CMakeLists.txt index 652ff40c0f..b2659a60b0 100644 --- a/Testing/Code/BasicFilters/CMakeLists.txt +++ b/Testing/Code/BasicFilters/CMakeLists.txt @@ -2059,6 +2059,33 @@ ADD_TEST(bfTvNDVIDataNodeFeatureFunction_Polygon ${BASICFILTERS_TESTS15} 0 ) + +ADD_TEST(bfTvParserConditionDataNodeFeatureFunction_Line_NDVI ${BASICFILTERS_TESTS15} + --compare-ogr ${NOTOL} + ${BASELINE_FILES}/bfTvNDVIDataNodeFeatureFunctionOutput_Line.shp + ${TEMP}/bfTvParserConditionDataNodeFeatureFunction_Line_NDVI.shp + otbParserConditionDataNodeFeatureFunction + ${INPUTDATA}/Dempster-Shafer/ROI_QB_TOULOUSE_ROADS.shp + ${INPUTDATA}/Dempster-Shafer/ROI_QB_TOULOUSE.TIF + ${INPUTDATA}/DEM/srtm_directory + ${TEMP}/bfTvParserConditionDataNodeFeatureFunction_Line_NDVI.shp + "ndvi(b3,b4) > 0.047" + 0 +) + +ADD_TEST(bfTvParserConditionDataNodeFeatureFunction_Polygon_NDVI ${BASICFILTERS_TESTS15} + --compare-ogr ${NOTOL} + ${BASELINE_FILES}/bfTvNDVIDataNodeFeatureFunctionOutput_Polygon.shp + ${TEMP}/bfTvParserConditionDataNodeFeatureFunction_Polygon_NDVI.shp + otbParserConditionDataNodeFeatureFunction + ${INPUTDATA}/Dempster-Shafer/ROI_QB_TOULOUSE_BUILDINGS.shp + ${INPUTDATA}/Dempster-Shafer/ROI_QB_TOULOUSE.TIF + ${INPUTDATA}/DEM/srtm_directory + ${TEMP}/bfTvParserConditionDataNodeFeatureFunction_Polygon_NDVI.shp + "ndvi(b3,b4) > 0.047" + 0 +) + # ------------------ otbSpectralAngleDataNodeFeatureFunction ------------------ ADD_TEST(bfTuSpectralAngleDataNodeFeatureFunctionNew ${BASICFILTERS_TESTS15} otbSpectralAngleDataNodeFeatureFunctionNew @@ -2395,6 +2422,7 @@ otbNDVIDataNodeFeatureFunction.cxx otbSpectralAngleDataNodeFeatureFunction.cxx otbDBOverlapDataNodeFeatureFunction.cxx otbRadiometryHomogenousWithNeighborhoodDataNodeFeatureFunction.cxx +otbParserConditionDataNodeFeatureFunction.cxx ) OTB_ADD_EXECUTABLE(otbBasicFiltersTests1 "${BasicFilters_SRCS1}" "OTBBasicFilters;OTBIO;OTBTesting") diff --git a/Testing/Code/BasicFilters/otbBasicFiltersTests15.cxx b/Testing/Code/BasicFilters/otbBasicFiltersTests15.cxx index 05859f0dca..66202f1b1e 100644 --- a/Testing/Code/BasicFilters/otbBasicFiltersTests15.cxx +++ b/Testing/Code/BasicFilters/otbBasicFiltersTests15.cxx @@ -27,6 +27,8 @@ void RegisterTests() { REGISTER_TEST(otbNDVIDataNodeFeatureFunctionNew); REGISTER_TEST(otbNDVIDataNodeFeatureFunction); + REGISTER_TEST(otbParserConditionDataNodeFeatureFunctionNew); + REGISTER_TEST(otbParserConditionDataNodeFeatureFunction); REGISTER_TEST(otbSpectralAngleDataNodeFeatureFunctionNew); REGISTER_TEST(otbSpectralAngleDataNodeFeatureFunction); REGISTER_TEST(otbRadiometryHomogenousWithNeighborhoodDataNodeFeatureFunctionNew); diff --git a/Testing/Code/BasicFilters/otbParserConditionDataNodeFeatureFunction.cxx b/Testing/Code/BasicFilters/otbParserConditionDataNodeFeatureFunction.cxx new file mode 100644 index 0000000000..e62307399f --- /dev/null +++ b/Testing/Code/BasicFilters/otbParserConditionDataNodeFeatureFunction.cxx @@ -0,0 +1,133 @@ +/*========================================================================= + + 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. + + =========================================================================*/ + +#include "otbParserConditionDataNodeFeatureFunction.h" + +#include "otbVectorImage.h" +#include "otbImageFileReader.h" +#include "otbVectorData.h" +#include "otbVectorDataFileReader.h" +#include "otbVectorDataIntoImageProjectionFilter.h" +#include "otbVectorDataFileWriter.h" +#include "itkPreOrderTreeIterator.h" + +int otbParserConditionDataNodeFeatureFunctionNew(int argc, char* argv[]) +{ + typedef double CoordRepType; + typedef double PrecisionType; + typedef otb::VectorImage<double, 2> ImageType; + typedef otb::ParserConditionDataNodeFeatureFunction<ImageType, CoordRepType, PrecisionType> + ParserConditionDataNodeFeaturefunctionType; + + ParserConditionDataNodeFeaturefunctionType::Pointer + ParserConditionFeature = ParserConditionDataNodeFeaturefunctionType::New(); + + std::cout << ParserConditionFeature << std::endl; + + return EXIT_SUCCESS; +} + +int otbParserConditionDataNodeFeatureFunction(int argc, char* argv[]) +{ + const char * inputVD = argv[1]; + const char * inputImg = argv[2]; + const char * DEMDir = argv[3]; + const char * outputVD = argv[4]; + const char * expression = argv[5]; + int DisplayWarnings = atoi(argv[6]); + + typedef double CoordRepType; + typedef double PrecisionType; + typedef otb::VectorImage<PrecisionType> ImageType; + typedef otb::ImageFileReader<ImageType> ImageReaderType; + typedef otb::VectorData<CoordRepType, 2, PrecisionType> VectorDataType; + typedef VectorDataType::DataNodeType DataNodeType; + typedef otb::VectorDataFileReader<VectorDataType> VectorDataReaderType; + typedef otb::VectorDataIntoImageProjectionFilter<VectorDataType, ImageType> VectorDataReProjFilter; + typedef otb::VectorDataFileWriter<VectorDataType> VectorDataWriterType; + typedef itk::PreOrderTreeIterator<VectorDataType::DataTreeType> TreeIteratorType; + + typedef otb::ParserConditionDataNodeFeatureFunction<ImageType, CoordRepType, PrecisionType> + ParserConditionDataNodeFeaturefunctionType; + typedef ParserConditionDataNodeFeaturefunctionType::OutputType ParserConditionFeatureOutputType; + + ImageReaderType::Pointer imgReader = ImageReaderType::New(); + VectorDataReaderType::Pointer vdReader = VectorDataReaderType::New(); + VectorDataReProjFilter::Pointer vdReProjFilter = VectorDataReProjFilter::New(); + VectorDataWriterType::Pointer vdWriter = VectorDataWriterType::New(); + ParserConditionDataNodeFeaturefunctionType::Pointer + ParserConditionFeatureFunction = ParserConditionDataNodeFeaturefunctionType::New(); + + if (!DisplayWarnings) + { + imgReader->SetGlobalWarningDisplay(0); + } + + vdReader->SetFileName(inputVD); + vdReader->Update(); + + imgReader->SetFileName(inputImg); + imgReader->UpdateOutputInformation(); + imgReader->Update(); //Needed to set m_EndIndex, m_StartIndex in otbDataNodeImageFunction + + vdReProjFilter->SetInputImage(imgReader->GetOutput()); + vdReProjFilter->SetInputVectorData(vdReader->GetOutput()); + vdReProjFilter->SetDEMDirectory(DEMDir); + vdReProjFilter->SetUseOutputSpacingAndOriginFromImage(true); + vdReProjFilter->Update(); + + ParserConditionFeatureFunction->SetExpression("ndvi(b3,b4) > 0.047"); + ParserConditionFeatureFunction->SetInputImage(imgReader->GetOutput()); + + // Output + VectorDataType::Pointer outVD = VectorDataType::New(); + // Retrieving root node + DataNodeType::Pointer root = outVD->GetDataTree()->GetRoot()->Get(); + // Create the document node + DataNodeType::Pointer document = DataNodeType::New(); + document->SetNodeType(otb::DOCUMENT); + // Adding the layer to the data tree + outVD->GetDataTree()->Add(document, root); + // Create the folder node + DataNodeType::Pointer folder = DataNodeType::New(); + folder->SetNodeType(otb::FOLDER); + // Adding the layer to the data tree + outVD->GetDataTree()->Add(folder, document); + + TreeIteratorType itVector(vdReProjFilter->GetOutput()->GetDataTree()); + itVector.GoToBegin(); + while (!itVector.IsAtEnd()) + { + if (itVector.Get()->IsLineFeature() || itVector.Get()->IsPolygonFeature()) + { + const DataNodeType::Pointer currentGeometry = itVector.Get(); + ParserConditionFeatureOutputType currentResult; + currentResult = ParserConditionFeatureFunction->Evaluate(*(currentGeometry.GetPointer())); + currentGeometry->SetFieldAsDouble("NDVI", (double) (currentResult[0])); + outVD->GetDataTree()->Add(currentGeometry, folder); + } + ++itVector; + } + + vdWriter->SetInput(outVD); + vdWriter->SetFileName(outputVD); + vdWriter->Update(); + + return EXIT_SUCCESS; +} + -- GitLab