Skip to content
Snippets Groups Projects
Commit 4591bad3 authored by Julien Malik's avatar Julien Malik
Browse files

ENH: fix misuse of Persistent filter

- The filter must merge the different segments in the output
at each AfterThreadedGenerateData call, not at Synthesize step
- GenerateInputRequestedRegion is needed as the filter requires
a padded input region
- Don't save pointers as members when they are not necessary
- Recreate the minipipeline at each iteration for security
- Set the default number of threads to 1, or we have too small
regions
parent e23b967d
No related branches found
No related tags found
No related merge requests found
......@@ -124,21 +124,21 @@ protected:
void GenerateInputRequestedRegion();
void BeforeThreadedGenerateData();
/** Multi-thread version GenerateData. */
void ThreadedGenerateData(const RegionType& outputRegionForThread,
int threadId);
void AfterThreadedGenerateData();
private:
PersistentLineSegmentDetector(const Self &); //purposely not implemented
void operator =(const Self&); //purposely not implemented
// region extractor
ExtractorListType m_ExtractorList;
// store requested region for each threads
RegionListType m_RegionList;
// line detector filters
LineDetectorListType m_LineDetectorList;
// store each thread output
/** the "Folder" node of the output vector data */
DataNodePointerType m_Folder;
/** store each thread output */
VectorDataListType m_VectorDataList;
/** tolerance to fuse 2 lines in 2 threads. */
double m_ThreadDistanceThreshold;
......
......@@ -40,6 +40,11 @@ PersistentLineSegmentDetector<TInputImage, TPrecision>
this->SetNumberOfRequiredOutputs(3);
this->itk::ProcessObject::SetNthOutput(1, this->MakeOutput(1).GetPointer());
this->itk::ProcessObject::SetNthOutput(2, this->MakeOutput(2).GetPointer());
// Set the number of threads to 1 by default to avoid oversegmentation
// There also seem to be a bug in the underlying LineSegmentDetector
// for small regions (probably when a stream does not contain segment)
this->SetNumberOfThreads(1);
}
template<class TInputImage, class TPrecision>
......@@ -116,31 +121,12 @@ PersistentLineSegmentDetector<TInputImage, TPrecision>
{
int nbThread = this->GetNumberOfThreads();
m_ExtractorList.clear();
m_RegionList.clear();
m_LineDetectorList.clear();
m_VectorDataList.clear();
m_VectorDataList.resize(nbThread);
m_RegionList.resize(nbThread);
for (int p = 0; p < nbThread; ++p)
{
m_ExtractorList.push_back(ExtractorType::New());
m_LineDetectorList.push_back(LineDetectorType::New());
m_LineDetectorList[p]->SetImageSize(this->GetInput()->GetLargestPossibleRegion().GetSize());
}
}
template<class TInputImage, class TPrecision>
void
PersistentLineSegmentDetector<TInputImage, TPrecision>
::Synthetize()
{
// merge all lines in a single vector data
VectorDataType* outputVData = this->GetOutputVectorData();
// Retrieving root node
DataNodePointerType root = outputVData->GetDataTree()->GetRoot()->Get();
// Create the document node
......@@ -148,28 +134,21 @@ PersistentLineSegmentDetector<TInputImage, TPrecision>
document->SetNodeType(otb::DOCUMENT);
DataNodePointerType folder = DataNodeType::New();
folder->SetNodeType(otb::FOLDER);
m_Folder = folder;
// Adding the layer to the data tree
outputVData->GetDataTree()->Add(document, root);
outputVData->GetDataTree()->Add(folder, document);
for (unsigned int threadId = 0; threadId < m_VectorDataList.size(); ++threadId)
{
TreeIteratorType itCurrentVData(m_VectorDataList[threadId]->GetDataTree());
itCurrentVData.GoToBegin();
while (!itCurrentVData.IsAtEnd())
{
if (itCurrentVData.Get()->IsLineFeature())
{
outputVData->GetDataTree()->Add(itCurrentVData.Get(), folder);
}
itCurrentVData ++;
}
}
this->GetOutputVectorData()->SetMetaDataDictionary(m_VectorDataList[0]->GetMetaDataDictionary());
}
template<class TInputImage, class TPrecision>
void
PersistentLineSegmentDetector<TInputImage, TPrecision>
::Synthetize()
{
}
template<class TInputImage, class TPrecision>
void
PersistentLineSegmentDetector<TInputImage, TPrecision>
......@@ -187,42 +166,84 @@ PersistentLineSegmentDetector<TInputImage, TPrecision>
if (this->GetInput())
{
ImagePointerType image = const_cast<ImageType *>(this->GetInput());
image->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());
ImagePointerType input = const_cast<ImageType *>(this->GetInput());
RegionType region = this->GetOutput()->GetRequestedRegion();
region.PadByRadius(1);
region.Crop(input->GetLargestPossibleRegion());
input->SetRequestedRegion(region);
}
}
template<class TInputImage, class TPrecision>
void
PersistentLineSegmentDetector<TInputImage, TPrecision>
::BeforeThreadedGenerateData()
{
}
template<class TInputImage, class TPrecision>
void
PersistentLineSegmentDetector<TInputImage, TPrecision>
::ThreadedGenerateData(const RegionType& outputRegionForThread, int threadId)
{
ImagePointerType inputPtr = const_cast<TInputImage *>(this->GetInput());
RegionType region = outputRegionForThread;
region.PadByRadius((unsigned int)(1));
region.Crop(inputPtr->GetLargestPossibleRegion());
inputPtr->SetRequestedRegion(region);
inputPtr->PropagateRequestedRegion();
inputPtr->UpdateOutputData();
m_ExtractorList[threadId]->SetInput(this->GetInput());
m_ExtractorList[threadId]->SetExtractionRegion(region);
//m_ExtractorList[threadId]->SetExtractionRegion(outputRegionForThread);
m_ExtractorList[threadId]->UpdateOutputInformation();
m_LineDetectorList[threadId]->SetInput(m_ExtractorList[threadId]->GetOutput());
m_LineDetectorList[threadId]->Update();
m_RegionList[threadId] = outputRegionForThread;
m_VectorDataList[threadId] = m_LineDetectorList[threadId]->GetOutput();
try
{
ImagePointerType inputPtr = const_cast<TInputImage *>(this->GetInput());
RegionType region = outputRegionForThread;
region.PadByRadius((unsigned int)(1));
region.Crop(inputPtr->GetLargestPossibleRegion());
inputPtr->SetRequestedRegion(region);
inputPtr->PropagateRequestedRegion();
inputPtr->UpdateOutputData();
typename ExtractorType::Pointer extractFilter = ExtractorType::New();
extractFilter->SetInput(this->GetInput());
extractFilter->SetExtractionRegion(region);
extractFilter->Update();
typename LineDetectorType::Pointer lineDetector = LineDetectorType::New();
lineDetector->SetInput(extractFilter->GetOutput());
lineDetector->Update();
m_VectorDataList[threadId] = lineDetector->GetOutput();
}
catch (itk::ExceptionObject& e)
{
std::cout << "Exception : " << e;
throw;
}
}
template<class TInputImage, class TPrecision>
void
PersistentLineSegmentDetector<TInputImage, TPrecision>
::AfterThreadedGenerateData()
{
// merge all lines in a single vector data
VectorDataType* outputVData = this->GetOutputVectorData();
outputVData->GetDataTree();
// end of class PersistentLineSegmentDetector
for (unsigned int threadId = 0; threadId < m_VectorDataList.size(); ++threadId)
{
TreeIteratorType itCurrentVData(m_VectorDataList[threadId]->GetDataTree());
itCurrentVData.GoToBegin();
while (!itCurrentVData.IsAtEnd())
{
if (itCurrentVData.Get()->IsLineFeature())
{
outputVData->GetDataTree()->Add(itCurrentVData.Get(), m_Folder);
}
itCurrentVData ++;
}
}
this->GetOutputVectorData()->SetMetaDataDictionary(m_VectorDataList[0]->GetMetaDataDictionary());
}
/**===========================================================================*/
// end of class PersistentLineSegmentDetector
template<class TInputImage, class TPrecision>
StreamingLineSegmentDetector<TInputImage, TPrecision>
......@@ -236,18 +257,5 @@ StreamingLineSegmentDetector<TInputImage, TPrecision>
{
}
/**
* The aim here is to gathered each thread output into a vector data.
* For that we have to fuse different thread output, in particular for line that throw thread.
* For that, for each thread and each detected line, we look if one of its extrema is over a thread lower limit (RegionList.GetSize()[1]).
* If yes, we store the line. If no, we add it to the vector data.
* At the next loop (ie. next thread), for each line, we check that it doesn't have a point in common with lines that end at the end of
* the previous thread.
* If yes we compute the extrema (one point ineach thread).
* If not, we add it to the vector data, else we store it.
* And so on.
* m_ThreadDistanceThreshold allows a tolerance over the commmon point spatial distance when 2 lines are fused.
*/
} // end namespace otb
#endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment