@@ -33,6 +33,8 @@ SpeedFunctionToPathFilter<TInputImage,TOutputPath>
33
33
m_CurrentArrivalFunction( nullptr )
34
34
{
35
35
m_TargetRadius = 2 ;
36
+ m_AutoTerminate = true ;
37
+ m_AutoTerminateFactor = 0.5 ;
36
38
}
37
39
38
40
@@ -106,6 +108,51 @@ SpeedFunctionToPathFilter<TInputImage,TOutputPath>
106
108
return (UniqueIndexes);
107
109
}
108
110
111
+
112
+ template <typename TInputImage, typename TOutputPath>
113
+ typename SpeedFunctionToPathFilter<TInputImage,TOutputPath>::InputImagePixelType
114
+ SpeedFunctionToPathFilter<TInputImage,TOutputPath>
115
+ ::GetTrialGradient (IndexTypeVec idxs)
116
+ {
117
+ InputImagePointer arrival = m_CurrentArrivalFunction;
118
+
119
+ using BoundaryConditionType = ConstantBoundaryCondition<InputImageType>;
120
+
121
+ IndexTypeSet UniqueIndexes;
122
+ typename InputImageType::SizeType radius;
123
+ radius.Fill (1 );
124
+ ConstNeighborhoodIterator<InputImageType, BoundaryConditionType>
125
+ niterator (radius, arrival, arrival->GetLargestPossibleRegion ());
126
+
127
+ BoundaryConditionType bc;
128
+ bc.SetConstant (itk::NumericTraits<InputImagePixelType>::max ());
129
+ niterator.SetBoundaryCondition (bc);
130
+ niterator.NeedToUseBoundaryConditionOn ();
131
+
132
+ // looking for the smallest nonzero difference
133
+ InputImagePixelType mindiff (itk::NumericTraits<InputImagePixelType>::max ());
134
+
135
+ for (auto it = idxs.begin (); it != idxs.end (); it++ )
136
+ {
137
+ niterator.SetLocation (*it);
138
+ InputImagePixelType CP = niterator.GetCenterPixel ();
139
+ // Visit the entire neighborhood (including center) and
140
+ // add any pixel that has a nonzero arrival function value
141
+ for (auto NB = 0 ; NB < niterator.Size (); NB++)
142
+ {
143
+ // CP values should always be zero
144
+ InputImagePixelType NPD = niterator.GetPixel (NB) - CP;
145
+ if (NPD > 0 )
146
+ {
147
+ mindiff=std::min (mindiff, NPD);
148
+ }
149
+ }
150
+ }
151
+
152
+ return (mindiff);
153
+ }
154
+
155
+
109
156
template <typename TInputImage, typename TOutputPath>
110
157
typename SpeedFunctionToPathFilter<TInputImage,TOutputPath>::InputImageType *
111
158
SpeedFunctionToPathFilter<TInputImage,TOutputPath>
@@ -124,7 +171,6 @@ SpeedFunctionToPathFilter<TInputImage,TOutputPath>
124
171
marching->SetInput ( speed );
125
172
marching->SetGenerateGradientImage ( false );
126
173
marching->SetTargetReachedModeToAllTargets ( );
127
- // marching->SetTargetOffset( 2.0 * Superclass::m_TerminationValue);
128
174
// Add next and previous front sources as target points to
129
175
// limit the front propagation to just the required zones
130
176
PointsContainerType PrevFront = m_Information[Superclass::m_CurrentOutput]->PeekPreviousFront ();
@@ -141,6 +187,7 @@ SpeedFunctionToPathFilter<TInputImage,TOutputPath>
141
187
NodeType nodeTargetPrevious;
142
188
speed->TransformPhysicalPointToIndex ( *it, indexTargetPrevious );
143
189
PrevIndexVec.push_back (indexTargetPrevious);
190
+ // std::cerr << "PrevTarg " << indexTargetPrevious << std::endl;
144
191
}
145
192
146
193
for (auto it = NextFront.begin (); it != NextFront.end (); it++)
@@ -149,6 +196,8 @@ SpeedFunctionToPathFilter<TInputImage,TOutputPath>
149
196
NodeType nodeTargetNext;
150
197
speed->TransformPhysicalPointToIndex ( *it, indexTargetNext );
151
198
NextIndexVec.push_back (indexTargetNext);
199
+ // std::cerr << "NextTarg " << indexTargetNext << std::endl;
200
+
152
201
}
153
202
154
203
IndexTypeVec AllTargets ( PrevIndexVec );
@@ -182,6 +231,8 @@ SpeedFunctionToPathFilter<TInputImage,TOutputPath>
182
231
nodeTrial.SetIndex ( indexTrial );
183
232
trial->InsertElement ( trial->Size (), nodeTrial );
184
233
CurrentIndexVec.push_back (indexTrial);
234
+ // std::cerr << "TrialPt " << indexTrial << std::endl;
235
+
185
236
}
186
237
marching->SetTrialPoints ( trial );
187
238
@@ -207,9 +258,19 @@ SpeedFunctionToPathFilter<TInputImage,TOutputPath>
207
258
m_Information[Superclass::m_CurrentOutput]->SetPrevious (PrevFront[MinPos]);
208
259
}
209
260
261
+ if (m_AutoTerminate)
262
+ {
263
+ // Examine the neighbours of the trial points to determine the minimum neighbour
264
+ // difference, for the purpose of estimating a good termination value.
265
+ InputImagePixelType MD = GetTrialGradient ( CurrentIndexVec );
266
+ std::cout << " Min diff for termination = " << MD << std::endl;
267
+ this ->SetTerminationValue ( MD * this ->GetAutoTerminateFactor () );
268
+ }
210
269
// Make the arrival function flat inside the seeds, otherwise the
211
270
// optimizer will cross over them. This only matters if the seeds are extended
212
- if (CurrentIndexVec.size () > 1 )
271
+ // Not sure that this is needed any more. Expect it was a side effect of only
272
+ // adding a single point to the trial set.
273
+ if ( CurrentIndexVec.size () > 1 )
213
274
{
214
275
for (auto vi = CurrentIndexVec.begin (); vi != CurrentIndexVec.end (); vi++)
215
276
{
0 commit comments