Commit 24587a42 authored by Cédric Traizet's avatar Cédric Traizet

STYLE : 80 characters rule

parent e1b2b1e5
......@@ -45,12 +45,14 @@ public:
typedef UInt32ImageType LabelImageType;
typedef LabelImageType::InternalPixelType LabelImagePixelType;
//typedef otb::StreamingStatisticsImageFilter<LabelImageType> StatisticsImageFilterType;
typedef otb::StreamingStatisticsMapFromLabelImageFilter<ImageType, LabelImageType> StatisticsMapFromLabelImageFilterType;
typedef otb::StreamingStatisticsMapFromLabelImageFilter
<ImageType, LabelImageType> StatisticsMapFromLabelImageFilterType;
typedef otb::LabelImageSmallRegionMergingFilter<LabelImageType> LabelImageSmallRegionMergingFilterType;
typedef otb::LabelImageSmallRegionMergingFilter<LabelImageType>
LabelImageSmallRegionMergingFilterType;
typedef itk::ChangeLabelImageFilter<LabelImageType,LabelImageType> ChangeLabelImageFilterType;
typedef itk::ChangeLabelImageFilter<LabelImageType,LabelImageType>
ChangeLabelImageFilterType;
itkNewMacro(Self);
itkTypeMacro(Merging, otb::Application);
......@@ -61,34 +63,43 @@ private:
void DoInit() override
{
SetName("SmallRegionsMerging");
SetDescription("This application merges small regions of a segmentation result to connected region.");
SetDescription("This application merges small regions of a segmentation "
"result to connected region.");
SetDocName("Small Region Merging");
SetDocLongDescription("Given a segmentation result and the original image, it will"
" merge segments whose size in pixels is lower than minsize parameter"
" with the adjacent segments with the adjacent segment with closest"
" radiometry and acceptable size.\n\n"
"Small segments will be processed by increasing size: first all segments"
" for which area is equal to 1 pixel will be merged with adjacent"
" segments, then all segments of area equal to 2 pixels will be processed,"
" until segments of area minsize.");
SetDocLongDescription("Given a segmentation result and the original image,"
" it will merge segments whose size in pixels is"
" lower than minsize parameter with the adjacent"
" segments with the adjacent segment with closest"
" radiometry and acceptable size. \n\n"
"Small segments will be processed by increasing size:"
" first all segments for which area is equal to 1"
" pixel will be merged with adjacent segments, then"
" all segments of area equal to 2 pixels will be"
" processed, until segments of area minsize.");
SetDocLimitations("This application is more efficient if the labels are contiguous, starting from 0.");
SetDocAuthors("OTB-Team");
SetDocSeeAlso( "Segmentation");
SetDocSeeAlso("Segmentation");
AddDocTag(Tags::Segmentation);
AddParameter(ParameterType_InputImage, "in", "Input image");
SetParameterDescription( "in", "The input image, containing initial spectral signatures corresponding to the segmented image (inseg)." );
AddParameter(ParameterType_InputImage, "inseg", "Segmented image");
SetParameterDescription( "inseg", "Segmented image where each pixel value is the unique integer label of the segment it belongs to." );
SetParameterDescription( "in", "The input image, containing initial"
" spectral signatures corresponding to the segmented image (inseg)." );
AddParameter(ParameterType_InputImage, "inseg", "Segmented image");
SetParameterDescription( "inseg", "Segmented image where each pixel value"
" is the unique integer label of the segment it belongs to." );
AddParameter(ParameterType_OutputImage, "out", "Output Image");
SetParameterDescription( "out", "The output image. The output image is the segmented image where the minimal segments have been merged." );
SetParameterDescription( "out", "The output image. The output image is the"
" segmented image where the minimal segments have been merged." );
SetDefaultOutputPixelType("out",ImagePixelType_uint32);
AddParameter(ParameterType_Int, "minsize", "Minimum Segment Size");
SetParameterDescription("minsize", "Minimum Segment Size. If, after the segmentation, a segment is of size strictly lower than this criterion, the segment is merged with the segment that has the closest sepctral signature.");
SetParameterDescription("minsize", "Minimum Segment Size. If, after the "
" segmentation, a segment is of size strictly lower than this criterion,"
" the segment is merged with the segment that has the closest sepctral"
" signature.");
SetDefaultParameterInt("minsize", 50);
SetMinimumParameterIntValue("minsize", 1);
MandatoryOff("minsize");
......@@ -123,7 +134,8 @@ private:
auto labelStatsFilter = StatisticsMapFromLabelImageFilterType::New();
labelStatsFilter->SetInput(imageIn);
labelStatsFilter->SetInputLabelImage(labelIn);
AddProcess(labelStatsFilter->GetStreamer() , "Computing stats on input image ...");
AddProcess(labelStatsFilter->GetStreamer() , "Computing stats on input"
" image ...");
labelStatsFilter->Update();
// Convert Map to Unordered map
......@@ -135,18 +147,19 @@ private:
labelPopulation[population.first]=population.second;
}
auto meanValueMap = labelStatsFilter->GetMeanValueMap();
std::unordered_map< unsigned int, itk::VariableLengthVector<double> > meanValues;
std::unordered_map< unsigned int, itk::VariableLengthVector<double> >
meanValues;
for (const auto & mean : meanValueMap)
{
meanValues[mean.first] = mean.second;
}
// Compute the LUT from the original label image to the merged output label image.
// Compute the LUT from the original label image to the merged output
// label image.
auto regionMergingFilter = LabelImageSmallRegionMergingFilterType::New();
regionMergingFilter->SetInputLabelImage( labelIn );
regionMergingFilter->SetLabelPopulation( labelPopulation );
regionMergingFilter->SetLabelStatistic( meanValues );
regionMergingFilter->SetMinSize( minSize);
AddProcess(regionMergingFilter, "Computing LUT ...");
......@@ -168,7 +181,8 @@ private:
SetParameterOutputImage("out", changeLabelFilter->GetOutput());
RegisterPipeline();
clock_t toc = clock();
otbAppLogINFO(<<"Elapsed time: "<<(double)(toc - tic) / CLOCKS_PER_SEC<<" seconds");
otbAppLogINFO(<<"Elapsed time: "<<(double)(toc - tic) / CLOCKS_PER_SEC<<
" seconds");
}
};
......
......@@ -49,17 +49,21 @@ PersistentLabelImageSmallRegionMergingFilter< TInputLabelImage >
::Synthetize()
{
NeigboursMapType neighboursMap;
// Merge the neighbours maps from all threads
for( unsigned int threadId = 0; threadId < this->GetNumberOfThreads(); threadId++)
for( unsigned int threadId = 0; threadId < this->GetNumberOfThreads();
threadId++)
{
for (auto const & neighbours : m_NeighboursMapsTmp[threadId])
{
neighboursMap[ neighbours.first ].insert( neighbours.second.begin(), neighbours.second.end() );
neighboursMap[ neighbours.first ].insert
( neighbours.second.begin(), neighbours.second.end() );
}
}
// For each label of the label map, find the "closest" connected label, according
// to the euclidian distance between the corresponding m_labelStatistic elements.
// For each label of the label map, find the "closest" connected label,
// according to the euclidian distance between the corresponding
// m_labelStatistic elements.
for (auto const & neighbours : neighboursMap)
{
double proximity = itk::NumericTraits<double>::max();
......@@ -82,6 +86,8 @@ PersistentLabelImageSmallRegionMergingFilter< TInputLabelImage >
auto curLabelLUT = FindCorrespondingLabel(label);
auto adjLabelLUT = FindCorrespondingLabel(closestNeighbour);
// Keep the smallest label (this prevents infinite loop in the LUT
// (like LUT[i]=j and LUT[j]=i)
if(curLabelLUT < adjLabelLUT)
{
m_LUT[adjLabelLUT] = curLabelLUT;
......@@ -98,24 +104,31 @@ PersistentLabelImageSmallRegionMergingFilter< TInputLabelImage >
label.second = FindCorrespondingLabel( label.first );
}
// Update statistics
// Update statistics : for each newly merged segments, sum the population, and
// recompute the mean.
for (auto label : m_LUT)
{
if((m_LabelPopulation[label.first]!=0) && (label.second != label.first))
{
m_LabelStatistic[ label.second ] = (m_LabelStatistic[label.second]*m_LabelPopulation[label.second] +
m_LabelStatistic[label.first]*m_LabelPopulation[label.first] ) / (m_LabelPopulation[label.first]+m_LabelPopulation[label.second]);
m_LabelStatistic[ label.second ] =
( m_LabelStatistic[label.first]*m_LabelPopulation[label.first]
+ m_LabelStatistic[label.second]*m_LabelPopulation[label.second] )
/ (m_LabelPopulation[label.first]+m_LabelPopulation[label.second]);
m_LabelPopulation[ label.second ] += m_LabelPopulation[ label.first ] ;
// Do not use this label anymore
m_LabelPopulation[ label.first ] = 0;
}
}
}
template <class TInputLabelImage >
typename PersistentLabelImageSmallRegionMergingFilter< TInputLabelImage >::InputLabelType
typename PersistentLabelImageSmallRegionMergingFilter< TInputLabelImage >
::InputLabelType
PersistentLabelImageSmallRegionMergingFilter< TInputLabelImage >
::FindCorrespondingLabel( typename PersistentLabelImageSmallRegionMergingFilter< TInputLabelImage >
::InputLabelType label)
::FindCorrespondingLabel( typename PersistentLabelImageSmallRegionMergingFilter
< TInputLabelImage >::InputLabelType label)
{
auto correspondingLabel = m_LUT[label];
while (label != correspondingLabel)
......@@ -160,7 +173,8 @@ PersistentLabelImageSmallRegionMergingFilter< TInputLabelImage >
// build an exception
itk::InvalidRequestedRegionError e(__FILE__, __LINE__);
e.SetLocation(ITK_LOCATION);
e.SetDescription("Requested region is (at least partially) outside the largest possible region.");
e.SetDescription("Requested region is (at least partially) outside the "
"largest possible region.");
e.SetDataObject(inputPtr);
throw e;
}
......@@ -170,10 +184,12 @@ PersistentLabelImageSmallRegionMergingFilter< TInputLabelImage >
template <class TInputLabelImage >
void
PersistentLabelImageSmallRegionMergingFilter< TInputLabelImage >
::ThreadedGenerateData(const RegionType& outputRegionForThread, itk::ThreadIdType threadId )
::ThreadedGenerateData(const RegionType& outputRegionForThread,
itk::ThreadIdType threadId )
{
using IteratorType = itk::ImageRegionConstIterator< TInputLabelImage >;
using NeighborhoodIteratorType = itk::ConstShapedNeighborhoodIterator< TInputLabelImage >;
using NeighborhoodIteratorType =
itk::ConstShapedNeighborhoodIterator< TInputLabelImage >;
typename NeighborhoodIteratorType::RadiusType radius;
radius.Fill(1);
......@@ -204,7 +220,7 @@ PersistentLabelImageSmallRegionMergingFilter< TInputLabelImage >
{
int neighbourLabel = m_LUT[ ci.Get() ];
if (neighbourLabel != currentLabel)
m_NeighboursMapsTmp[threadId][ currentLabel ].insert( neighbourLabel );
m_NeighboursMapsTmp[threadId][ currentLabel ].insert(neighbourLabel);
}
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment