diff --git a/Code/Common/otbPolyLineParametricPathWithValue.txx b/Code/Common/otbPolyLineParametricPathWithValue.txx index ed4d60b6edabdce758cf29574a66e50b5bc0a51d..8724e8d56a7e1637b8b52a9a33024ca8f1d09883 100644 --- a/Code/Common/otbPolyLineParametricPathWithValue.txx +++ b/Code/Common/otbPolyLineParametricPathWithValue.txx @@ -81,6 +81,13 @@ namespace otb ::PrintSelf(std::ostream& os, itk::Indent indent) const { Superclass::PrintSelf(os, indent); + VertexListConstIteratorType it = this->GetVertexList()->Begin(); + while(it != this->GetVertexList()->End()) + { + os << it.Value() << " - "; + it++; + } + os << std::endl; } } // end namespace otb diff --git a/Code/FeatureExtraction/otbLinkPathListFilter.h b/Code/FeatureExtraction/otbLinkPathListFilter.h index 63728f26461ab3b3bebbadb28e9d3837f5d0f0cc..ad5b512959a71c0b9478c48184911b3c0aa5b257 100644 --- a/Code/FeatureExtraction/otbLinkPathListFilter.h +++ b/Code/FeatureExtraction/otbLinkPathListFilter.h @@ -34,6 +34,11 @@ namespace otb * Please note that this filter may invert the order of the vertices in the newly created path. * * This filter is part of the road extraction framework. + * + * \sa ParallelLinePathListFilter + * + * \ingroup PathFilters + * */ template <class TPath> class ITK_EXPORT LinkPathListFilter diff --git a/Code/FeatureExtraction/otbParallelLinePathListFilter.h b/Code/FeatureExtraction/otbParallelLinePathListFilter.h index be647ad19702fe1d8a13b14c348b3a35caf0ddd2..7ec50024fede41741eda05217afa6f9087c77856 100644 --- a/Code/FeatureExtraction/otbParallelLinePathListFilter.h +++ b/Code/FeatureExtraction/otbParallelLinePathListFilter.h @@ -24,9 +24,26 @@ PURPOSE. See the above copyright notices for more information. namespace otb { /** \class ParallelLinePathListFilter - * \brief Description needed - * + * \brief otbParallelLinePathListFilter detects parallel lines in imagery. The required input data are a pathlist object. * + * The class consists of three basic functions that determine the angle between two lines, + * the distance between the lines and the common part of the lines. First, all input lines + * are checked if there is a second line running in the same direction. Thereafter, all line + * pairs that already fulfilled the angular criterion are checked whether they are close to + * each other or not, i.e. the orthogonal distance between them is calculated. Finally, it + * has to be verified if the two lines have a common part since lines may fulfil the two + * first criteria but be located in different parts of the image. In order to adapt the + * detection algorithm to the user’s needs, the thresholds AngularThreshold, DistanceThreshold + * and CommonDistanceThreshold can be set. + * + * A possible processing chain would be to extract lines with a line detector, to convert the + * result to pathlist objects, to link short line segments with the otbLinkPathListFilter to + * longer lines and to finally detect all parallel long lines. + * + * \sa LinkPathListFilter + * + * \ingroup PathFilters + * */ template <class TPath> class ITK_EXPORT ParallelLinePathListFilter diff --git a/Testing/Code/FeatureExtraction/CMakeLists.txt b/Testing/Code/FeatureExtraction/CMakeLists.txt index 16147db51985b2cac75d32dd63de899be25edaba..d5448b715137572cb6f9aaf9c0a4f5b68f34c6ce 100644 --- a/Testing/Code/FeatureExtraction/CMakeLists.txt +++ b/Testing/Code/FeatureExtraction/CMakeLists.txt @@ -844,6 +844,17 @@ ADD_TEST(feTvImageToHessianDeterminantImageFilter ${FEATUREEXTRACTION_TESTS9} ADD_TEST(feTuImageFittingPolygonListFilterNew ${FEATUREEXTRACTION_TESTS9} otbImageFittingPolygonListFilterNew) +ADD_TEST(feTvImageFittingPolygonListFilter ${FEATUREEXTRACTION_TESTS9} +--compare-ascii ${EPS} + ${BASELINE_FILES}/feTvImageFittingPolygonListFilter_Output.kml + ${TEMP}/feTvImageFittingPolygonListFilter_Output.kml + otbImageFittingPolygonListFilter + ${INPUTDATA}/polygon.png + ${INPUTDATA}/polygon-start.kml + ${TEMP}/feTvImageFittingPolygonListFilter_Output.kml + 5 10 +) + # A enrichir SET(BasicFeatureExtraction_SRCS1 otbAlignImageToPath.cxx @@ -949,6 +960,7 @@ otbImageToSIFTKeyPointSetFilterOutputAscii.cxx otbImageToHessianDeterminantImageFilterNew.cxx otbImageToHessianDeterminantImageFilter.cxx otbImageFittingPolygonListFilterNew.cxx +otbImageFittingPolygonListFilter.cxx ) INCLUDE_DIRECTORIES("${OTBTesting_BINARY_DIR}") diff --git a/Testing/Code/FeatureExtraction/otbFeatureExtractionTests9.cxx b/Testing/Code/FeatureExtraction/otbFeatureExtractionTests9.cxx index 9b4221b808cf1c489e92c082fbe1be9076307aeb..4f1e48adef26ae266bdfa013e9ac162df7da67b7 100644 --- a/Testing/Code/FeatureExtraction/otbFeatureExtractionTests9.cxx +++ b/Testing/Code/FeatureExtraction/otbFeatureExtractionTests9.cxx @@ -36,5 +36,5 @@ REGISTER_TEST(otbImageToSIFTKeyPointSetFilterOutputAscii); REGISTER_TEST(otbImageToHessianDeterminantImageFilterNew); REGISTER_TEST(otbImageToHessianDeterminantImageFilter); REGISTER_TEST(otbImageFittingPolygonListFilterNew); - +REGISTER_TEST(otbImageFittingPolygonListFilter); } diff --git a/Testing/Code/FeatureExtraction/otbImageFittingPolygonListFilter.cxx b/Testing/Code/FeatureExtraction/otbImageFittingPolygonListFilter.cxx new file mode 100644 index 0000000000000000000000000000000000000000..35968ee020dc0bde944571437a3a23c8d1ec6378 --- /dev/null +++ b/Testing/Code/FeatureExtraction/otbImageFittingPolygonListFilter.cxx @@ -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. + +=========================================================================*/ +#include "itkExceptionObject.h" + +#include "otbImageFittingPolygonListFilter.h" +#include "otbPolygon.h" +#include "otbImage.h" +#include "otbVectorData.h" +#include "otbImageFileReader.h" +#include "otbVectorDataFileReader.h" +#include "otbVectorDataFileWriter.h" +#include "itkCannyEdgeDetectionImageFilter.h" +#include "otbObjectList.h" +#include <fstream> +#include <cstdlib> + +int otbImageFittingPolygonListFilter(int argc, char * argv[]) +{ + const char * imageFileName = argv[1]; + const char * polyFileName = argv[2]; + const char * outFileName = argv[3]; + const int fittingRadius = atoi(argv[4]); + const int fittingIters = atoi(argv[5]); + + const unsigned int Dimension =2; + typedef otb::Polygon<double> PolygonType; + typedef otb::Image<double,Dimension> ImageType; + + //Read the reference image and extract its contours + typedef otb::ImageFileReader<ImageType> ReaderType; + ReaderType::Pointer reader = ReaderType::New(); + reader->SetFileName(imageFileName); + + typedef itk::CannyEdgeDetectionImageFilter<ImageType,ImageType> CannyFilterType; + CannyFilterType::Pointer canny = CannyFilterType::New(); + canny->SetInput(reader->GetOutput()); + + //Read the original polygon list (kml file) + typedef otb::VectorData<> VectorDataType; + typedef VectorDataType::DataTreeType DataTreeType; + typedef itk::PreOrderTreeIterator<DataTreeType> TreeIteratorType; + typedef VectorDataType::DataNodeType DataNodeType; + typedef DataNodeType::Pointer DataNodePointerType; + typedef otb::VectorDataFileReader<VectorDataType> VectorDataFileReaderType; + VectorDataFileReaderType::Pointer readerVector = VectorDataFileReaderType::New(); + + readerVector->SetFileName(polyFileName); + readerVector->Update(); + + //Copy the polygons of the data tree in a polygon list + typedef otb::ObjectList<PolygonType> PolygonListType; + PolygonListType::Pointer polygonList = PolygonListType::New(); + + TreeIteratorType it(readerVector->GetOutput()->GetDataTree()); + it.GoToBegin(); + + while(!it.IsAtEnd()) + { + DataNodePointerType dataNode = it.Get(); + if(dataNode->IsPolygonFeature()) + { + polygonList->PushBack(dataNode->GetPolygonExteriorRing()); + } + ++it; + } + + //Fit the polygons on the image + typedef otb::ImageFittingPolygonListFilter<PolygonType,ImageType> FittingPolygonType; + + FittingPolygonType::Pointer fittingPolygon = FittingPolygonType::New(); + fittingPolygon->SetInput(polygonList); + fittingPolygon->SetInputImage(canny->GetOutput()); + fittingPolygon->SetRadius(fittingRadius); + fittingPolygon->SetNumberOfIterations(fittingIters); + fittingPolygon->Update(); + + + //Write the improved polygon list (kml file) + VectorDataType::Pointer data = VectorDataType::New(); + + DataNodeType::Pointer document = DataNodeType::New(); + DataNodeType::Pointer folder = DataNodeType::New(); + + document->SetNodeType(otb::DOCUMENT); + folder->SetNodeType(otb::FOLDER); + + document->SetNodeId("DOCUMENT"); + folder->SetNodeId("FOLDER"); + + DataNodeType::Pointer root = data->GetDataTree()->GetRoot()->Get(); + + data->GetDataTree()->Add(document,root); + data->GetDataTree()->Add(folder,document); + + typedef PolygonListType::ConstIterator ListIteratorType; + ListIteratorType listIt = fittingPolygon->GetOutput()->Begin(); + while(listIt != fittingPolygon->GetOutput()->End()) + { + DataNodeType::Pointer polygon = DataNodeType::New(); + polygon->SetNodeType(otb::FEATURE_POLYGON); + polygon->SetNodeId("FEATURE_POLYGON"); + polygon->SetPolygonExteriorRing(listIt.Get()); + data->GetDataTree()->Add(polygon,folder); + ++listIt; + } + + typedef otb::VectorDataFileWriter<VectorDataType> WriterType; + WriterType::Pointer writer = WriterType::New(); + writer->SetFileName(outFileName); + writer->SetInput(data); + writer->Update(); + + return EXIT_SUCCESS; +}