Commit 1b2e16ac authored by Cyrille Valladeau's avatar Cyrille Valladeau
Browse files

ENH : streamed LSD + tests

parent b91e6399
/*=========================================================================
Program: ORFEO Toolbox
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
See OTBCopyright.txt for details.
Some parts of this code are derived from ITK. See ITKCopyright.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 __otbImageToLineSegmentVectorData_h
#define __otbImageToLineSegmentVectorData_h
#include "otbPersistentImageFilter.h"
#include "otbObjectList.h"
#include "otbLineSegmentDetector.h"
#include "itkExtractImageFilter.h"
#include "otbPersistentFilterStreamingDecorator.h"
#include "otbVectorData.h"
namespace otb
{
/** \class PersistentLineDetector
* \brief Perform line segment computation in a persistent way.
*
* This filter allows find and store the segment from a mono channel image.
* Its output is a LineSpatialObject list.
* The Reset() method allows to clear the result path list.
*
* \sa PersistentImageFilter
*
*/
template<class TInputImage, class TPrecision=double >
class ITK_EXPORT PersistentLineSegmentDetector :
public PersistentImageFilter<TInputImage, TInputImage>
{
public:
/** Standard Self typedef */
typedef PersistentLineSegmentDetector Self;
typedef PersistentImageFilter<TInputImage,TInputImage> Superclass;
typedef itk::SmartPointer<Self> Pointer;
typedef itk::SmartPointer<const Self> ConstPointer;
/** Method for creation through the object factory. */
itkNewMacro(Self);
/** Runtime information support. */
itkTypeMacro(PersistentLineSegmentDetector, PersistentImageFilter);
/** Image related typedefs. */
// First Input
typedef TInputImage ImageType;
typedef typename TInputImage::Pointer ImagePointer;
typedef typename TInputImage::RegionType RegionType;
typedef typename TInputImage::SizeType SizeType;
typedef typename TInputImage::IndexType IndexType;
typedef typename TInputImage::PixelType PixelType;
typedef typename TInputImage::InternalPixelType InternalPixelType;
// Output path type
typedef LineSegmentDetector<ImageType, TPrecision> LineDetectorType;
typedef typename LineDetectorType::Pointer LineDetectorPointerType;
typedef typename LineDetectorType::LineSpatialObjectListType LineSpatialObjectType;
typedef typename LineSpatialObjectType::Pointer LineSpatialObjectPointerType;
typedef ObjectList<LineSpatialObjectType> LineSpatialObjectListType;
typedef typename LineSpatialObjectListType::Pointer LineSpatialObjectListPointerType;
typedef itk::ExtractImageFilter<ImageType, ImageType> ExtractorType;
typedef typename ExtractorType::Pointer ExtractorPointerType;
virtual void Reset(void);
virtual void Synthetize(void);
itkGetObjectMacro(LineSpatialObjectList,LineSpatialObjectListType);
void AllocateOutputs(){};
void GenerateOutputInformation();
// Override since the filter needs all the data for the algorithm
virtual void GenerateInputRequestedRegion();
/*
void SetInput(const ImageType *input)
{
this->SetInput(0, input );
};
const ImageType* GetInput()
{
if ( this->GetNumberOfInputs() < 1 )
{
return 0;
}
else
return( static_cast<const TInputImage *>(this->itk::ProcessObject::GetInput(0)) );
}
*/
protected:
PersistentLineSegmentDetector();
~PersistentLineSegmentDetector() {};
void PrintSelf(std::ostream& os, itk::Indent indent) const;
virtual void ThreadedGenerateData (const RegionType& outputRegionForThread,int threadId);
//virtual void GenerateData();
private:
PersistentLineSegmentDetector(const Self&); //purposely not implemented
void operator=(const Self&); //purposely not implemented
// line detector filter
LineDetectorPointerType m_LineDetector;
// Region extractor.
LineSpatialObjectListPointerType m_LineSpatialObjectList;
}; // end of class
// end of class PersistentLineSegmentDetector
/**===========================================================================*/
/** \class ImageToLineSegmentVectorData
* \brief This class streams the whole input image through the PersistentLineSegmentDetector.
*
* This way, it allows to compute the inner product of this image. It calls the
* Reset() method of the PersistentLineSegmentDetector before streaming the image and the
* Synthetize() method of the PersistentLineSegmentDetector after having streamed the image
* to compute the statistics. The accessor on the results are wrapping the accessors of the
* internal PersistentLineSegmentDetector.
* Its output is a vector data file.
*
* \sa PersistentLineSegmentDetector
* \sa PersistentImageFilter
* \sa PersistentFilterStreamingDecorator
* \sa StreamingImageVirtualWriter
* \ingroup Streamed
* \ingroup Multithreaded
* \ingroup MathematicalStatisticsImageFilters
*/
template<class TInputImage, class TPrecision=double>
class ITK_EXPORT ImageToLineSegmentVectorData :
public PersistentFilterStreamingDecorator< PersistentLineSegmentDetector<TInputImage, TPrecision> >
{
public:
/** Standard Self typedef */
typedef ImageToLineSegmentVectorData Self;
typedef PersistentFilterStreamingDecorator
< PersistentLineSegmentDetector<TInputImage, TPrecision> > Superclass;
typedef itk::SmartPointer<Self> Pointer;
typedef itk::SmartPointer<const Self> ConstPointer;
/** Type macro */
itkNewMacro(Self);
/** Creation through object factory macro */
itkTypeMacro(ImageToLineSegmentVectorData,PersistentFilterStreamingDecorator);
typedef TInputImage InputImageType;
typedef typename Superclass::FilterType LSDFilterType;
/** Type of DataObjects used for scalar outputs */
typedef typename LSDFilterType::LineSpatialObjectListType LineSpatialObjectListType;
typedef typename LineSpatialObjectListType::Pointer LineSpatialObjectListPointerType;
typedef typename LSDFilterType::LineSpatialObjectType LineSpatialObjectType;
typedef VectorData<TPrecision> VectorDataType;
typedef typename VectorDataType::Pointer VectorDataPointerType;
typedef typename VectorDataType::DataNodeType DataNodeType;
typedef typename DataNodeType::Pointer DataNodePointerType;
typedef typename DataNodeType::LineType LineType;
typedef typename LineType::VertexType VertexType;
void SetInput(TInputImage * input)
{
this->GetFilter()->SetInput(input);
}
const TInputImage * GetInput()
{
return this->GetFilter()->GetInput();
}
LineSpatialObjectListPointerType GetLines()
{
return this->GetFilter()->GetLineSpatialObjectList();
};
/** Transform the linespatialobject list into vector data*/
VectorDataPointerType GetOutputVectorData();
protected:
/** Constructor */
ImageToLineSegmentVectorData();
/** Destructor */
virtual ~ImageToLineSegmentVectorData() {};
private:
ImageToLineSegmentVectorData(const Self&); //purposely not implemented
void operator=(const Self&); //purposely not implemented
};
} // end namespace otb
#ifndef OTB_MANUAL_INSTANTIATION
#include "otbImageToLineSegmentVectorData.txx"
#endif
#endif
/*=========================================================================
Program: ORFEO Toolbox
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
See OTBCopyright.txt for details.
Some parts of this code are derived from ITK. See ITKCopyright.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 __otbImageToLineSegmentVectorData_txx
#define __otbImageToLineSegmentVectorData_txx
#include "otbImageToLineSegmentVectorData.h"
#include "itkImageRegionConstIterator.h"
#include "itkImageRegionIterator.h"
#include "itkProgressReporter.h"
namespace otb
{
template<class TInputImage, class TPrecision>
PersistentLineSegmentDetector<TInputImage, TPrecision>
::PersistentLineSegmentDetector()
{
//m_LineDetector = LineDetectorType::New();
m_LineSpatialObjectList = LineSpatialObjectListType::New();
}
template<class TInputImage, class TPrecision>
void
PersistentLineSegmentDetector<TInputImage, TPrecision>
::Reset()
{
m_LineSpatialObjectList->Clear();
}
template<class TInputImage, class TPrecision>
void
PersistentLineSegmentDetector<TInputImage, TPrecision>
::Synthetize()
{}
template<class TInputImage, class TPrecision>
void
PersistentLineSegmentDetector<TInputImage, TPrecision>
::GenerateInputRequestedRegion()
{
Superclass::GenerateInputRequestedRegion();
if ( this->GetInput() )
{
ImagePointer image = const_cast< ImageType * >( this->GetInput() );
image->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());
}
}
template<class TInputImage, class TPrecision>
void
PersistentLineSegmentDetector<TInputImage, TPrecision>
::GenerateOutputInformation()
{
Superclass::GenerateOutputInformation();
if ( this->GetInput() )
{
this->GetOutput()->CopyInformation(this->GetInput());
this->GetOutput()->SetLargestPossibleRegion(this->GetInput()->GetLargestPossibleRegion());
}
if (this->GetOutput()->GetRequestedRegion().GetNumberOfPixels()==0)
{
this->GetOutput()->SetRequestedRegion(this->GetOutput()->GetLargestPossibleRegion());
}
}
template<class TInputImage, class TPrecision>
void
PersistentLineSegmentDetector<TInputImage, TPrecision>
::ThreadedGenerateData (const RegionType& outputRegionForThread,int threadId)
{
ImagePointer inputPtr = const_cast< TInputImage * >( this->GetInput() );
ImagePointer outputPtr = const_cast< TInputImage * >( this->GetOutput() );
inputPtr->SetRequestedRegion(outputRegionForThread);
inputPtr->PropagateRequestedRegion();
inputPtr->UpdateOutputData();
LineDetectorPointerType lineDetector = LineDetectorType::New();
ExtractorPointerType extractor = ExtractorType::New();
extractor->SetInput(this->GetInput());
extractor->SetExtractionRegion(this->GetInput()->GetRequestedRegion());
extractor->UpdateOutputInformation();
lineDetector->SetInput(extractor->GetOutput());
lineDetector->Update();
m_LineSpatialObjectList->PushBack(lineDetector->GetOutput());
}
template<class TInputImage, class TPrecision>
void
PersistentLineSegmentDetector<TInputImage, TPrecision>
::PrintSelf(std::ostream& os, itk::Indent indent) const
{
Superclass::PrintSelf(os,indent);
}
// end of class PersistentLineSegmentDetector
/**===========================================================================*/
template<class TInputImage, class TPrecision>
ImageToLineSegmentVectorData<TInputImage, TPrecision>
::ImageToLineSegmentVectorData()
{
}
template<class TInputImage, class TPrecision>
typename ImageToLineSegmentVectorData<TInputImage, TPrecision>::VectorDataPointerType
ImageToLineSegmentVectorData<TInputImage, TPrecision>
::GetOutputVectorData()
{
unsigned int listSize = this->GetLines()->Size();
if( listSize == 0)
{
itkExceptionMacro(<<"No LineSpatialObject to vectorize");
}
VectorDataPointerType vlines = VectorDataType::New();
DataNodePointerType document = DataNodeType::New();
DataNodePointerType folder = DataNodeType::New();
DataNodePointerType root = vlines->GetDataTree()->GetRoot()->Get();
document->SetNodeType(otb::DOCUMENT);
folder->SetNodeType(otb::FOLDER);
vlines->GetDataTree()->Add(document,root);
vlines->GetDataTree()->Add(folder,document);
vlines->SetProjectionRef(this->GetInput()->GetProjectionRef());
for(unsigned int i = 0; i<listSize; i++ )
{
typename LineSpatialObjectType::const_iterator it = this->GetLines()->GetNthElement(i)->begin();
typename LineSpatialObjectType::const_iterator itEnd = this->GetLines()->GetNthElement(i)->end();
while(it != itEnd)
{
VertexType p1,p2;
typename LineType::Pointer l = LineType::New();
typename LineSpatialObjectType::LineType::PointListType & pointsList = (*it)->GetPoints();
typename LineSpatialObjectType::LineType::PointListType::const_iterator itPoints = pointsList.begin();
p1[0] =(*itPoints).GetPosition()[0]; //First Vertex
p1[1] =(*itPoints).GetPosition()[1];
itPoints++;
p2[0] =(*itPoints).GetPosition()[0]; //Second Vertex
p2[1] =(*itPoints).GetPosition()[1];
l->AddVertex(p1);
l->AddVertex(p2);
DataNodePointerType node = DataNodeType::New();
node->SetNodeType(otb::FEATURE_LINE);
node->SetLine(l);
vlines->GetDataTree()->Add(node,folder);
++it;
} /** End lsd To VectorData */
}
return vlines;
}
}// end namespace otb
#endif
......@@ -28,7 +28,6 @@
#include "itkGradientRecursiveGaussianImageFilter.h"
#include "itkGradientImageFilter.h"
#include "otbImageFileWriter.h"
namespace otb
{
......@@ -164,9 +163,11 @@ protected:
LineSegmentDetector();
virtual ~LineSegmentDetector() {};
/** Before Generate Data method*/
virtual void BeforeGenerateData();
/** Generate Data method*/
virtual void GenerateData();
/** Sort the image and store the coordinates in a histogram
* this method is used to determine the seeds where to begin the search segments
* Points with large gradient modulus are more able to belong to a segment
......
......@@ -71,6 +71,23 @@ LineSegmentDetector<TInputImage,TPrecision >
}
template <class TInputImage, class TPrecision >
void
LineSegmentDetector<TInputImage,TPrecision >
::BeforeGenerateData()
{
if( this->GetInput()->GetRequestedRegion() != this->GetInput()->GetLargestPossibleRegion() )
{
itkExceptionMacro(<<"No stremed filer. ERROR : requested region is not the largest possible region.");
}
/** Allocate memory for the temporary label Image*/
m_UsedPointImage->SetRegions(this->GetInput()->GetLargestPossibleRegion());
m_UsedPointImage->Allocate();
m_UsedPointImage->FillBuffer(0);
}
/**
*
*/
......@@ -80,13 +97,15 @@ void
LineSegmentDetector<TInputImage,TPrecision >
::GenerateData()
{
this->BeforeGenerateData();
/** The Output*/
m_LineList = this->GetOutput();
/** Allocate memory for the temporary label Image*/
m_UsedPointImage->SetRegions(this->GetInput()->GetRequestedRegion());
m_UsedPointImage->Allocate();
m_UsedPointImage->FillBuffer(0);
//m_UsedPointImage->SetRegions(this->GetInput()->GetLargestPossbileRegion());
//m_UsedPointImage->Allocate();
//m_UsedPointImage->FillBuffer(0);
/** Cast the MagnitudeOutput Image in */
typedef itk::CastImageFilter<InputImageType, OutputImageType> castFilerType;
......
......@@ -30,6 +30,7 @@ SET(FEATUREEXTRACTION_TESTS11 ${CXX_TEST_PATH}/otbFeatureExtractionTests11)
SET(FEATUREEXTRACTION_TESTS12 ${CXX_TEST_PATH}/otbFeatureExtractionTests12)
SET(FEATUREEXTRACTION_TESTS13 ${CXX_TEST_PATH}/otbFeatureExtractionTests13)
SET(FEATUREEXTRACTION_TESTS14 ${CXX_TEST_PATH}/otbFeatureExtractionTests14)
SET(FEATUREEXTRACTION_TESTS15 ${CXX_TEST_PATH}/otbFeatureExtractionTests15)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ otbFeatureExtractionTests1 ~~~~~~~~~~~~~~~~~~~~~
......@@ -1734,6 +1735,25 @@ ADD_TEST(feTvRegionImageToRectangularPathListFilter ${FEATUREEXTRACTION_TESTS14}
10) #minimum size
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ otbFeatureExtractionTests15 ~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ------- otb::ImageToLineSegmentVectorData -------------
ADD_TEST(feTuImageToLineSegmentVectorDataNew ${FEATUREEXTRACTION_TESTS15}
otbImageToLineSegmentVectorDataNew)
ADD_TEST(feTvImageToLineSegmentVectorData ${FEATUREEXTRACTION_TESTS15}
--compare-ogr ${EPS}
${BASELINE}/feTvImageToLineSegmentVectorData.shp
${TEMP}/feTvImageToLineSegmentVectorData.shp
otbImageToLineSegmentVectorData
${INPUTDATA}/scene.png #prison_toulouse.tif
${TEMP}/feTvImageToLineSegmentVectorData.shp
)
# A enrichir
SET(BasicFeatureExtraction_SRCS1
otbAlignImageToPath.cxx
......@@ -1893,6 +1913,10 @@ otbRegionImageToRectangularPathListFilterNew.cxx
otbRegionImageToRectangularPathListFilter.cxx
)
SET(BasicFeatureExtraction_SRCS15
otbImageToLineSegmentVectorDataNew.cxx
otbImageToLineSegmentVectorData.cxx
)
INCLUDE_DIRECTORIES("${OTBTesting_BINARY_DIR}")
......@@ -1924,6 +1948,8 @@ ADD_EXECUTABLE(otbFeatureExtractionTests13 otbFeatureExtractionTests13.cxx ${Bas
TARGET_LINK_LIBRARIES(otbFeatureExtractionTests13 OTBFeatureExtraction OTBIO)
ADD_EXECUTABLE(otbFeatureExtractionTests14 otbFeatureExtractionTests14.cxx ${BasicFeatureExtraction_SRCS14})
TARGET_LINK_LIBRARIES(otbFeatureExtractionTests14 OTBFeatureExtraction OTBIO)
ADD_EXECUTABLE(otbFeatureExtractionTests15 otbFeatureExtractionTests15.cxx ${BasicFeatureExtraction_SRCS15})
TARGET_LINK_LIBRARIES(otbFeatureExtractionTests15 OTBFeatureExtraction OTBIO)
# ADD_EXECUTABLE(roadDetect roadDetect.cxx)
......
/*=========================================================================
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.
=========================================================================*/
// this file defines the otbCommonTest for the test driver
// and all it expects is that you have a function called RegisterTests
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif
#include "otbTestMain.h"
void RegisterTests()
{
REGISTER_TEST(otbImageToLineSegmentVectorDataNew);
REGISTER_TEST(otbImageToLineSegmentVectorData);
}
/*=========================================================================
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 "otbImageToLineSegmentVectorData.h"
#include "otbImageFileReader.h"
#include "otbVectorDataFileWriter.h"
#include "otbStreamingImageFileWriter.h"
int otbImageToLineSegmentVectorData( int argc, char * argv[] )
{
typedef float InputPixelType;
const unsigned int Dimension = 2;
/** Typedefs */
typedef otb::Image< InputPixelType, Dimension > ImageType;
typedef otb::ImageFileReader<ImageType> ReaderType;
typedef otb::ImageToLineSegmentVectorData<ImageType> ImToLSDFilterType;
typedef ImToLSDFilterType::VectorDataType VectorDataType;
typedef otb::VectorDataFileWriter<VectorDataType> WriterType;
ImToLSDFilterType::Pointer lsdFilter = ImToLSDFilterType::New();
ReaderType::Pointer reader = ReaderType::New();
WriterType::Pointer writer = WriterType::New();
reader->SetFileName(argv[1]);
reader->GenerateOutputInformation();
lsdFilter->SetInput( reader->GetOutput() );
lsdFilter->Update();