@@ -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