Skip to content

Commit 51455fd

Browse files
richardbeareromangrothausmann
authored andcommitted
Facility for automatic estimation of termination value
1 parent 40d2cb0 commit 51455fd

File tree

2 files changed

+72
-3
lines changed

2 files changed

+72
-3
lines changed

include/itkSpeedFunctionToPathFilter.h

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,18 @@ class ITK_TEMPLATE_EXPORT SpeedFunctionToPathFilter : public ArrivalFunctionToPa
164164
itkGetConstMacro(CurrentArrivalFunction, InputImagePointer);
165165

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

170180
protected:
171181
SpeedFunctionToPathFilter();
@@ -190,11 +200,15 @@ itkGetConstMacro( TargetRadius, typename InputImageType::SizeType::SizeValueType
190200
GetNextEndPoint() override;
191201

192202
IndexTypeSet GetNeighbors(IndexTypeVec idxs);
203+
InputImagePixelType GetTrialGradient(IndexTypeVec idxs);
193204

194205
std::vector<typename PathInformationType::Pointer> m_Information;
195206
InputImagePointer m_CurrentArrivalFunction;
196207

197208
typename InputImageType::SizeType::SizeValueType m_TargetRadius;
209+
210+
bool m_AutoTerminate;
211+
double m_AutoTerminateFactor;
198212
};
199213

200214
} // end namespace itk

include/itkSpeedFunctionToPathFilter.hxx

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ SpeedFunctionToPathFilter<TInputImage, TOutputPath>::SpeedFunctionToPathFilter()
3232
: m_CurrentArrivalFunction(nullptr)
3333
{
3434
m_TargetRadius = 2;
35+
m_AutoTerminate = true;
36+
m_AutoTerminateFactor = 0.5;
3537
}
3638

3739

@@ -100,6 +102,50 @@ SpeedFunctionToPathFilter<TInputImage,TOutputPath>
100102
return(UniqueIndexes);
101103
}
102104

105+
106+
template <typename TInputImage, typename TOutputPath>
107+
typename SpeedFunctionToPathFilter<TInputImage,TOutputPath>::InputImagePixelType
108+
SpeedFunctionToPathFilter<TInputImage,TOutputPath>::GetTrialGradient(IndexTypeVec idxs)
109+
{
110+
InputImagePointer arrival = m_CurrentArrivalFunction;
111+
112+
using BoundaryConditionType = ConstantBoundaryCondition<InputImageType>;
113+
114+
IndexTypeSet UniqueIndexes;
115+
typename InputImageType::SizeType radius;
116+
radius.Fill(1);
117+
ConstNeighborhoodIterator<InputImageType, BoundaryConditionType>
118+
niterator(radius, arrival, arrival->GetLargestPossibleRegion());
119+
120+
BoundaryConditionType bc;
121+
bc.SetConstant(itk::NumericTraits<InputImagePixelType>::max());
122+
niterator.SetBoundaryCondition(bc);
123+
niterator.NeedToUseBoundaryConditionOn();
124+
125+
// looking for the smallest nonzero difference
126+
InputImagePixelType mindiff(itk::NumericTraits<InputImagePixelType>::max());
127+
128+
for (auto it = idxs.begin(); it != idxs.end(); it++ )
129+
{
130+
niterator.SetLocation(*it);
131+
InputImagePixelType CP = niterator.GetCenterPixel();
132+
// Visit the entire neighborhood (including center) and
133+
// add any pixel that has a nonzero arrival function value
134+
for (auto NB = 0; NB < niterator.Size(); NB++)
135+
{
136+
// CP values should always be zero
137+
InputImagePixelType NPD = niterator.GetPixel(NB) - CP;
138+
if (NPD > 0 )
139+
{
140+
mindiff=std::min(mindiff, NPD);
141+
}
142+
}
143+
}
144+
145+
return(mindiff);
146+
}
147+
148+
103149
template <typename TInputImage, typename TOutputPath>
104150
typename SpeedFunctionToPathFilter<TInputImage, TOutputPath>::InputImageType *
105151
SpeedFunctionToPathFilter<TInputImage, TOutputPath>::ComputeArrivalFunction()
@@ -141,7 +187,6 @@ SpeedFunctionToPathFilter<TInputImage, TOutputPath>::ComputeArrivalFunction()
141187
speed->TransformPhysicalPointToIndex(*it, indexTargetNext);
142188
NextIndexVec.push_back(indexTargetNext);
143189
}
144-
145190
IndexTypeVec AllTargets( PrevIndexVec );
146191
AllTargets.insert(AllTargets.end(), NextIndexVec.begin(), NextIndexVec.end());
147192

@@ -200,8 +245,18 @@ SpeedFunctionToPathFilter<TInputImage, TOutputPath>::ComputeArrivalFunction()
200245
m_Information[Superclass::m_CurrentOutput]->SetPrevious(PrevFront[MinPos]);
201246
}
202247

248+
if (m_AutoTerminate)
249+
{
250+
// Examine the neighbours of the trial points to determine the minimum neighbour
251+
// difference, for the purpose of estimating a good termination value.
252+
InputImagePixelType MD = GetTrialGradient( CurrentIndexVec );
253+
std::cout << "Min diff for termination = " << MD << std::endl;
254+
this->SetTerminationValue( MD * this->GetAutoTerminateFactor() );
255+
}
203256
// Make the arrival function flat inside the seeds, otherwise the
204257
// optimizer will cross over them. This only matters if the seeds are extended
258+
// Not sure that this is needed any more. Expect it was a side effect of only
259+
// adding a single point to the trial set.
205260
if (CurrentIndexVec.size() > 1)
206261
{
207262
for (auto vi = CurrentIndexVec.begin(); vi != CurrentIndexVec.end(); vi++)

0 commit comments

Comments
 (0)