Skip to content

Commit 23cfe3f

Browse files
richardbearethewtex
authored andcommitted
Facility for automatic estimation of termination value
1 parent b320bf9 commit 23cfe3f

File tree

2 files changed

+75
-4
lines changed

2 files changed

+75
-4
lines changed

include/itkSpeedFunctionToPathFilter.h

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,18 @@ class ITK_EXPORT SpeedFunctionToPathFilter :
159159
itkGetConstMacro( CurrentArrivalFunction, InputImagePointer );
160160

161161
/** Set/get the radius of target neighbourhood used to ensure smooth gradients */
162-
itkSetMacro( TargetRadius, typename InputImageType::SizeType::SizeValueType);
163-
itkGetConstMacro( TargetRadius, typename InputImageType::SizeType::SizeValueType);
162+
itkSetMacro( TargetRadius, typename InputImageType::SizeType::SizeValueType);
163+
itkGetConstMacro( TargetRadius, typename InputImageType::SizeType::SizeValueType);
164+
165+
/** Set/get the auto termination factor. The termination value is set to this factor
166+
multiplied by the minimum non zero difference between target point and
167+
neighbours */
168+
itkSetMacro( AutoTerminateFactor , double);
169+
itkGetConstMacro( AutoTerminateFactor , double);
170+
171+
itkSetMacro( AutoTerminate, bool );
172+
itkGetConstMacro( AutoTerminate, bool );
173+
itkBooleanMacro( AutoTerminate );
164174

165175
protected:
166176

@@ -181,12 +191,15 @@ itkGetConstMacro( TargetRadius, typename InputImageType::SizeType::SizeValueType
181191
const PointsContainerType & GetNextEndPoint( ) override;
182192

183193
IndexTypeSet GetNeighbors(IndexTypeVec idxs);
194+
InputImagePixelType GetTrialGradient(IndexTypeVec idxs);
184195

185196
std::vector< typename PathInformationType::Pointer > m_Information;
186197
InputImagePointer m_CurrentArrivalFunction;
187198

188199
typename InputImageType::SizeType::SizeValueType m_TargetRadius;
189200

201+
bool m_AutoTerminate;
202+
double m_AutoTerminateFactor;
190203
};
191204

192205
} // end namespace itk

include/itkSpeedFunctionToPathFilter.hxx

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ SpeedFunctionToPathFilter<TInputImage,TOutputPath>
3636
{
3737
m_CurrentArrivalFunction = nullptr;
3838
m_TargetRadius = 2;
39+
m_AutoTerminate = true;
40+
m_AutoTerminateFactor = 0.5;
3941
}
4042

4143

@@ -118,6 +120,48 @@ SpeedFunctionToPathFilter<TInputImage,TOutputPath>
118120
return(UniqueIndexes);
119121
}
120122

123+
template<typename TInputImage, typename TOutputPath>
124+
typename SpeedFunctionToPathFilter<TInputImage,TOutputPath>::InputImagePixelType
125+
SpeedFunctionToPathFilter<TInputImage,TOutputPath>
126+
::GetTrialGradient(IndexTypeVec idxs)
127+
{
128+
InputImagePointer arrival = m_CurrentArrivalFunction;
129+
130+
using BoundaryConditionType = ConstantBoundaryCondition<InputImageType>;
131+
132+
IndexTypeSet UniqueIndexes;
133+
typename InputImageType::SizeType radius;
134+
radius.Fill(1);
135+
ConstNeighborhoodIterator<InputImageType, BoundaryConditionType>
136+
niterator(radius, arrival, arrival->GetLargestPossibleRegion());
137+
138+
BoundaryConditionType bc;
139+
bc.SetConstant(itk::NumericTraits<InputImagePixelType>::max());
140+
niterator.SetBoundaryCondition(bc);
141+
niterator.NeedToUseBoundaryConditionOn();
142+
143+
// looking for the smallest nonzero difference
144+
InputImagePixelType mindiff(itk::NumericTraits<InputImagePixelType>::max());
145+
146+
for (auto it = idxs.begin(); it != idxs.end(); it++ )
147+
{
148+
niterator.SetLocation(*it);
149+
InputImagePixelType CP = niterator.GetCenterPixel();
150+
// Visit the entire neighborhood (including center) and
151+
// add any pixel that has a nonzero arrival function value
152+
for (auto NB = 0; NB < niterator.Size(); NB++)
153+
{
154+
// CP values should always be zero
155+
InputImagePixelType NPD = niterator.GetPixel(NB) - CP;
156+
if (NPD > 0 )
157+
{
158+
mindiff=std::min(mindiff, NPD);
159+
}
160+
}
161+
}
162+
163+
return(mindiff);
164+
}
121165
/**
122166
*
123167
*/
@@ -139,7 +183,6 @@ SpeedFunctionToPathFilter<TInputImage,TOutputPath>
139183
marching->SetInput( speed );
140184
marching->SetGenerateGradientImage( false );
141185
marching->SetTargetReachedModeToAllTargets( );
142-
//marching->SetTargetOffset( 2.0 * Superclass::m_TerminationValue);
143186
// Add next and previous front sources as target points to
144187
// limit the front propagation to just the required zones
145188
PointsContainerType PrevFront = m_Information[Superclass::m_CurrentOutput]->PeekPreviousFront();
@@ -156,6 +199,7 @@ SpeedFunctionToPathFilter<TInputImage,TOutputPath>
156199
NodeType nodeTargetPrevious;
157200
speed->TransformPhysicalPointToIndex( *it, indexTargetPrevious );
158201
PrevIndexVec.push_back(indexTargetPrevious);
202+
//std::cerr << "PrevTarg " << indexTargetPrevious << std::endl;
159203
}
160204

161205
for (auto it = NextFront.begin(); it != NextFront.end(); it++)
@@ -164,6 +208,8 @@ SpeedFunctionToPathFilter<TInputImage,TOutputPath>
164208
NodeType nodeTargetNext;
165209
speed->TransformPhysicalPointToIndex( *it, indexTargetNext );
166210
NextIndexVec.push_back(indexTargetNext);
211+
//std::cerr << "NextTarg " << indexTargetNext << std::endl;
212+
167213
}
168214

169215
IndexTypeVec AllTargets( PrevIndexVec );
@@ -197,6 +243,8 @@ SpeedFunctionToPathFilter<TInputImage,TOutputPath>
197243
nodeTrial.SetIndex( indexTrial );
198244
trial->InsertElement( trial->Size(), nodeTrial );
199245
CurrentIndexVec.push_back(indexTrial);
246+
//std::cerr << "TrialPt " << indexTrial << std::endl;
247+
200248
}
201249
marching->SetTrialPoints( trial );
202250

@@ -222,9 +270,19 @@ SpeedFunctionToPathFilter<TInputImage,TOutputPath>
222270
m_Information[Superclass::m_CurrentOutput]->SetPrevious(PrevFront[MinPos]);
223271
}
224272

273+
if (m_AutoTerminate)
274+
{
275+
// Examine the neighbours of the trial points to determine the minimum neighbour
276+
// difference, for the purpose of estimating a good termination value.
277+
InputImagePixelType MD = GetTrialGradient( CurrentIndexVec );
278+
std::cout << "Min diff for termination = " << MD << std::endl;
279+
this->SetTerminationValue( MD * this->GetAutoTerminateFactor() );
280+
}
225281
// Make the arrival function flat inside the seeds, otherwise the
226282
// optimizer will cross over them. This only matters if the seeds are extended
227-
if (CurrentIndexVec.size() > 1)
283+
// Not sure that this is needed any more. Expect it was a side effect of only
284+
// adding a single point to the trial set.
285+
if ( CurrentIndexVec.size() > 1 )
228286
{
229287
for (auto vi = CurrentIndexVec.begin(); vi != CurrentIndexVec.end(); vi++)
230288
{

0 commit comments

Comments
 (0)