@@ -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+
103149template <typename TInputImage, typename TOutputPath>
104150typename SpeedFunctionToPathFilter<TInputImage, TOutputPath>::InputImageType *
105151SpeedFunctionToPathFilter<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