diff --git a/Code/OBIA/otbStreamingConnectedComponentSegmentationOBIAToVectorDataFilter.h b/Code/OBIA/otbStreamingConnectedComponentSegmentationOBIAToVectorDataFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..96eec13a07aaa85a01218aeabaa52215891ccda3 --- /dev/null +++ b/Code/OBIA/otbStreamingConnectedComponentSegmentationOBIAToVectorDataFilter.h @@ -0,0 +1,203 @@ +/*========================================================================= + + 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 __otbStreamingConnectedComponentSegmentationOBIAToVectorDataFilter_h +#define __otbStreamingConnectedComponentSegmentationOBIAToVectorDataFilter_h + +#include "itkMacro.h" +#include "otbPersistentImageToVectorDataFilter.h" +#include "otbPersistentFilterStreamingDecorator.h" + +#include "otbConnectedComponentMuParserFunctor.h" +#include "itkConnectedComponentFunctorImageFilter.h" +#include "otbMaskMuParserFilter.h" +#include "itkRelabelComponentImageFilter.h" +#include "otbAttributesMapLabelObject.h" +#include "otbLabelMapWithAdjacency.h" +#include "otbLabelImageToLabelMapWithAdjacencyFilter.h" +#include "otbBandsStatisticsAttributesLabelMapFilter.h" +#include "otbShapeAttributesLabelMapFilter.h" +#include "otbLabelObjectOpeningMuParserFilter.h" +#include "otbLabelMapToVectorDataFilter.h" + +namespace otb { + +/** \class PersistentConnectedComponentSegmentationOBIAToVectorDataFilter +* \brief [internal] Helper class to perform connected component segmentation on an input image, +* apply OBIA filtering and output a VectorData +* +* The whole chain is described in : +* http://wiki.orfeo-toolbox.org/index.php/Connected_component_segmentation_module +* +* This class wraps a whole processing chain based on connected component segmentation, +* OBIA filtering and conversion to VectorData. +* An optional mask can be applied to segment only the pixels inside the mask. +* +* Mathematical expression can be given for the 3 main parameters : +* <li> MaskExpression +* +* \ingroup Streamed +*/ +template <class TVImage, class TLabelImage, class TMaskImage, class TOutputVectorData> +class PersistentConnectedComponentSegmentationOBIAToVectorDataFilter : public otb::PersistentImageToVectorDataFilter<TVImage, TOutputVectorData> +{ +public: + /** Standard Self typedef */ + typedef PersistentConnectedComponentSegmentationOBIAToVectorDataFilter Self; + typedef PersistentImageToVectorDataFilter<TVImage,TOutputVectorData > Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; + + typedef TVImage VectorImageType; + typedef TLabelImage LabelImageType; + typedef TMaskImage MaskImageType; + typedef TOutputVectorData VectorDataType; + + typedef typename VectorImageType::Pointer VectorImagePointerType; + typedef typename VectorDataType::Pointer VectorDataPointerType; + + typedef typename VectorImageType::PixelType VectorImagePixelType; + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Runtime information support. */ + itkTypeMacro(PersistentConnectedComponentSegmentationOBIAToVectorDataFilter, PersistentImageToVectorDataFilter); + + /** ImageDimension constants */ + itkStaticConstMacro(InputImageDimension, unsigned int, + TVImage::ImageDimension); + + // Mask generation + typedef Functor::ConnectedComponentMuParserFunctor<VectorImagePixelType> FunctorType; + typedef itk::ConnectedComponentFunctorImageFilter< + VectorImageType, + LabelImageType, + FunctorType, + MaskImageType > ConnectedComponentFilterType; + + // mask typedef + typedef otb::MaskMuParserFilter<VectorImageType, MaskImageType> MaskMuParserFilterType; + + // Labelization + typedef itk::RelabelComponentImageFilter<LabelImageType, LabelImageType> RelabelComponentFilterType; + typedef otb::AttributesMapLabelObject<unsigned int, InputImageDimension, double> AttributesMapLabelObjectType; + + typedef otb::LabelMapWithAdjacency<AttributesMapLabelObjectType> AttributesLabelMapType; + typedef otb::LabelImageToLabelMapWithAdjacencyFilter<LabelImageType, AttributesLabelMapType> + LabelImageToLabelMapFilterType; + + typedef otb::BandsStatisticsAttributesLabelMapFilter<AttributesLabelMapType, VectorImageType> + RadiometricLabelMapFilterType; + typedef otb::ShapeAttributesLabelMapFilter<AttributesLabelMapType> ShapeLabelMapFilterType; + + typedef otb::LabelObjectOpeningMuParserFilter<AttributesLabelMapType> LabelObjectOpeningFilterType; + typedef otb::LabelMapToVectorDataFilter<AttributesLabelMapType, VectorDataType> LabelMapToVectorDataFilterType; + + typedef typename RelabelComponentFilterType::ObjectSizeType ObjectSizeType; + + /* Set the mathematical expression used for the mask */ + itkSetStringMacro(MaskExpression); + + /* Get the mathematical expression used for the mask */ + itkGetStringMacro(MaskExpression); + + /* Set the mathematical expression used during connected component segmentation */ + itkSetStringMacro(ConnectedComponentExpression); + + /* Get the mathematical expression used during connected component segmentation */ + itkGetStringMacro(ConnectedComponentExpression); + + /* Set the minimum object size */ + itkSetMacro(MinimumObjectSize, ObjectSizeType); + + /* Get the minimum object size */ + itkGetMacro(MinimumObjectSize, ObjectSizeType); + + /* Set the mathematical expression for filtering labelobjects */ + itkSetStringMacro(OBIAExpression); + + /* Get the mathematical expression for filtering labelobjects */ + itkGetStringMacro(OBIAExpression); + +protected: + PersistentConnectedComponentSegmentationOBIAToVectorDataFilter(); + + virtual ~PersistentConnectedComponentSegmentationOBIAToVectorDataFilter(); + +private: + + ObjectSizeType m_MinimumObjectSize; + std::string m_MaskExpression; + std::string m_ConnectedComponentExpression; + std::string m_OBIAExpression; + + virtual VectorDataPointerType ProcessTile(const VectorImageType* inputImage); +}; + +/** \class StreamingConnectedComponentSegmentationOBIAToVectorDataFilter +* \brief Performs connected component segmentation on an input image, +* apply OBIA filtering and output a VectorData, with streaming capabilities +* +* This class wraps a whole processing chain based on connected component segmentation, +* OBIA filtering and conversion to VectorData. +* An optional mask can be applied to segment only the pixels inside the mask. +* +* The whole chain is described in : +* http://wiki.orfeo-toolbox.org/index.php/Connected_component_segmentation_module +* +* The parameters of the processing chain must be applied on the internal filter, +* which can be accessed with GetFilter. See PersistentConnectedComponentSegmentationOBIAToVectorDataFilter +* +* Mathematical expression can be given for the 3 main parameters : +* - MaskExpression : sets the expression to apply on the input image to make a mask +* - ConnectedComponentExpression : sets the expression which connects two pixels +* - MinimumObjectSize : sets the minimum object size kept after segmentation +* - OBIAExpression : sets the expression to apply on the input image to make a mask +* +* \sa PersistentConnectedComponentSegmentationOBIAToVectorDataFilter +* \sa PersistentFilterStreamingDecorator +* +* \ingroup Streamed +*/ +template <class TVImage, class TLabelImage, class TMaskImage, class TOutputVectorData> +class StreamingConnectedComponentSegmentationOBIAToVectorDataFilter +{ +public: + + // define the PersistentStreamingLineSegmentDetector template + typedef PersistentConnectedComponentSegmentationOBIAToVectorDataFilter< + TVImage, TLabelImage, TMaskImage, TOutputVectorData> + PersistentConnectedComponentSegmentationOBIAToVectorDataFilterType; + + typedef typename PersistentConnectedComponentSegmentationOBIAToVectorDataFilterType::VectorImageType VectorImageType; + typedef typename PersistentConnectedComponentSegmentationOBIAToVectorDataFilterType::LabelImageType LabelImageType; + typedef typename PersistentConnectedComponentSegmentationOBIAToVectorDataFilterType::MaskImageType MaskImageType; + typedef typename PersistentConnectedComponentSegmentationOBIAToVectorDataFilterType::VectorDataType VectorDataType; + + // typedef for streaming capable filter + typedef PersistentFilterStreamingDecorator<PersistentConnectedComponentSegmentationOBIAToVectorDataFilterType> + FilterType; +}; + +} // end namespace itk + +#ifndef OTB_MANUAL_INSTANTIATION +#include "otbStreamingConnectedComponentSegmentationOBIAToVectorDataFilter.txx" +#endif + +#endif diff --git a/Code/OBIA/otbStreamingConnectedComponentSegmentationOBIAToVectorDataFilter.txx b/Code/OBIA/otbStreamingConnectedComponentSegmentationOBIAToVectorDataFilter.txx new file mode 100644 index 0000000000000000000000000000000000000000..ef669cfb7fd2b79a1eb57dc5c332461db0587564 --- /dev/null +++ b/Code/OBIA/otbStreamingConnectedComponentSegmentationOBIAToVectorDataFilter.txx @@ -0,0 +1,95 @@ +/*========================================================================= + + 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 __otbStreamingConnectedComponentSegmentationOBIAToVectorDataFilter_txx +#define __otbStreamingConnectedComponentSegmentationOBIAToVectorDataFilter_txx + +#include "otbStreamingConnectedComponentSegmentationOBIAToVectorDataFilter.h" + +namespace otb { + +template<class TVImage, class TLabelImage, class TMaskImage, class TOutputVectorData> +PersistentConnectedComponentSegmentationOBIAToVectorDataFilter<TVImage, TLabelImage, TMaskImage, TOutputVectorData> +::PersistentConnectedComponentSegmentationOBIAToVectorDataFilter() + : m_MinimumObjectSize(2) +{ +} + +template<class TVImage, class TLabelImage, class TMaskImage, class TOutputVectorData> +PersistentConnectedComponentSegmentationOBIAToVectorDataFilter<TVImage, TLabelImage, TMaskImage, TOutputVectorData> +::~PersistentConnectedComponentSegmentationOBIAToVectorDataFilter() +{ +} + +template<class TVImage, class TLabelImage, class TMaskImage, class TOutputVectorData> +typename PersistentConnectedComponentSegmentationOBIAToVectorDataFilter<TVImage, TLabelImage, TMaskImage, TOutputVectorData>::VectorDataPointerType +PersistentConnectedComponentSegmentationOBIAToVectorDataFilter<TVImage, TLabelImage, TMaskImage, TOutputVectorData> +::ProcessTile(const VectorImageType* inputImage) +{ + // Compute the mask + typename MaskMuParserFilterType::Pointer maskFilter; + maskFilter = MaskMuParserFilterType::New(); + maskFilter->SetInput(inputImage); + maskFilter->SetExpression(m_MaskExpression); + maskFilter->Update(); + + // Perform connected components segmentation + typename ConnectedComponentFilterType::Pointer connected = ConnectedComponentFilterType::New(); + connected->SetInput(inputImage); + connected->SetMaskImage(maskFilter->GetOutput()); + connected->GetFunctor().SetExpression(m_ConnectedComponentExpression); + connected->Update(); + + // Relabel connected component output + typename RelabelComponentFilterType::Pointer relabel = RelabelComponentFilterType::New(); + relabel->SetInput(connected->GetOutput()); + relabel->SetMinimumObjectSize(m_MinimumObjectSize); + relabel->Update(); + + //Attributes computation + // LabelImage to Label Map transformation + typename LabelImageToLabelMapFilterType::Pointer labelImageToLabelMap = LabelImageToLabelMapFilterType::New(); + labelImageToLabelMap->SetInput(relabel->GetOutput()); + labelImageToLabelMap->SetBackgroundValue(0); + labelImageToLabelMap->Update(); + + // shape attributes computation + typename ShapeLabelMapFilterType::Pointer shapeLabelMapFilter = ShapeLabelMapFilterType::New(); + shapeLabelMapFilter->SetInput(labelImageToLabelMap->GetOutput()); + shapeLabelMapFilter->SetReducedAttributeSet(false); + + // band stat attributes computation + typename RadiometricLabelMapFilterType::Pointer radiometricLabelMapFilter = RadiometricLabelMapFilterType::New(); + radiometricLabelMapFilter->SetInput(shapeLabelMapFilter->GetOutput()); + radiometricLabelMapFilter->SetFeatureImage(inputImage); + radiometricLabelMapFilter->SetReducedAttributeSet(true); + + // OBIA Filtering using shape and radiometric object characteristics + typename LabelObjectOpeningFilterType::Pointer opening = LabelObjectOpeningFilterType::New(); + opening->SetExpression(m_OBIAExpression); + opening->SetInput(radiometricLabelMapFilter->GetOutput()); + + // Transformation to VectorData + typename LabelMapToVectorDataFilterType::Pointer labelMapToVectorDataFilter = LabelMapToVectorDataFilterType::New(); + labelMapToVectorDataFilter->SetInput(opening->GetOutput()); + labelMapToVectorDataFilter->Update(); + + return labelMapToVectorDataFilter->GetOutput(); +} + +} // end namespace otb +#endif diff --git a/Testing/Code/OBIA/CMakeLists.txt b/Testing/Code/OBIA/CMakeLists.txt index 3a23e7a5077083108f7bcd17ab70c0773f0c477c..f43ae61bee5f0643e3f434b250f824b1b9f0a0b0 100644 --- a/Testing/Code/OBIA/CMakeLists.txt +++ b/Testing/Code/OBIA/CMakeLists.txt @@ -141,7 +141,22 @@ ADD_TEST(obTvVectorDataToLabelMapFilter ${OBIA_TESTS1} ${INPUTDATA}/vectorIOexample_gis_to_vec.shp ${TEMP}/vectordataToLabelMap.png) - +ADD_TEST(obTuStreamingConnectedComponentSegmentationOBIAToVectorDataFilterNew ${OBIA_TESTS1} + otbStreamingConnectedComponentSegmentationOBIAToVectorDataFilterNew) + +ADD_TEST(obTvStreamingConnectedComponentSegmentationOBIAToVectorDataFilter ${OBIA_TESTS1} + --compare-ogr ${NOTOL} + ${BASELINE_FILES}/obTvStreamingConnectedComponentSegmentationOBIAToVectorDataFilter.shp + ${TEMP}/obTvStreamingConnectedComponentSegmentationOBIAToVectorDataFilter.shp + otbStreamingConnectedComponentSegmentationOBIAToVectorDataFilter + ${INPUTDATA}/ROI_QB_MUL_4.tif + ${TEMP}/obTvStreamingConnectedComponentSegmentationOBIAToVectorDataFilter.shp + "((b1>80) * intensity>95)" + "distance<40" + 15 + "SHAPE_Elongation>8" + 5 ) + # OBIATests2 (need PQXX) IF(OTB_USE_PQXX) ADD_TEST(obTuLabelMapToGISTableFilterNew ${OBIA_TESTS2} @@ -194,6 +209,7 @@ otbShapeAttributesLabelMapFilterNew.cxx otbStatisticsAttributesLabelMapFilterNew.cxx otbVectorDataToLabelMapFilter.cxx otbVectorDataToLabelMapFilterNew.cxx +otbStreamingConnectedComponentOBIATest.cxx ) IF(OTB_USE_PQXX) diff --git a/Testing/Code/OBIA/otbOBIATests1.cxx b/Testing/Code/OBIA/otbOBIATests1.cxx index 166e9dd2974b7563c87d9840f0ebba0330a4ba9a..0499993bf96cfb74c05e9a006a820096f8357df3 100644 --- a/Testing/Code/OBIA/otbOBIATests1.cxx +++ b/Testing/Code/OBIA/otbOBIATests1.cxx @@ -51,4 +51,6 @@ REGISTER_TEST(otbShapeAttributesLabelMapFilterNew); REGISTER_TEST(otbStatisticsAttributesLabelMapFilterNew); REGISTER_TEST(otbVectorDataToLabelMapFilterNew); REGISTER_TEST(otbVectorDataToLabelMapFilter); +REGISTER_TEST(otbStreamingConnectedComponentSegmentationOBIAToVectorDataFilterNew); +REGISTER_TEST(otbStreamingConnectedComponentSegmentationOBIAToVectorDataFilter); } diff --git a/Testing/Code/OBIA/otbStreamingConnectedComponentOBIATest.cxx b/Testing/Code/OBIA/otbStreamingConnectedComponentOBIATest.cxx new file mode 100644 index 0000000000000000000000000000000000000000..20756c9118a910eec9127335f81bc650fb5d1689 --- /dev/null +++ b/Testing/Code/OBIA/otbStreamingConnectedComponentOBIATest.cxx @@ -0,0 +1,84 @@ +/*========================================================================= + + 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 "otbImage.h" +#include "otbVectorImage.h" +#include "otbVectorData.h" +#include "otbImageFileReader.h" +#include "otbVectorDataFileWriter.h" +#include "otbStreamingConnectedComponentSegmentationOBIAToVectorDataFilter.h" + +typedef float InputPixelType; +const unsigned int Dimension = 2; +typedef otb::VectorImage<InputPixelType, Dimension> InputVectorImageType; +typedef otb::Image<unsigned int, Dimension> LabelImageType; +typedef otb::Image<unsigned int, Dimension> MaskImageType; +typedef otb::ImageFileReader<InputVectorImageType> ReaderType; + +typedef otb::VectorData<double, Dimension> VectorDataType; +typedef VectorDataType::Pointer VectorDataPointerType; +typedef otb::VectorDataFileWriter<VectorDataType> VectorDataFileWriterType; +typedef VectorDataFileWriterType::Pointer VectorDataFileWriterPointerType; + +typedef otb::StreamingConnectedComponentSegmentationOBIAToVectorDataFilter + < InputVectorImageType, + LabelImageType, + MaskImageType, + VectorDataType > ConnectedComponentSegmentationOBIAToVectorDataFilterType; + +int otbStreamingConnectedComponentSegmentationOBIAToVectorDataFilterNew(int argc, char * argv[]) +{ + ConnectedComponentSegmentationOBIAToVectorDataFilterType::FilterType::Pointer connected + = ConnectedComponentSegmentationOBIAToVectorDataFilterType::FilterType::New(); + std::cout << connected << std::endl; + + return EXIT_SUCCESS; +} + +int otbStreamingConnectedComponentSegmentationOBIAToVectorDataFilter(int argc, char * argv[]) +{ + const char * inputFilename = argv[1]; + const char * outputFilename = argv[2]; + const char * maskexpression = argv[3]; + const char * segmentationexpression = argv[4]; + unsigned int minobjectsize = atoi(argv[5]); + const char * obiaexpression = argv[6]; + unsigned int nbstreams = atoi(argv[7]); + + ReaderType::Pointer reader = ReaderType::New(); + reader->SetFileName(inputFilename); + reader->UpdateOutputInformation(); + + ConnectedComponentSegmentationOBIAToVectorDataFilterType::FilterType::Pointer connected + = ConnectedComponentSegmentationOBIAToVectorDataFilterType::FilterType::New(); + connected->GetFilter()->SetInput(reader->GetOutput()); + + connected->GetFilter()->SetMaskExpression(maskexpression); + connected->GetFilter()->SetConnectedComponentExpression(segmentationexpression); + connected->GetFilter()->SetMinimumObjectSize(minobjectsize); + connected->GetFilter()->SetOBIAExpression(obiaexpression); + + connected->GetStreamer()->SetNumberOfDivisionsStrippedStreaming(nbstreams); + connected->Update(); + + VectorDataFileWriterPointerType vdwriter = VectorDataFileWriterType::New(); + vdwriter->SetInput(connected->GetFilter()->GetOutputVectorData()); + vdwriter->SetFileName(outputFilename); + vdwriter->Update(); + + return EXIT_SUCCESS; +}