Skip to content

Commit 5a6fddd

Browse files
richardbearethewtex
authored andcommitted
Facility for automatic estimation of termination value
1 parent 4b38a9b commit 5a6fddd

File tree

2 files changed

+78
-4
lines changed

2 files changed

+78
-4
lines changed

include/itkSpeedFunctionToPathFilter.h

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

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

166176
protected:
167177

@@ -182,12 +192,15 @@ itkGetConstMacro( TargetRadius, typename InputImageType::SizeType::SizeValueType
182192
const PointsContainerType & GetNextEndPoint( ) override;
183193

184194
IndexTypeSet GetNeighbors(IndexTypeVec idxs);
195+
InputImagePixelType GetTrialGradient(IndexTypeVec idxs);
185196

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

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

202+
bool m_AutoTerminate;
203+
double m_AutoTerminateFactor;
191204
};
192205

193206
} // end namespace itk

include/itkSpeedFunctionToPathFilter.hxx

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ SpeedFunctionToPathFilter<TInputImage,TOutputPath>
3333
m_CurrentArrivalFunction( nullptr )
3434
{
3535
m_TargetRadius = 2;
36+
m_AutoTerminate = true;
37+
m_AutoTerminateFactor = 0.5;
3638
}
3739

3840

@@ -106,6 +108,51 @@ SpeedFunctionToPathFilter<TInputImage,TOutputPath>
106108
return(UniqueIndexes);
107109
}
108110

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+
109156
template<typename TInputImage, typename TOutputPath>
110157
typename SpeedFunctionToPathFilter<TInputImage,TOutputPath>::InputImageType *
111158
SpeedFunctionToPathFilter<TInputImage,TOutputPath>
@@ -124,7 +171,6 @@ SpeedFunctionToPathFilter<TInputImage,TOutputPath>
124171
marching->SetInput( speed );
125172
marching->SetGenerateGradientImage( false );
126173
marching->SetTargetReachedModeToAllTargets( );
127-
//marching->SetTargetOffset( 2.0 * Superclass::m_TerminationValue);
128174
// Add next and previous front sources as target points to
129175
// limit the front propagation to just the required zones
130176
PointsContainerType PrevFront = m_Information[Superclass::m_CurrentOutput]->PeekPreviousFront();
@@ -141,6 +187,7 @@ SpeedFunctionToPathFilter<TInputImage,TOutputPath>
141187
NodeType nodeTargetPrevious;
142188
speed->TransformPhysicalPointToIndex( *it, indexTargetPrevious );
143189
PrevIndexVec.push_back(indexTargetPrevious);
190+
//std::cerr << "PrevTarg " << indexTargetPrevious << std::endl;
144191
}
145192

146193
for (auto it = NextFront.begin(); it != NextFront.end(); it++)
@@ -149,6 +196,8 @@ SpeedFunctionToPathFilter<TInputImage,TOutputPath>
149196
NodeType nodeTargetNext;
150197
speed->TransformPhysicalPointToIndex( *it, indexTargetNext );
151198
NextIndexVec.push_back(indexTargetNext);
199+
//std::cerr << "NextTarg " << indexTargetNext << std::endl;
200+
152201
}
153202

154203
IndexTypeVec AllTargets( PrevIndexVec );
@@ -182,6 +231,8 @@ SpeedFunctionToPathFilter<TInputImage,TOutputPath>
182231
nodeTrial.SetIndex( indexTrial );
183232
trial->InsertElement( trial->Size(), nodeTrial );
184233
CurrentIndexVec.push_back(indexTrial);
234+
//std::cerr << "TrialPt " << indexTrial << std::endl;
235+
185236
}
186237
marching->SetTrialPoints( trial );
187238

@@ -207,9 +258,19 @@ SpeedFunctionToPathFilter<TInputImage,TOutputPath>
207258
m_Information[Superclass::m_CurrentOutput]->SetPrevious(PrevFront[MinPos]);
208259
}
209260

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+
}
210269
// Make the arrival function flat inside the seeds, otherwise the
211270
// 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 )
213274
{
214275
for (auto vi = CurrentIndexVec.begin(); vi != CurrentIndexVec.end(); vi++)
215276
{

0 commit comments

Comments
 (0)