From 455b98bc227fec53ccb04d4bcdabfa566b1a5a27 Mon Sep 17 00:00:00 2001 From: Julien Michel <julien.michel@c-s.fr> Date: Tue, 23 Oct 2007 11:59:33 +0000 Subject: [PATCH] Evolutions R&T --- ...bImageMultiSegmentationToRCC8GraphFilter.h | 1 + ...mageMultiSegmentationToRCC8GraphFilter.txx | 60 ++-- .../otbImageToImageRCC8Calculator.txx | 43 ++- .../otbPolygonToPolygonRCC8Calculator.h | 130 +++++++ .../otbPolygonToPolygonRCC8Calculator.txx | 319 ++++++++++++++++++ Code/SpatialReasoning/otbRCC8Graph.h | 30 +- Code/SpatialReasoning/otbRCC8Graph.txx | 46 +-- .../SpatialReasoning/otbRCC8GraphFileReader.h | 30 +- .../otbRCC8GraphFileReader.txx | 36 +- .../SpatialReasoning/otbRCC8GraphFileWriter.h | 17 - .../otbRCC8GraphFileWriter.txx | 29 -- Code/SpatialReasoning/otbRCC8VertexBase.h | 26 +- Code/SpatialReasoning/otbRCC8VertexBase.txx | 83 +++-- .../otbRCC8VertexWithCompacity.h | 8 +- .../otbRCC8VertexWithCompacity.txx | 18 +- 15 files changed, 640 insertions(+), 236 deletions(-) create mode 100644 Code/SpatialReasoning/otbPolygonToPolygonRCC8Calculator.h create mode 100644 Code/SpatialReasoning/otbPolygonToPolygonRCC8Calculator.txx diff --git a/Code/SpatialReasoning/otbImageMultiSegmentationToRCC8GraphFilter.h b/Code/SpatialReasoning/otbImageMultiSegmentationToRCC8GraphFilter.h index f49f5c58cb..8a95f91d6a 100644 --- a/Code/SpatialReasoning/otbImageMultiSegmentationToRCC8GraphFilter.h +++ b/Code/SpatialReasoning/otbImageMultiSegmentationToRCC8GraphFilter.h @@ -53,6 +53,7 @@ public: typedef typename OutputGraphType::Pointer OutputGraphPointerType; typedef typename OutputGraphType::VertexType VertexType; typedef typename VertexType::Pointer VertexPointerType; + typedef typename VertexType::PathType PathType; typedef typename OutputGraphType::VertexDescriptorType VertexDescriptorType; /** Knowledge enum typedef */ typedef typename OutputGraphType::RCC8ValueType RCC8ValueType; diff --git a/Code/SpatialReasoning/otbImageMultiSegmentationToRCC8GraphFilter.txx b/Code/SpatialReasoning/otbImageMultiSegmentationToRCC8GraphFilter.txx index d7192271f2..f8e03ff525 100644 --- a/Code/SpatialReasoning/otbImageMultiSegmentationToRCC8GraphFilter.txx +++ b/Code/SpatialReasoning/otbImageMultiSegmentationToRCC8GraphFilter.txx @@ -20,11 +20,13 @@ #include "otbImageMultiSegmentationToRCC8GraphFilter.h" #include "itkMinimumMaximumImageCalculator.h" -#include "otbImageToImageRCC8Calculator.h" +#include "otbPolygonToPolygonRCC8Calculator.h" #include "otbRCC8VertexIterator.h" #include "otbRCC8InEdgeIterator.h" #include "otbRCC8OutEdgeIterator.h" #include "itkProgressReporter.h" +#include "otbImageToEdgePathFilter.h" +#include "otbSimplifyPathListFilter.h" namespace otb { @@ -135,13 +137,20 @@ ImageMultiSegmentationToRCC8GraphFilter<TInputImage, TOutputGraph> // Ouptut graph pointer OutputGraphPointerType graph = this->GetOutput(); + + + // invert value vector RCC8ValueType invert[8]={OTB_RCC8_DC,OTB_RCC8_EC,OTB_RCC8_PO,OTB_RCC8_TPPI, OTB_RCC8_TPP,OTB_RCC8_NTPPI,OTB_RCC8_NTPP,OTB_RCC8_EQ}; // Some typedefs + typedef otb::ImageToEdgePathFilter<InputImageType,PathType> EdgeExtractionFilterType; + typedef otb::SimplifyPathListFilter<PathType> SimplifyPathFilterType; + typedef typename SimplifyPathFilterType::PathListType PathListType; + typedef itk::MinimumMaximumImageCalculator<InputImageType> MinMaxCalculatorType; - typedef ImageToImageRCC8Calculator<InputImageType> RCC8CalculatorType; + typedef PolygonToPolygonRCC8Calculator<PathType> RCC8CalculatorType; typedef RCC8VertexIterator<OutputGraphType> VertexIteratorType; typedef RCC8InEdgeIterator<OutputGraphType> InEdgeIteratorType; typedef RCC8OutEdgeIterator<OutputGraphType> OutEdgeIteratorType; @@ -164,18 +173,27 @@ ImageMultiSegmentationToRCC8GraphFilter<TInputImage, TOutputGraph> maxLabelVector.push_back(minMax->GetMaximum()); otbMsgDebugMacro(<<"Number of objects in image "<<segmentationImageIndex<<": " <<minMax->GetMaximum()); - - // Add the image to the segmentation image list of the output graph - graph->GetSegmentationImageList()->PushBack(it.Get()); // then for each region of the images for(PixelType label=1; label<=maxLabelVector.back();++label) { + typename PathListType::Pointer region = PathListType::New(); + typename EdgeExtractionFilterType::Pointer extraction = EdgeExtractionFilterType::New(); + extraction->SetInput(it.Get()); + extraction->SetForegroundValue(label); + extraction->Update(); + region->PushBack(extraction->GetOutput()); + typename SimplifyPathFilterType::Pointer simplifier = SimplifyPathFilterType::New(); + simplifier->SetInput(region); + simplifier->SetTolerance(0.1); + simplifier->Update(); + // Create a new vertex - VertexPointerType vertex = VertexType::New(); + VertexPointerType vertex = VertexType::New(); // Set its properties - vertex->SetSegmentationImageIndex(segmentationImageIndex); - vertex->SetObjectLabelInImage(label); + vertex->SetPath(simplifier->GetOutput()->GetNthElement(0)); + vertex->SetSegmentationLevel(segmentationImageIndex/2); + vertex->SetSegmentationType(segmentationImageIndex%2); // Put it in the graph graph->SetVertex(vertexIndex,vertex); vertexIndex++; @@ -194,23 +212,14 @@ ImageMultiSegmentationToRCC8GraphFilter<TInputImage, TOutputGraph> { for(vIt2.GoToBegin();!vIt2.IsAtEnd();++vIt2) { - // Get the segmentation images indexes - unsigned int source = vIt1.Get()->GetSegmentationImageIndex(); - unsigned int target = vIt2.Get()->GetSegmentationImageIndex(); - - // We do not examine each couple because of the RCC8 simetry - if(source<target) + //We do not examine each couple because of the RCC8 symmetry + if(vIt1.GetIndex()<vIt2.GetIndex()) { - // Get the labels of source and target - PixelType label1 = vIt1.Get()->GetObjectLabelInImage(); - PixelType label2 = vIt2.Get()->GetObjectLabelInImage(); - + // Compute the RCC8 relation typename RCC8CalculatorType::Pointer calc = RCC8CalculatorType::New(); - calc->SetInput1(segList->GetNthElement(source)); - calc->SetInsideValue1(label1); - calc->SetInput2(segList->GetNthElement(target)); - calc->SetInsideValue2(label2); + calc->SetPolygon1(vIt1.Get()->GetPath()); + calc->SetPolygon2(vIt2.Get()->GetPath()); RCC8ValueType value=OTB_RCC8_DC; // if the optimisations are activated @@ -269,7 +278,7 @@ ImageMultiSegmentationToRCC8GraphFilter<TInputImage, TOutputGraph> { // Else trigger the computation // (which will take the optimisation phase info into account) - calc->Update(); + calc->Compute(); value=calc->GetValue(); } // otbMsgDebugMacro(<<"RCC8GraphFilter: Leaving optimisation loop"); @@ -277,7 +286,7 @@ ImageMultiSegmentationToRCC8GraphFilter<TInputImage, TOutputGraph> // If the optimisations are not activated else { - calc->Update(); + calc->Compute(); value=calc->GetValue(); } m_Accumulator[value]+=1; @@ -289,12 +298,13 @@ ImageMultiSegmentationToRCC8GraphFilter<TInputImage, TOutputGraph> otbMsgDevMacro(<<"Adding edge: "<<vIt1.GetIndex()<<" -> "<<vIt2.GetIndex()<<": "<<value); graph->AddEdge(vIt1.GetIndex(),vIt2.GetIndex(),value); } - } + } progress.CompletedPixel(); progress.CompletedPixel(); } } } + template <class TInputImage, class TOutputGraph> void ImageMultiSegmentationToRCC8GraphFilter<TInputImage, TOutputGraph> diff --git a/Code/SpatialReasoning/otbImageToImageRCC8Calculator.txx b/Code/SpatialReasoning/otbImageToImageRCC8Calculator.txx index 5ad5d84173..82430a6c2b 100644 --- a/Code/SpatialReasoning/otbImageToImageRCC8Calculator.txx +++ b/Code/SpatialReasoning/otbImageToImageRCC8Calculator.txx @@ -29,6 +29,9 @@ #include "otbBinaryImageMinimalBoundingRegionCalculator.h" #include "otbMacro.h" +//TODELETE #include "otbImageFileWriter.h" +//TODELETE #include "itkCastImageFilter.h" + namespace otb { /** @@ -132,19 +135,27 @@ namespace otb region2=rc->GetRegion(); // otbMsgDebugMacro(<<"RCC8Calculator->ComputeMinimalRegion() Region1: index: "<<region1.GetIndex()<<" size: "<<region1.GetSize()); // otbMsgDebugMacro(<<"RCC8Calculator->ComputeMinimalRegion() Region2: index: "<<region2.GetIndex()<<" size: "<<region2.GetSize()); + + //TODELETE std::cout<<"RCC8Calculator->ComputeMinimalRegion() Region1: index: "<<region1.GetIndex()<<" size: "<<region1.GetSize()<<std::endl; + //TODELETE std::cout<<"RCC8Calculator->ComputeMinimalRegion() Region2: index: "<<region2.GetIndex()<<" size: "<<region2.GetSize()<<std::endl; + typename ImageType::SizeType size; typename ImageType::IndexType index; for(int i=0;i<ImageType::ImageDimension;i++) { - index[i]=std::max(region1.GetIndex()[i],region2.GetIndex()[i]); - int potSize = std::min(region1.GetIndex()[i]+region1.GetSize()[i], + index[i]=std::min(region1.GetIndex()[i],region2.GetIndex()[i]); + int potSize = std::max(region1.GetIndex()[i]+region1.GetSize()[i], region2.GetIndex()[i]+region2.GetSize()[i]); size[i]=(potSize-index[i]<0 ? 0 : potSize-index[i]); } region.SetIndex(index); region.SetSize(size); + region.PadByRadius(2); + region.Crop(image1->GetLargestPossibleRegion()); + region.Crop(image2->GetLargestPossibleRegion()); // otbMsgDebugMacro(<<"RCC8Calculator->ComputeMinimalRegion(): index: "<<index<<" size: "<<size); + //TODELETE std::cout<<"RCC8Calculator->ComputeMinimalRegion(): index: "<<index<<" size: "<<size<<std::endl; return region; } /** @@ -258,6 +269,7 @@ ImageToImageRCC8Calculator<TInputImage> typename InvertFilterType::Pointer invert = InvertFilterType::New(); typename AndFilterType::Pointer andFilter = AndFilterType::New(); /// The exterior is the inverted input image + invert->SetMaximum(true); invert->SetInput(m_BoolImage1); andFilter->SetInput1(m_BoolImage2); andFilter->SetInput2(invert->GetOutput()); @@ -275,17 +287,38 @@ ImageToImageRCC8Calculator<TInputImage> ImageToImageRCC8Calculator<TInputImage> ::ComputeInterExterBool(void) { - /// Definition of the filters used + /// Definition of the filters used typedef itk::InvertIntensityImageFilter<BoolImageType,BoolImageType> InvertFilterType; typedef itk::AndImageFilter<BoolImageType,BoolImageType,BoolImageType> AndFilterType; + //TODELETE typedef otb::Image<unsigned char,2> TmpImageType; + //TODELETE typedef itk::CastImageFilter<BoolImageType,TmpImageType> CastFilterType; + + //TODELETE typedef ImageFileWriter<TmpImageType> WriterType; /// Declaration and instantiation typename InvertFilterType::Pointer invert = InvertFilterType::New(); typename AndFilterType::Pointer andFilter = AndFilterType::New(); /// The exterior is the inverted input image + invert->SetMaximum(true); invert->SetInput(m_BoolImage2); + + //TODELETE typename CastFilterType::Pointer caster = CastFilterType::New(); + //TODELETE caster->SetInput(invert->GetOutput()); + //TODELETE typename WriterType::Pointer writer = WriterType::New(); +//TODELETE writer->SetFileName("invert.tif"); + //TODELETE writer->SetInput(caster->GetOutput()); +//TODELETE writer->Update(); + andFilter->SetInput1(m_BoolImage1); andFilter->SetInput2(invert->GetOutput()); andFilter->Update(); + + //TODELETE caster = CastFilterType::New(); + //TODELETE caster->SetInput(andFilter->GetOutput()); + //TODELETE writer = WriterType::New(); + //TODELETE writer->SetFileName("and.tif"); + //TODELETE writer->SetInput(caster->GetOutput()); + //TODELETE writer->Update(); + /// test if the intersection is empty or not return IsBoolImageNotEmpty(andFilter->GetOutput()); } @@ -414,6 +447,7 @@ ImageToImageRCC8Calculator<TInputImage> /// now edgeEdgeBool = ComputeEdgeEdgeBool(); // otbMsgDebugMacro(<<"RCC8Calculator->GenerateData(): edgeEdge "<<edgeEdgeBool); + //TODELETE std::cout<<"RCC8Calculator->GenerateData(): edgeEdge "<<edgeEdgeBool<<std::endl; /// Here comes the outside knowledge if(this->GetLevel1APrioriKnowledge()) { @@ -429,6 +463,7 @@ ImageToImageRCC8Calculator<TInputImage> // otbMsgDebugMacro(<<"RCC8Calculator->GenerateData(): interExter "<<interExterBool); } /// At this stage we can determine if the relation is of type NTPP + //TODELETE std::cout<<"RCC8Calculator->GenerateData(): interExter "<<interExterBool<<std::endl; if((!interExterBool)&&(!edgeEdgeBool)) { m_Value=OTB_RCC8_NTPP; @@ -449,11 +484,13 @@ ImageToImageRCC8Calculator<TInputImage> exterInterBool = ComputeExterInterBool(); // otbMsgDebugMacro(<<"RCC8Calculator->GenerateData(): ExterInter "<<exterInterBool); } + //TODELETE std::cout<<"RCC8Calculator->GenerateData(): ExterInter "<<exterInterBool<<std::endl; /// If it is not sufficient to compute the relation if(!ComputeRelation(edgeEdgeBool,interExterBool,exterInterBool)) { /// Compute the last boolean interInterBool = ComputeInterInterBool(); + //TODELETE std::cout<<"RCC8Calculator->GenerateData(): InterInter "<<interInterBool<<std::endl; // otbMsgDebugMacro(<<"RCC8Calculator->GenerateData(): InterInter "<<interInterBool); /// Which allow the full determination if ((interExterBool)&&(edgeEdgeBool)&&(exterInterBool)&&(!interInterBool)) diff --git a/Code/SpatialReasoning/otbPolygonToPolygonRCC8Calculator.h b/Code/SpatialReasoning/otbPolygonToPolygonRCC8Calculator.h new file mode 100644 index 0000000000..cee52a90f1 --- /dev/null +++ b/Code/SpatialReasoning/otbPolygonToPolygonRCC8Calculator.h @@ -0,0 +1,130 @@ +/*========================================================================= + + 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 _otbPolygonToPolygonRCC8Calculator_h +#define _otbPolygonToPolygonRCC8Calculator_h + +#include "itkObject.h" +#include "otbRCC8Value.h" +#include "otbImage.h" + +namespace otb +{ +/** + * \class PolygonToPolygonRCC8Calculator + * \brief This class compute the RCC8 relation between the regions from two segmentation images. + * + * The RCC8 system comes from qualitative spatial reasoning. + * It is a set of pairwise disjoint exhaustive relation between two closed region of space. + * There are 8 possible relations : + * DC: Disconnected + * EC: Externaly connected + * PO: Partial overlap + * TPP: Tangential proper part + * NTPP: Non tangential proper part + * TPPI: Tangential proper part inverse + * NTPPI: Non tangential proper part inverse + * EQ: Equivalence + * + * The goal of this class is to determine which of these 8 relations link the two inputs regions represented + * by the closed input path. Since this class will further be used iteratively on a possibly large set + * of regiosn, it is optimised : the decision is managed by a decision tree. + */ +template <class TInputPolygon> + class ITK_EXPORT PolygonToPolygonRCC8Calculator : public itk::Object +{ +public: + /** Standard class typedefs. */ + typedef PolygonToPolygonRCC8Calculator Self; + typedef itk::Object 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(PolygonToPolygonRCC8Calculator,Object); + /** Types definitions for the input image. */ + typedef TInputPolygon PolygonType; + typedef typename PolygonType::Pointer PolygonPointerType; + typedef typename PolygonType::ConstPointer PolygonConstPointerType; + typedef typename PolygonType::VertexListType VertexListType; + typedef typename PolygonType::ContinuousIndexType ContinuousIndexType; + typedef typename VertexListType::ConstIterator VertexListIteratorType; + typedef std::vector<bool> BoolVectorType; + + /** RCC8 values type */ + typedef RCC8Value RCC8ValueType; + + /** + * Get the RCC8 relation. + * \return The RCC8 relation value. + */ + RCC8ValueType GetValue(void); + + /** Set external knowledge to help the decision process */ + itkSetMacro(Level1APrioriKnowledge,bool); + itkSetMacro(Level3APrioriKnowledge,bool); + itkGetMacro(Level1APrioriKnowledge,bool); + itkGetMacro(Level3APrioriKnowledge,bool); + + itkSetObjectMacro(Polygon1,PolygonType); + itkSetObjectMacro(Polygon2,PolygonType); + itkGetObjectMacro(Polygon1,PolygonType); + itkGetObjectMacro(Polygon2,PolygonType); + + /** Main computation method */ + void Compute(void); + + virtual bool ComputeRelation(bool edgeEdgeBool, bool interExterBool, bool exterInterBool); + + virtual bool ComputeInterExter(PolygonPointerType path1,PolygonPointerType path2); + + virtual bool ComputeEdgeEdge(PolygonPointerType path1, PolygonPointerType path2); + + virtual bool ComputeInterInter(PolygonPointerType path1, PolygonPointerType path2); + + + protected: + /** Constructor */ + PolygonToPolygonRCC8Calculator(); + /** Destructor */ + virtual ~PolygonToPolygonRCC8Calculator() {}; + /** PrintSelf method */ + void PrintSelf(std::ostream& os, itk::Indent indent) const; + + private: + /** The RCC8 relation value */ + RCC8ValueType m_Value; + /** Decision tree Level 1 A priori knowledge */ + bool m_Level1APrioriKnowledge; + /** Decision tree Level 3 A priori knowledge */ + bool m_Level3APrioriKnowledge; + /** Polygon of region 1 */ + PolygonPointerType m_Polygon1; + /** Polygon of region 2 */ + PolygonPointerType m_Polygon2; + /** Epsilon */ + double m_Epsilon; + +}; +} // end namespace otb + +#ifndef OTB_MANUAL_INSTANTIATION +#include "otbPolygonToPolygonRCC8Calculator.txx" +#endif + +#endif diff --git a/Code/SpatialReasoning/otbPolygonToPolygonRCC8Calculator.txx b/Code/SpatialReasoning/otbPolygonToPolygonRCC8Calculator.txx new file mode 100644 index 0000000000..a8a26e32ab --- /dev/null +++ b/Code/SpatialReasoning/otbPolygonToPolygonRCC8Calculator.txx @@ -0,0 +1,319 @@ +/*========================================================================= + + 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 _otbPolygonToPolygonRCC8Calculator_txx +#define _otbPolygonToPolygonRCC8Calculator_txx + +#include "otbPolygonToPolygonRCC8Calculator.h" +#include "otbMacro.h" + +namespace otb +{ +/** + * Constructor + */ +template<class TInputPolygon> +PolygonToPolygonRCC8Calculator<TInputPolygon> +::PolygonToPolygonRCC8Calculator() +{ + m_Value = OTB_RCC8_DC; + m_Level1APrioriKnowledge=false; + m_Level3APrioriKnowledge=false; + } +/** + * Get the RCC8 relation. + * \return The RCC8 relation value. + */ +template <class TInputPolygon> +typename PolygonToPolygonRCC8Calculator<TInputPolygon> +::RCC8ValueType +PolygonToPolygonRCC8Calculator<TInputPolygon> +::GetValue(void) +{ + return m_Value; +} + +template<class TInputPolygon> +void +PolygonToPolygonRCC8Calculator<TInputPolygon> +::Compute(void) +{ + bool edgeEdgeBool,interExterBool,exterInterBool,interInterBool; + /// The boolean edgeEdge is needed in each case, so it si computed + /// now + edgeEdgeBool = ComputeEdgeEdge(m_Polygon1,m_Polygon2); + + //std::cout<<"EdgeEdge: "<<edgeEdgeBool<<std::endl; + + if(this->GetLevel1APrioriKnowledge()) + { + interExterBool=true; + } + else + { + /// Else it must be computed + interExterBool = ComputeInterExter(m_Polygon1,m_Polygon2); + } + + //std::cout<<"InterExter: "<<interExterBool<<std::endl; + + /// At this stage we can determine if the relation is of type NTPP + if((!interExterBool)&&(!edgeEdgeBool)) + { + m_Value=OTB_RCC8_NTPP; + } + else + { + /// If not, we must consider the intersection between exterior + if(this->GetLevel3APrioriKnowledge()) + { + /// If the Level3APRioriKnowledge flag is set, this boolean + /// can be determined from the two others + exterInterBool=true; + } + else + { + /// Else it must be computed + exterInterBool = ComputeInterExter(m_Polygon2,m_Polygon1); + } + + //std::cout<<"ExterInter: "<<exterInterBool<<std::endl; + + /// If it is not sufficient to compute the relation + if(!ComputeRelation(edgeEdgeBool,interExterBool,exterInterBool)) + { + /// Compute the last boolean + interInterBool = ComputeInterInter(m_Polygon1,m_Polygon2); + + //std::cout<<"InterInter: "<<interInterBool<<std::endl; + + /// Which allow the full determination + if ((interExterBool)&&(edgeEdgeBool)&&(exterInterBool)&&(!interInterBool)) + { + m_Value=OTB_RCC8_EC; + } + else + { + m_Value=OTB_RCC8_PO; + } + } + } +} +template<class TInputPolygon> +bool +PolygonToPolygonRCC8Calculator<TInputPolygon> +::ComputeRelation(bool edgeEdgeBool, bool interExterBool, bool exterInterBool) +{ + // This decision process is based on a decision tree + if ((!interExterBool)&&(edgeEdgeBool)&&(!exterInterBool)) + { + m_Value=OTB_RCC8_EQ; + return true; + } + else if ((!interExterBool)&&(edgeEdgeBool)&&(exterInterBool)) + { + m_Value=OTB_RCC8_TPP; + return true; + } + else if ((interExterBool)&&(!edgeEdgeBool)&&(!exterInterBool)) + { + m_Value=OTB_RCC8_NTPPI; + return true; + } + else if ((interExterBool)&&(!edgeEdgeBool)&&(exterInterBool)) + { + m_Value=OTB_RCC8_DC; + return true; + } + else if ((interExterBool)&&(edgeEdgeBool)&&(!exterInterBool)) + { + m_Value=OTB_RCC8_TPPI; + return true; + } + else + { + return false; + } +} + +template<class TInputPolygon> +bool +PolygonToPolygonRCC8Calculator<TInputPolygon> +::ComputeInterExter(PolygonPointerType polygon1, PolygonPointerType polygon2) +{ + bool resp = false; + VertexListIteratorType it = polygon1->GetVertexList()->Begin(); + VertexListIteratorType it_end = polygon1->GetVertexList()->End(); + + ContinuousIndexType current = it.Value(); + ContinuousIndexType first = current; + bool isInside = polygon2->IsInside(current); + bool firstIsInside = isInside; + bool isExterior = !isInside && !polygon2->IsOnEdge(current); + + //std::cout<<current<<" is inside: "<<isInside<<std::endl; + //std::cout<<current<<" is on edge: "<<polygon2->IsOnEdge(current)<<std::endl; + + unsigned int index = 0; + if(isExterior) + { + resp = true; + } + ++it; + while (!resp && it != it_end) + { + bool nextIsInside = polygon2->IsInside(it.Value()); + + if (isInside && nextIsInside) + { + //std::cout<<current<<" is inside and "<<it.Value()<<" is inside, nb crossings: "<<polygon2->NbCrossing(current,it.Value())<<std::endl; + resp = polygon2->NbCrossing(current,it.Value()) >0; + } + current = it.Value(); + isInside = nextIsInside; + isExterior = !isInside && !polygon2->IsOnEdge(current) ; + //std::cout<<current<<" is inside: "<<isInside<<std::endl; + //std::cout<<current<<" is on edge: "<<polygon2->IsOnEdge(current)<<std::endl; + if(isExterior) + { + resp = true; + } + + ++index; + ++it; + } + + if(!resp && isInside && firstIsInside) + { + resp = polygon2->NbCrossing(current,first)>0; + //std::cout<<current<<" is inside and "<<first<<" is inside, nb crossings: "<<polygon2->NbCrossing(current,first)<<std::endl; + } + + return resp; +} + + +template<class TInputPolygon> +bool +PolygonToPolygonRCC8Calculator<TInputPolygon> +::ComputeInterInter(PolygonPointerType polygon1, PolygonPointerType polygon2) +{ + bool resp = false; + VertexListIteratorType it = polygon1->GetVertexList()->Begin(); + VertexListIteratorType it_end = polygon1->GetVertexList()->End(); + ContinuousIndexType current = it.Value(); + ContinuousIndexType first = current; + bool currentIsInside = polygon2->IsInside(current); + bool firstIsInside = currentIsInside; + + if(currentIsInside) + { + resp = true; + } + ++it; + while (!resp && it != it_end) + { + bool nextIsInside = polygon2->IsInside(it.Value()); + + if (!currentIsInside && !nextIsInside && !polygon2->IsOnEdge(current) && !polygon2->IsOnEdge(it.Value())) + { + unsigned int nbCrossings = polygon2->NbCrossing(current,it.Value()); + + resp = nbCrossings>0; + } + currentIsInside =nextIsInside; + current = it.Value(); + + if(currentIsInside) + { + resp = true; + } + ++it; + } + + if (!resp && !currentIsInside && !firstIsInside && !polygon2->IsOnEdge(current) && !polygon2->IsOnEdge(first)) + { + unsigned int nbCrossings = polygon2->NbCrossing(current,first); + + resp = nbCrossings>0; + } + return resp; +} +template<class TInputPolygon> +bool +PolygonToPolygonRCC8Calculator<TInputPolygon> +::ComputeEdgeEdge(PolygonPointerType polygon1, PolygonPointerType polygon2) +{ + bool resp = false; + VertexListIteratorType it = polygon1->GetVertexList()->Begin(); + VertexListIteratorType it_end = polygon1->GetVertexList()->End(); + + ContinuousIndexType current = it.Value(); + resp = polygon2->IsOnEdge(current); + //std::cout<<"IsOnEdge: "<<current<<": "<<polygon2->IsOnEdge(current)<<std::endl; + ContinuousIndexType first = current; + ++it; + + while (! resp && it != it_end) + { + if(polygon2->NbTouching(current,it.Value())>0) + { + resp = true; + //std::cout<<"NbCrossing: "<<current<<" -> "<<it.Value()<<": "<<polygon2->NbCrossing(current,it.Value())<<std::endl; + } + if(polygon2->NbCrossing(current,it.Value())>0) + { + resp = true; + //std::cout<<"NbTouching: "<<current<<" -> "<<it.Value()<<": "<<polygon2->NbTouching(current,it.Value())<<std::endl; + } + current = it.Value(); + + if(polygon2->IsOnEdge(current)) + { + resp = true; + //std::cout<<"IsOnEdge: "<<current<<": "<<polygon2->IsOnEdge(current)<<std::endl; + } + ++it; + } + if(!resp && polygon2->NbTouching(current,first)>0) + { + resp = true; + //std::cout<<"NbCrossing: "<<current<<" -> "<<first<<": "<<polygon2->NbCrossing(current,first)<<std::endl; + } + if(polygon2->NbCrossing(current,first)>0) + { + resp = true; + //std::cout<<"NbTouching: "<<current<<" -> "<<first<<": "<<polygon2->NbTouching(current,first)<<std::endl; + } + + return resp; +} +/** + * PrintSelf method + */ +template<class TInputPolygon> +void +PolygonToPolygonRCC8Calculator<TInputPolygon> +::PrintSelf( std::ostream& os,itk::Indent indent ) const +{ + Superclass::PrintSelf(os,indent); +} +} // end namespace otb + +#endif + + diff --git a/Code/SpatialReasoning/otbRCC8Graph.h b/Code/SpatialReasoning/otbRCC8Graph.h index 5f0995eaeb..5a74837c7f 100644 --- a/Code/SpatialReasoning/otbRCC8Graph.h +++ b/Code/SpatialReasoning/otbRCC8Graph.h @@ -30,15 +30,7 @@ namespace otb /** * \class RCC8Graph * \brief This class is a data structure designed to store RCC8 Graph - * computed from a pyramidal segmentation. It is divided in two - * components : - * An internal graph object which uses the boost graph library - * implementation, using RCC8GraphEdgeProperties for edges properties - * and RCC8GraphVerticesProperties for vertices properties. - * A list of segmentation images resulting from the pyramidal - * segmentation. These use a label pixel type, and each region is - * referenced from in the graph vertex properties via its - * RegionIndexInImage parameter. + * computed from a pyramidal segmentation. * * A batch of boost operation has been embedded in order to provide * basic functionnality such as adding a new edge, or retrieving the @@ -48,7 +40,7 @@ namespace otb * applications, one should provide a patch for this class including * the new functionnalities, for consistency reason. */ -template <class TVertex, class TSegmentationImage = Image< typename TVertex::LabelType,2> > +template <class TVertex> class ITK_EXPORT RCC8Graph : public itk::DataObject { @@ -77,19 +69,9 @@ class ITK_EXPORT RCC8Graph : typedef typename InternalGraphType::vertex_descriptor VertexDescriptorType; typedef typename InternalGraphType::edge_descriptor EdgeDescriptorType; - /** Segmentation images typedef */ - typedef TSegmentationImage SegmentationImageType; - typedef typename SegmentationImageType::Pointer SegmentationImagePointerType; - typedef ImageList<SegmentationImageType> SegmentationImageListType; - typedef typename SegmentationImageListType::Pointer SegmentationImageListPointerType; - /** Getters and Setters for the number of vertices */ itkSetMacro(NumberOfVertices,unsigned int); itkGetConstReferenceMacro(NumberOfVertices,unsigned int); - - /** Get and set the internal image list */ - itkSetObjectMacro(SegmentationImageList,SegmentationImageListType); - itkGetObjectMacro(SegmentationImageList,SegmentationImageListType); /** * Return the internal boost graph object. @@ -126,11 +108,7 @@ class ITK_EXPORT RCC8Graph : * /return The number of edges. */ unsigned int GetNumberOfEdges(void); - /** - * Get the number of segmentation images - * \return the number of segmentation images - */ - unsigned int GetNumberOfSegmentationImages(void); + protected: /** Constructor */ RCC8Graph(); @@ -150,8 +128,6 @@ private: unsigned int m_NumberOfVertices; /** Internal representation using the boost graph library */ InternalGraphType m_Graph; - /** The segmentation image list associated with the graph */ - SegmentationImageListPointerType m_SegmentationImageList; }; } // end namespace otb diff --git a/Code/SpatialReasoning/otbRCC8Graph.txx b/Code/SpatialReasoning/otbRCC8Graph.txx index 6fad57a23e..83cfb5d10c 100644 --- a/Code/SpatialReasoning/otbRCC8Graph.txx +++ b/Code/SpatialReasoning/otbRCC8Graph.txx @@ -23,21 +23,20 @@ namespace otb /** * Constructor */ - template <class TVertex, class TSegmentationImage> - RCC8Graph<TVertex, TSegmentationImage> + template <class TVertex> + RCC8Graph<TVertex> ::RCC8Graph() { m_NumberOfVertices = 0; - m_SegmentationImageList = SegmentationImageListType::New(); }; /** * since the number of vertices is mandatory to instantiate the * internal boost representation, the build method has to be called * once this parameter is set. */ - template <class TVertex, class TSegmentationImage> + template <class TVertex> void - RCC8Graph<TVertex, TSegmentationImage> + RCC8Graph<TVertex> ::Build(void) { this->Initialize(m_NumberOfVertices-1); @@ -46,9 +45,9 @@ namespace otb * Initialize a range of vertex. * \param num The index of the last vertices to intialize. */ - template <class TVertex, class TSegmentationImage> + template <class TVertex> void - RCC8Graph<TVertex, TSegmentationImage> + RCC8Graph<TVertex> ::Initialize( unsigned int num) { for(unsigned int i = boost::num_vertices(m_Graph); i<=num;i++) @@ -63,9 +62,9 @@ namespace otb * \param index The index of the vertex in the graph. * \param vertex The vertex to set. */ - template<class TVertex, class TSegmentationImage> + template<class TVertex> void - RCC8Graph<TVertex, TSegmentationImage> + RCC8Graph<TVertex> ::SetVertex(unsigned int index, VertexPointerType vertex) { if(index>=m_NumberOfVertices) @@ -81,10 +80,10 @@ namespace otb * \param index The index of the vertex in the graph * \return The vertex. */ - template <class TVertex, class TSegmentationImage> - typename RCC8Graph<TVertex, TSegmentationImage> + template <class TVertex> + typename RCC8Graph<TVertex> ::VertexPointerType - RCC8Graph<TVertex, TSegmentationImage> + RCC8Graph<TVertex> ::GetVertex(unsigned int index) { VertexDescriptorType v = *boost::vertices(m_Graph).first; @@ -96,9 +95,9 @@ namespace otb * \param index2 The index of the target vertex. * \param r The rcc8 value associated to the edge. */ - template <class TVertex, class TSegmentationImage> + template <class TVertex> void - RCC8Graph<TVertex, TSegmentationImage> + RCC8Graph<TVertex> ::AddEdge(unsigned int index1, unsigned int index2, RCC8ValueType r) { EdgeDescriptorType e = boost::add_edge(index1,index2,m_Graph).first; @@ -110,30 +109,19 @@ namespace otb * Get number of edges * /return The number of edges. */ - template <class TVertex, class TSegmentationImage> + template <class TVertex> unsigned int - RCC8Graph<TVertex, TSegmentationImage> + RCC8Graph<TVertex> ::GetNumberOfEdges(void) { return num_edges(m_Graph); } - /** - * Get the number of segmentation images - * \return the number of segmentation images - */ - template <class TVertex, class TSegmentationImage> - unsigned int - RCC8Graph<TVertex, TSegmentationImage> - ::GetNumberOfSegmentationImages(void) - { - return m_SegmentationImageList->Size(); - } /** * PrintSelf method */ - template <class TVertex, class TSegmentationImage> + template <class TVertex> void - RCC8Graph<TVertex, TSegmentationImage> + RCC8Graph<TVertex> ::PrintSelf( std::ostream& os,itk::Indent indent ) const { Superclass::PrintSelf(os,indent); diff --git a/Code/SpatialReasoning/otbRCC8GraphFileReader.h b/Code/SpatialReasoning/otbRCC8GraphFileReader.h index 878c84365b..047252695d 100644 --- a/Code/SpatialReasoning/otbRCC8GraphFileReader.h +++ b/Code/SpatialReasoning/otbRCC8GraphFileReader.h @@ -21,8 +21,6 @@ #include "otbRCC8GraphSource.h" #include "itkExceptionObject.h" -#include "otbImageFileReader.h" - namespace otb { /** \class RCC8GraphFileReaderException @@ -57,15 +55,6 @@ public: * and ParseVertex. The ParseVertex use builds an AttributesMap and pass it to a new * vertex. * - * The flag ReadSegmentationImages enable or disable the reading of the segmentation images. - * If this is enabled, the RCC8GraphFileReader will look for image files with the same name - * than the graph filename, concatenated with the segmentation image index, and the image extension. - * - * For instance, if the graph file is "graph.dot", and the image extension "tif", and if the graph comes - * from 6 segmentations image (information extracted from the Vertices properties), the reader will look for - * image files named graph1.tif, graph2.tif ..., graph6.tif. If one of the segmentation image is missing, none of - * them are loaded into the graph object output. - * * \sa RCC8GraphFileWriter * \sa RCC8Graph */ @@ -88,25 +77,11 @@ public: typedef typename OutputGraphType::VertexType VertexType; typedef typename VertexType::Pointer VertexPointerType; typedef typename OutputGraphType::RCC8ValueType RCC8ValueType; - typedef typename OutputGraphType::SegmentationImageType SegmentationImageType; - typedef typename OutputGraphType::SegmentationImagePointerType SegmentationImagePointerType; - typedef typename OutputGraphType::SegmentationImageListType SegmentationImageListType; - typedef typename OutputGraphType::SegmentationImageListPointerType SegmentationImageListPointerType; - typedef ImageFileReader<SegmentationImageType> SegmentationImageReaderType; - typedef typename SegmentationImageReaderType::Pointer SegmentationImageReaderPointerType; /** Set the filename */ itkSetStringMacro(FileName); /** Get the filename */ itkGetStringMacro(FileName); - /** Flag to enable/Disable the reading of segmentation images */ - itkSetMacro(ReadSegmentationImages,bool); - itkGetMacro(ReadSegmentationImages,bool); - itkBooleanMacro(ReadSegmentationImages); - /** Set the segmentation image extension */ - itkSetStringMacro(ImageExtension); - /** Get the segmentation image extension */ - itkGetStringMacro(ImageExtension); protected: /** Constructor */ @@ -125,14 +100,13 @@ protected: * \param line The line to parse. */ void ParseVertex(std::string line); + /** PrintSelf method */ virtual void PrintSelf(std::ostream& os, itk::Indent indent) const; - + private: /** File name */ std::string m_FileName; - std::string m_ImageExtension; - bool m_ReadSegmentationImages; }; } #ifndef OTB_MANUAL_INSTANTIATION diff --git a/Code/SpatialReasoning/otbRCC8GraphFileReader.txx b/Code/SpatialReasoning/otbRCC8GraphFileReader.txx index e522529b95..fb58d49ccc 100644 --- a/Code/SpatialReasoning/otbRCC8GraphFileReader.txx +++ b/Code/SpatialReasoning/otbRCC8GraphFileReader.txx @@ -34,8 +34,6 @@ RCC8GraphFileReader<TOutputGraph> ::RCC8GraphFileReader() { m_FileName=""; - m_ImageExtension=".tif"; - m_ReadSegmentationImages = true; } /** * Destructor @@ -98,6 +96,7 @@ RCC8GraphFileReader<TOutputGraph> vertex->SetAttributesMap(attr); this->GetOutput()->SetVertex(index,vertex); } + /** * Generate data method */ @@ -106,7 +105,6 @@ void RCC8GraphFileReader<TOutputGraph> ::GenerateData() { - otbMsgDevMacro(<<"RCC8GraphFileWriter: Call to the GenerateData method"); std::ifstream fin; std::string line; @@ -141,38 +139,6 @@ RCC8GraphFileReader<TOutputGraph> } } fin.close(); - - // if the reading of the segmentation images is enabled - if(m_ReadSegmentationImages) - { - unsigned int nImages = 0; - // first find the number of segmentation images to look for - RCC8VertexIterator<OutputGraphType> it(this->GetOutput()); - for(it.GoToBegin();!it.IsAtEnd();++it) - { - if(nImages<it.Get()->GetSegmentationImageIndex()) - { - nImages=it.Get()->GetSegmentationImageIndex(); - } - } - nImages = nImages+1; - std::string prefix = m_FileName.substr(0,m_FileName.length()-4); - - itk::OStringStream oss; - - // then read the images - for(unsigned int i=1;i<=nImages;++i) - { - oss.str(""); - oss<<prefix<<i<<m_ImageExtension; - - SegmentationImageReaderPointerType reader = SegmentationImageReaderType::New(); - reader->SetFileName(oss.str().c_str()); - // may be supressed - reader->Update(); - this->GetOutput()->GetSegmentationImageList()->PushBack(reader->GetOutput()); - } - } } /** * PrintSelf method diff --git a/Code/SpatialReasoning/otbRCC8GraphFileWriter.h b/Code/SpatialReasoning/otbRCC8GraphFileWriter.h index 5325c5a424..6d074f7572 100644 --- a/Code/SpatialReasoning/otbRCC8GraphFileWriter.h +++ b/Code/SpatialReasoning/otbRCC8GraphFileWriter.h @@ -21,7 +21,6 @@ #include "itkProcessObject.h" #include "itkExceptionObject.h" #include "otbRCC8Graph.h" -#include "otbImageFileWriter.h" namespace otb { @@ -83,23 +82,11 @@ public: typedef typename InputGraphType::VertexDescriptorType VertexDescriptorType; typedef typename InputGraphType::RCC8ValueType RCC8ValueType; typedef typename VertexType::AttributesMapType AttributesMapType; - typedef typename InputGraphType::SegmentationImageType SegmentationImageType; - typedef typename SegmentationImageType::Pointer SegmentationImagePointerType; - typedef ImageFileWriter<SegmentationImageType> SegmentationImageWriterType; - typedef typename SegmentationImageWriterType::Pointer SegmentationImageWriterPointerType; /** Set the filename */ itkSetStringMacro(FileName); /** Get the filename */ itkGetStringMacro(FileName); - /** Set the segmentation images suffix */ - itkSetStringMacro(ImageExtension); - /** Get the segmentation images suffix */ - itkGetStringMacro(ImageExtension); - /** Wether to write segmentation images or not */ - itkSetMacro(WriteSegmentationImages,bool); - itkGetMacro(WriteSegmentationImages,bool); - itkBooleanMacro(WriteSegmentationImages); /** * Set the input graph. * \param inputGraph The graph to write. @@ -154,10 +141,6 @@ protected: private: /** Filename of the graph file to write */ std::string m_FileName; - /** Wether to write segmentation images or not */ - bool m_WriteSegmentationImages; - /** The segmentation images suffix */ - std::string m_ImageExtension; }; } // namespace otb diff --git a/Code/SpatialReasoning/otbRCC8GraphFileWriter.txx b/Code/SpatialReasoning/otbRCC8GraphFileWriter.txx index 69bd272c7b..597ab592f9 100644 --- a/Code/SpatialReasoning/otbRCC8GraphFileWriter.txx +++ b/Code/SpatialReasoning/otbRCC8GraphFileWriter.txx @@ -35,8 +35,6 @@ RCC8GraphFileWriter<TInputGraph> { this->SetNumberOfRequiredInputs(1); m_FileName = ""; - m_ImageExtension = ".tif"; - m_WriteSegmentationImages = true; } /** * Destructor @@ -150,16 +148,10 @@ RCC8GraphFileWriter<TInputGraph> out<<"digraph G {"<<std::endl; // For each vertex in the graph - unsigned int maxSegImageIndex = 0; - VertexIteratorType vIt(input); for(vIt.GoToBegin();!vIt.IsAtEnd();++vIt) { this->WriteVertex(out,vIt.GetIndex(),vIt.Get()); - if(maxSegImageIndex<vIt.Get()->GetSegmentationImageIndex()) - { - maxSegImageIndex = vIt.Get()->GetSegmentationImageIndex(); - } } // For each edge in the graph @@ -176,27 +168,6 @@ RCC8GraphFileWriter<TInputGraph> // Close the file out.close(); - - // Write the segmentation images - if(m_WriteSegmentationImages) - { - - std::string prefix = m_FileName.substr(0,m_FileName.length()-4); - - itk::OStringStream oss; - - // then read the images - for(unsigned int i=1;i<=maxSegImageIndex+1;++i) - { - oss.str(""); - oss<<prefix<<i<<m_ImageExtension; - - SegmentationImageWriterPointerType writer = SegmentationImageWriterType::New(); - writer->SetFileName(oss.str().c_str()); - writer->SetInput(this->GetInput()->GetSegmentationImageList()->GetNthElement(i-1)); - writer->Update(); - } - } } /** * Write an edge to file. diff --git a/Code/SpatialReasoning/otbRCC8VertexBase.h b/Code/SpatialReasoning/otbRCC8VertexBase.h index 42a7abe763..988ccc7b7e 100644 --- a/Code/SpatialReasoning/otbRCC8VertexBase.h +++ b/Code/SpatialReasoning/otbRCC8VertexBase.h @@ -31,7 +31,7 @@ namespace otb * * \sa RCC8Graph, RCC8Edge */ -template <class TLabel> +template <class TPath> class ITK_EXPORT RCC8VertexBase : public itk::DataObject { @@ -46,17 +46,21 @@ class ITK_EXPORT RCC8VertexBase /** Run-time type information (and related methods). */ itkTypeMacro(RCC8VertexBase,DataObject); /** Input image associated typedefs*/ - typedef TLabel LabelType; + typedef TPath PathType; + typedef typename PathType::Pointer PathPointerType; + typedef typename PathType::ContinuousIndexType ContinuousIndexType; /** char* vector attributes */ typedef std::map<std::string,std::string> AttributesMapType; /** Segmentation image index accessors */ - itkGetMacro(SegmentationImageIndex,unsigned int); - itkSetMacro(SegmentationImageIndex,unsigned int); + itkGetMacro(SegmentationLevel,unsigned int); + itkSetMacro(SegmentationLevel,unsigned int); + itkGetMacro(SegmentationType,bool); + itkSetMacro(SegmentationType,bool); /** Object label in image accessor */ - itkGetMacro(ObjectLabelInImage,LabelType); - itkSetMacro(ObjectLabelInImage,LabelType); + itkGetObjectMacro(Path,PathType); + itkSetObjectMacro(Path,PathType); /** * Set the VertexBase attributes from the attributes vector. * \param attributes The vector containing the parsed attributes. @@ -77,10 +81,12 @@ protected: void PrintSelf(std::ostream& os, itk::Indent indent) const; private: - /** The segmentation image index */ - unsigned int m_SegmentationImageIndex; - /** The label of the object in the segmentation image */ - LabelType m_ObjectLabelInImage; + /** The segmentation level */ + unsigned int m_SegmentationLevel; + /** True if bright details, false otherwise */ + bool m_SegmentationType; + /** The path of the edge of the region */ + PathPointerType m_Path; }; } // end namespace otb #ifndef OTB_MANUAL_INSTANTIATION diff --git a/Code/SpatialReasoning/otbRCC8VertexBase.txx b/Code/SpatialReasoning/otbRCC8VertexBase.txx index 9fcb80d967..c0ae5c7d18 100644 --- a/Code/SpatialReasoning/otbRCC8VertexBase.txx +++ b/Code/SpatialReasoning/otbRCC8VertexBase.txx @@ -25,55 +25,98 @@ namespace otb /** * Constructor */ -template <class TLabel> -RCC8VertexBase<TLabel> +template <class TPath> +RCC8VertexBase<TPath> ::RCC8VertexBase() { - m_SegmentationImageIndex=0; - m_ObjectLabelInImage=0; + m_SegmentationLevel=0; + m_SegmentationType= true; + m_Path = PathType::New(); + m_Path->Initialize(); } /** * Set the VertexBase attributes from the attributes vector. * \param attributes The vector containing the parsed attributes. */ -template <class TLabel> +template <class TPath> void -RCC8VertexBase<TLabel> +RCC8VertexBase<TPath> ::SetAttributesMap(AttributesMapType attributes) { - m_SegmentationImageIndex=static_cast<unsigned int>(atoi(attributes["SegmentationImageIndex"].c_str())); - m_ObjectLabelInImage=static_cast<LabelType>(atof(attributes["ObjectLabelInImage"].c_str())); + m_SegmentationLevel=static_cast<unsigned int>(atoi(attributes["SegmentationLevel"].c_str())); + m_SegmentationType=static_cast<bool>(atoi(attributes["SegmentationType"].c_str())); + unsigned int nbPoints =static_cast<unsigned int>(atoi(attributes["NumberOfPointsInPath"].c_str())); + + itk::OStringStream oss; + + m_Path = PathType::New(); + m_Path->Initialize(); + + for(unsigned int i = 0;i<nbPoints;++i) + { + ContinuousIndexType newPoint; + oss<<"P"<<i<<"x"; + newPoint[0]=atof(attributes[oss.str()].c_str()); + oss.str(""); + oss<<"P"<<i<<"y"; + newPoint[1]=atof(attributes[oss.str()].c_str()); + oss.str(""); + m_Path->AddVertex(newPoint); + } } /** * Get an attributes vector representing the VertexBase attributes. * \return The attributes vector */ -template <class TLabel> -typename RCC8VertexBase<TLabel>::AttributesMapType -RCC8VertexBase<TLabel> +template <class TPath> +typename RCC8VertexBase<TPath>::AttributesMapType +RCC8VertexBase<TPath> ::GetAttributesMap(void) { - std::stringstream oss; + itk::OStringStream oss; AttributesMapType results; - oss<<m_SegmentationImageIndex; - results["SegmentationImageIndex"]=oss.str(); + oss<<m_SegmentationLevel; + results["SegmentationLevel"]=oss.str(); oss.str(""); - oss<<static_cast<unsigned int>(m_ObjectLabelInImage); - results["ObjectLabelInImage"]=oss.str(); + oss<<m_SegmentationType; + results["SegmentationType"]=oss.str(); oss.str(""); + oss<<m_Path->GetVertexList()->Size(); + results["NumberOfPointsInPath"]=oss.str(); + oss.str(""); + + typename PathType::VertexListType::ConstIterator it; + unsigned int index = 0; + + for(it=m_Path->GetVertexList()->Begin();it!=m_Path->GetVertexList()->End();++it,++index) + { + ContinuousIndexType point = it.Value(); + oss<<"P"<<index<<"x"; + std::string key = oss.str(); + oss.str(""); + oss<<point[0]; + results[key]=oss.str(); + oss.str(""); + oss<<"P"<<index<<"y"; + key = oss.str(); + oss.str(""); + oss<<point[1]; + results[key]=oss.str(); + oss.str(""); + } return results; } /** * PrintSelf method */ -template <class TLabel> +template <class TPath> void -RCC8VertexBase<TLabel> +RCC8VertexBase<TPath> ::PrintSelf( std::ostream& os,itk::Indent indent ) const { Superclass::PrintSelf(os,indent); - os<<indent<<"SegmentationImageIndex: "<<m_SegmentationImageIndex<<std::endl; - os<<indent<<"ObjectLabelInImage: "<<m_ObjectLabelInImage<<std::endl; + os<<indent<<"SegmentationLevel: "<<m_SegmentationLevel<<std::endl; + os<<indent<<"SegmentationType: "<<m_SegmentationType<<std::endl; } } // end namespace otb #endif diff --git a/Code/SpatialReasoning/otbRCC8VertexWithCompacity.h b/Code/SpatialReasoning/otbRCC8VertexWithCompacity.h index 23f123890d..7dffcba63f 100644 --- a/Code/SpatialReasoning/otbRCC8VertexWithCompacity.h +++ b/Code/SpatialReasoning/otbRCC8VertexWithCompacity.h @@ -29,14 +29,14 @@ namespace otb * * \sa RCC8Graph, RCC8Edge, RCC8VertexBase */ - template <class TLabel, class TPrecision = float> + template <class TPath, class TPrecision = float> class ITK_EXPORT RCC8VertexWithCompacity - : public RCC8VertexBase<TLabel> + : public RCC8VertexBase<TPath> { public: /** Standard class typedefs */ typedef RCC8VertexWithCompacity Self; - typedef otb::RCC8VertexBase<TLabel> Superclass; + typedef otb::RCC8VertexBase<TPath> Superclass; typedef itk::SmartPointer<Self> Pointer; typedef itk::SmartPointer<const Self> ConstPointer; /** Method for creation through the object factory. */ @@ -44,7 +44,7 @@ namespace otb /** Run-time type information (and related methods). */ itkTypeMacro(RCC8VertexWithCompacity,RCC8VertexBase); /** Input image associated typedefs*/ - typedef TLabel LabelType; + typedef TPath PathType; /** Precision typedef */ typedef TPrecision PrecisionType; /** char* vector attributes */ diff --git a/Code/SpatialReasoning/otbRCC8VertexWithCompacity.txx b/Code/SpatialReasoning/otbRCC8VertexWithCompacity.txx index 76869cc50e..e43614b1d5 100644 --- a/Code/SpatialReasoning/otbRCC8VertexWithCompacity.txx +++ b/Code/SpatialReasoning/otbRCC8VertexWithCompacity.txx @@ -25,8 +25,8 @@ namespace otb /** * Constructor */ -template <class TLabel,class TPrecision> -RCC8VertexWithCompacity<TLabel,TPrecision> +template <class TPath,class TPrecision> +RCC8VertexWithCompacity<TPath,TPrecision> ::RCC8VertexWithCompacity() { m_Compacity=0.0; @@ -35,9 +35,9 @@ RCC8VertexWithCompacity<TLabel,TPrecision> * Set the VertexWithCompacity attributes from the attributes vector. * \param attributes The vector containing the parsed attributes. */ -template <class TLabel,class TPrecision> +template <class TPath,class TPrecision> void -RCC8VertexWithCompacity<TLabel,TPrecision> +RCC8VertexWithCompacity<TPath,TPrecision> ::SetAttributesMap(AttributesMapType attributes) { this->Superclass::SetAttributesMap(attributes); @@ -47,9 +47,9 @@ RCC8VertexWithCompacity<TLabel,TPrecision> * Get an attributes vector representing the VertexBase attributes. * \return The attributes vector */ -template <class TLabel,class TPrecision> -typename RCC8VertexWithCompacity<TLabel,TPrecision>::AttributesMapType -RCC8VertexWithCompacity<TLabel,TPrecision> +template <class TPath,class TPrecision> +typename RCC8VertexWithCompacity<TPath,TPrecision>::AttributesMapType +RCC8VertexWithCompacity<TPath,TPrecision> ::GetAttributesMap(void) { std::stringstream oss; @@ -63,9 +63,9 @@ RCC8VertexWithCompacity<TLabel,TPrecision> /** * PrintSelf method */ -template <class TLabel,class TPrecision> +template <class TPath,class TPrecision> void -RCC8VertexWithCompacity<TLabel,TPrecision> +RCC8VertexWithCompacity<TPath,TPrecision> ::PrintSelf( std::ostream& os,itk::Indent indent ) const { Superclass::PrintSelf(os,indent); -- GitLab