Skip to content
Snippets Groups Projects
Commit fa0d7e9f authored by Cyrille Valladeau's avatar Cyrille Valladeau
Browse files

ENH : add thread result fusion ion ImageToLineSegment

parent cdae7cf1
Branches
Tags
No related merge requests found
......@@ -203,6 +203,8 @@ class ITK_EXPORT ImageToLineSegmentVectorData :
/** Transform the linespatialobject list into vector data*/
VectorDataPointerType GetOutputVectorData();
itkSetMacro(ThreadDistanceThreshold, double);
itkGetMacro(ThreadDistanceThreshold, double);
protected:
/** Constructor */
......@@ -214,6 +216,8 @@ private:
ImageToLineSegmentVectorData(const Self&); //purposely not implemented
void operator=(const Self&); //purposely not implemented
/** tolerance to fuse 2 lines in 2 threads. */
double m_ThreadDistanceThreshold;
};
} // end namespace otb
......
......@@ -53,13 +53,12 @@ PersistentLineSegmentDetector<TInputImage, TPrecision>
m_RegionList = RegionListType(nbThread);
m_Extractor->Clear();
m_LineDetector->Clear();
//m_Extractor->Resize(nbThread);
//m_LineDetector->Resize(nbThread);
for(unsigned int p=0; p<nbThread; p++)
for(int p=0; p<nbThread; p++)
{
m_Extractor->PushBack( ExtractorType::New() );
m_LineDetector->PushBack( LineDetectorType::New() );
m_LineDetector->GetNthElement(p)->SetImageSize(this->GetInput()->GetLargestPossibleRegion().GetSize());
}
......@@ -112,38 +111,23 @@ void
PersistentLineSegmentDetector<TInputImage, TPrecision>
::ThreadedGenerateData (const RegionType& outputRegionForThread,int threadId)
{
std::cout<<"START: "<<threadId<<std::endl;
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(outputRegionForThread);//this->GetInput()->GetRequestedRegion());
extractor->UpdateOutputInformation();
lineDetector->SetInput(extractor->GetOutput());
lineDetector->Update();
*/
m_Extractor->GetNthElement(threadId)->SetInput(this->GetInput());
m_Extractor->GetNthElement(threadId)->SetExtractionRegion(outputRegionForThread/*this->GetInput()->GetRequestedRegion()*/);
m_Extractor->GetNthElement(threadId)->SetExtractionRegion(outputRegionForThread);
m_Extractor->GetNthElement(threadId)->UpdateOutputInformation();
m_LineDetector->GetNthElement(threadId)->SetInput(m_Extractor->GetNthElement(threadId)->GetOutput());
m_LineDetector->GetNthElement(threadId)->Update();
/*
m_RegionList[threadId] = outputRegionForThread;
m_LineSpatialObjectList->SetNthElement(threadId, lineDetector->GetOutput());
*/
std::cout<<"END: "<<threadId<<std::endl;
m_LineSpatialObjectList->SetNthElement(threadId, m_LineDetector->GetNthElement(threadId)->GetOutput());
}
template<class TInputImage, class TPrecision>
......@@ -163,15 +147,28 @@ template<class TInputImage, class TPrecision>
ImageToLineSegmentVectorData<TInputImage, TPrecision>
::ImageToLineSegmentVectorData()
{
m_ThreadDistanceThreshold = 10.;
}
/**
* 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.
*/
template<class TInputImage, class TPrecision>
typename ImageToLineSegmentVectorData<TInputImage, TPrecision>::VectorDataPointerType
ImageToLineSegmentVectorData<TInputImage, TPrecision>
::GetOutputVectorData()
{
unsigned int listSize = this->GetLines()->Size();
unsigned int listSize = this->GetLines()->Size();
if( listSize == 0)
{
itkExceptionMacro(<<"No LineSpatialObject to vectorize");
......@@ -195,13 +192,11 @@ ImageToLineSegmentVectorData<TInputImage, TPrecision>
typedef std::vector<VertexType> DoubleVertexType;
std::vector<DoubleVertexType> vertexList, vertexNewList;
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();
std::cout<<i<<" / "<<listSize<<" : "<<regionList[i].GetSize()<<", "<<regionList[i].GetIndex()<<std::endl;
while(it != itEnd)
{
VertexType p1,p2;
......@@ -214,29 +209,14 @@ ImageToLineSegmentVectorData<TInputImage, TPrecision>
p2[0] =(*itPoints).GetPosition()[0]; //Second Vertex
p2[1] =(*itPoints).GetPosition()[1];
std::cout<<p1<<" - "<<p2<<std::endl;
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 while(it != itEnd) loop
/*
bool go = false;
// horizontal line
if( vcl_abs(p1[1]-whereAmI[1])<1 && vcl_abs(p2[1]-whereAmI[1])<1 )
if( vcl_abs(p1[1]-whereAmI[1])<m_ThreadDistanceThreshold && vcl_abs(p2[1]-whereAmI[1])<m_ThreadDistanceThreshold )
{
go = true;
}
// point over the border
else if( vcl_abs(p1[1]-whereAmI[1])<1 || vcl_abs(p2[1]-whereAmI[1])<1 )
else if( vcl_abs(p1[1]-whereAmI[1])<m_ThreadDistanceThreshold || vcl_abs(p2[1]-whereAmI[1])<m_ThreadDistanceThreshold )
{
// have to fuse?
unsigned int j=0;
......@@ -247,24 +227,27 @@ ImageToLineSegmentVectorData<TInputImage, TPrecision>
{
p1Old = vertexList[j][0];
p2Old = vertexList[j][1];
// if p1=p1old and p2=p2Old or p1=p2old and p2=p1Old mod 1
if( ( vcl_abs(p1[0]-p1Old[0]) && vcl_abs(p1[1]-p1Old[1]) ) || ( vcl_abs(p2[0]-p2Old[0]) && vcl_abs(p2[1]-p2Old[1]) ) ||
( vcl_abs(p1[0]-p2Old[0]) && vcl_abs(p1[1]-p2Old[1]) ) || ( vcl_abs(p2[0]-p1Old[0]) && vcl_abs(p2[1]-p1Old[1]) ) )
if( ( vcl_abs(p1[0]-p1Old[0])<m_ThreadDistanceThreshold && vcl_abs(p1[1]-p1Old[1])<m_ThreadDistanceThreshold ) ||
( vcl_abs(p2[0]-p2Old[0])<m_ThreadDistanceThreshold && vcl_abs(p2[1]-p2Old[1])<m_ThreadDistanceThreshold ) ||
( vcl_abs(p1[0]-p2Old[0])<m_ThreadDistanceThreshold && vcl_abs(p1[1]-p2Old[1])<m_ThreadDistanceThreshold ) ||
( vcl_abs(p2[0]-p1Old[0])<m_ThreadDistanceThreshold && vcl_abs(p2[1]-p1Old[1])<m_ThreadDistanceThreshold ) )
{
done = true;
}
j++;
}
if(done==true)
if(done==true && j!=0)
{
DoubleVertexType vert;
// keep the 2 lines extramities
// p1 is the common point -> keep p2
if(vcl_abs(p1[1]-whereAmI[1])<1)
if(vcl_abs(p1[1]-whereAmI[1])<m_ThreadDistanceThreshold)
{
vert.push_back(p2);
// p1 is the same as p1Old -> keep p2Old
if( vcl_abs(p1[0]-p1Old[0]) && vcl_abs(p1[1]-p1Old[1]) )
if( vcl_abs(p1[0]-p1Old[0])<m_ThreadDistanceThreshold && vcl_abs(p1[1]-p1Old[1])<m_ThreadDistanceThreshold )
vert.push_back(p2Old);
else
vert.push_back(p1Old);
......@@ -274,7 +257,7 @@ ImageToLineSegmentVectorData<TInputImage, TPrecision>
{
vert.push_back(p1);
// p2 is the same as p1Old -> keep p1Old
if( vcl_abs(p2[0]-p2Old[0]) && vcl_abs(p2[1]-p2Old[1]) )
if( vcl_abs(p2[0]-p2Old[0])<m_ThreadDistanceThreshold && vcl_abs(p2[1]-p2Old[1]<m_ThreadDistanceThreshold) )
vert.push_back(p1Old);
else
vert.push_back(p2Old);
......@@ -283,14 +266,23 @@ ImageToLineSegmentVectorData<TInputImage, TPrecision>
// j-1 because of the j++ at the end of the while
vertexList.erase(vertexList.begin()+(j-1));
}
else if(j==0)
{
DoubleVertexType vert;
vert.push_back(p1);
vert.push_back(p2);
vertexNewList.push_back(vert);
}
// no point to fuse
else
go = true;
}
go = true;
}// else if( vcl_abs(p1[1]-whereAmI[1])<m_ThreadDistanceThreshold || vcl_abs(p2[1]-whereAmI[1])<m_ThreadDistanceThreshold )
else
{
go = true;
}
if( go==true)
{
l->AddVertex(p1);
......@@ -322,7 +314,7 @@ ImageToLineSegmentVectorData<TInputImage, TPrecision>
vertexNewList.clear();
whereAmI[0] += regionList[i].GetSize()[0];
whereAmI[1] += regionList[i].GetSize()[1];
*/
}// End for loop
return vlines;
......
......@@ -75,6 +75,8 @@ namespace Functor
* \brief this class implement a fast line detector with false detection control using
* the a contrario method
*
* \sa ImageLineSegmentDetector (streamed version)
*
* See Publication : " LSD: A line segment detector ", R. Grompone, J.Jackubowicz, J-M.Morel, G.Randall
*
*/
......@@ -83,7 +85,7 @@ template <class TInputImage,class TPrecision = double>
class ITK_EXPORT LineSegmentDetector :
public otb::ImageToLineSpatialObjectListFilter< TInputImage >
{
public:
public:
/** typedef for the classes standards. */
typedef LineSegmentDetector Self;
......@@ -159,6 +161,9 @@ public:
typedef typename RectangleListType::iterator RectangleListTypeIterator;
itkSetMacro(ImageSize, SizeType);
itkGetMacro(ImageSize, SizeType);
protected:
LineSegmentDetector();
virtual ~LineSegmentDetector() {};
......@@ -224,6 +229,8 @@ protected:
/** Printself method*/
void PrintSelf(std::ostream& os, itk::Indent indent) const;
private:
LineSegmentDetector(const Self&); //purposely not implemented
void operator=(const Self&); //purposely not implemented
......@@ -239,8 +246,10 @@ private:
unsigned int m_MinimumRegionSize;
unsigned int m_NumberOfImagePixels;
int m_Length;
int m_Width;
/** The image size has to be the LargestPosssibleRegion in the case
* (streaming uses (streaming decorator).
*/
SizeType m_ImageSize;
/** Gradient filter */
GradientFilterPointerType m_GradientFilter;
......
......@@ -66,8 +66,7 @@ LineSegmentDetector<TInputImage,TPrecision >
/** A Line List : This is the output*/
LineSpatialObjectListType::Pointer m_LineList = LineSpatialObjectListType::New();
m_Length = 0;
m_Width = 0;
m_ImageSize.Fill(0);
}
......@@ -102,11 +101,6 @@ LineSegmentDetector<TInputImage,TPrecision >
/** The Output*/
m_LineList = this->GetOutput();
/** Allocate memory for the temporary label Image*/
//m_UsedPointImage->SetRegions(this->GetInput()->GetLargestPossbileRegion());
//m_UsedPointImage->Allocate();
//m_UsedPointImage->FillBuffer(0);
/** Cast the MagnitudeOutput Image in */
typedef itk::CastImageFilter<InputImageType, OutputImageType> castFilerType;
typename castFilerType::Pointer castFilter = castFilerType::New();
......@@ -134,7 +128,6 @@ LineSegmentDetector<TInputImage,TPrecision >
* - A Line List m_LineList
*/
this->ComputeRectangles();
std::cout<<"UPUPUP"<<std::endl;
}
/**************************************************************************************************************/
......@@ -148,26 +141,23 @@ typename LineSegmentDetector<TInputImage,TPrecision >
LineSegmentDetector<TInputImage,TPrecision >
::SortImageByModulusValue(OutputImageType * modulusImage)
{
/* Size of the images **/
SizeType SizeInput = this->GetInput()->GetRequestedRegion().GetSize();
m_Width = SizeInput[0];
m_Length = SizeInput[1];
if(m_ImageSize[0]==0 && m_ImageSize[1]==0)
m_ImageSize = this->GetInput()->GetLargestPossibleRegion().GetSize();
//std::cout <<" m_Width"<<m_Width << " m_Length"<< m_Length << std::endl;
m_NumberOfImagePixels = m_Length * m_Width;
m_NumberOfImagePixels = static_cast<unsigned int>(m_ImageSize[1] * m_ImageSize[0]);
/**
* Compute the minimum region size
*/
double logNT = 5.*(vcl_log10(static_cast<double>(m_Width)) + vcl_log10(static_cast<double>(m_Length)))/2.;
double logNT = 5.*(vcl_log10(static_cast<double>(m_ImageSize[0])) + vcl_log10(static_cast<double>(m_ImageSize[1])))/2.;
double log1_p = vcl_log10(m_DirectionsAllowed);
double rapport = logNT/log1_p;
m_MinimumRegionSize = -1*static_cast<unsigned int>(rapport);
/** Definition of the min & the max of an image*/
OutputPixelType min = itk::NumericTraits</*MagnitudePixelType*/TPrecision>::Zero;
OutputPixelType max = itk::NumericTraits</*MagnitudePixelType*/TPrecision>::Zero;
OutputPixelType min = itk::NumericTraits<TPrecision>::Zero;
OutputPixelType max = itk::NumericTraits<TPrecision>::Zero;
/** Computing the min & max of the image*/
typedef itk::MinimumMaximumImageCalculator<OutputImageType> MinMaxCalculatorFilter;
......@@ -195,8 +185,8 @@ LineSegmentDetector<TInputImage,TPrecision >
while(!it.IsAtEnd())
{
OutputIndexType index = it.GetIndex();
if(static_cast<int>(index[0]) > 0 && static_cast<int>(index[0]) < m_Width-1
&& static_cast<int>(index[1]) >0 && static_cast<int>(index[1]) < m_Length-1 )
if(static_cast<int>(index[0]) > 0 && static_cast<int>(index[0]) < m_ImageSize[0]-1
&& static_cast<int>(index[1]) >0 && static_cast<int>(index[1]) < m_ImageSize[1]-1 )
{
unsigned int bin = static_cast<unsigned int> (it.Value()/lengthBin);
if( it.Value()- m_Threshold >1e-10 )
......@@ -273,14 +263,12 @@ LineSegmentDetector<TInputImage, TPrecision>
RectangleListTypeIterator itRec = m_RectangleList.begin();
while(itRec != m_RectangleList.end())
{
//double NFA = this->ImproveRectangle(&(*itRec) );
double NFA = this->ComputeRectNFA((*itRec));
/**
* Here we start building the OUTPUT :a LineSpatialObjectList.
*/
if(NFA > 0./** eps */)
if(NFA > 0.)
{
//std::cout << (*itRec)[0] << " " << (*itRec)[1] << " " << (*itRec)[2] << " " << (*itRec)[3]<<std::endl;
PointListType pointList;
PointType point;
......@@ -621,7 +609,7 @@ LineSegmentDetector<TInputImage, TPrecision>
typedef std::vector<MagnitudePixelType> MagnitudeVector;
unsigned int Diagonal = static_cast< unsigned int>(vnl_math_hypot(m_Length ,m_Width)) + 2;
unsigned int Diagonal = static_cast< unsigned int>(vnl_math_hypot(static_cast<double>(m_ImageSize[1]) ,static_cast<double>(m_ImageSize[0])) + 2);
MagnitudeVector sum_l( 2*Diagonal, itk::NumericTraits<MagnitudePixelType>::Zero);
MagnitudeVector sum_w( 2*Diagonal, itk::NumericTraits<MagnitudePixelType>::Zero);
......@@ -683,7 +671,7 @@ LineSegmentDetector<TInputImage, TPrecision>
*/
if(vcl_abs(wl - wr) - vcl_sqrt(static_cast<double>(m_Length*m_Length + m_Width*m_Width)) < 1e-10)
if(vcl_abs(wl - wr) - vcl_sqrt(static_cast<double>(m_ImageSize[1]*m_ImageSize[1] + m_ImageSize[0]*m_ImageSize[0])) < 1e-10)
{
RectangleType rec(8 ,0.); // Definition of a rectangle : 8 components
rec[0] = (x + lb*dx >0)?x + lb*dx:0.;
......@@ -792,34 +780,6 @@ LineSegmentDetector<TInputImage, TPrecision>
int NbAligned = 0;
double nfa_val = 0.;
//double dx = vcl_cos(rec[5]);
//double dy = vcl_sin(rec[5]);
//double halfWidth = rec[4]/2;
/** Determine the four corners of the rectangle*/
/** Remember :
* vec[0] = x1
* vec[1] = y1
* vec[2] = x2
* vec[3] = y2
* vec[4] = width
* vec[5] = theta
* vec[6] = prec = Pi/8
* vec[7] = p = 1/8
*/
// RectangleType X(4,0.) , Y(4,0.);
// X[0] = rec[0] + dy* halfWidth;
// Y[0] = rec[1] - dx* halfWidth;
// X[1] = rec[0] - dy* halfWidth;
// Y[1] = rec[1] + dx* halfWidth;
// X[2] = rec[2] + dy* halfWidth;
// Y[2] = rec[3] - dx* halfWidth;
// X[3] = rec[2] - dy* halfWidth;
// Y[3] = rec[3] + dx* halfWidth;
/** Compute the NFA of the rectangle
* We Need : The number of : Points in the rec (Area of the rectangle)
* Aligned points with theta in the rectangle
......@@ -863,7 +823,7 @@ LineSegmentDetector<TInputImage, TPrecision>
}
/** Compute the NFA from the rectangle computed below*/
double logNT = 5.*(vcl_log10(static_cast<double>(m_Length)) + vcl_log10(static_cast<double>(m_Width)))/2.;
double logNT = 5.*(vcl_log10(static_cast<double>(m_ImageSize[1])) + vcl_log10(static_cast<double>(m_ImageSize[0])))/2.;
nfa_val = NFA(pts,NbAligned ,m_DirectionsAllowed,logNT);
......
......@@ -43,6 +43,7 @@ int otbImageToLineSegmentVectorData( int argc, char * argv[] )
reader->SetFileName(argv[1]);
reader->GenerateOutputInformation();
lsdFilter->SetInput( reader->GetOutput() );
lsdFilter->SetThreadDistanceThreshold( 10. );
lsdFilter->Update();
writer->SetFileName(argv[2]);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment