[Insight-users] Fwd: problem with ParallelSparseFieldLevelSetImageFilter - Fix
Luca Antiga
luca.antiga at gmail.com
Wed Jul 30 06:02:20 EDT 2008
Hey,
so I looked into the issue with the
ParallelSparseFieldLevelSetImageFilter
Luis, I need your wisdom here (sorry for the long message ahead).
As the documentation for itk::LevelSetFunction says:
* \warning You MUST call Initialize() in the constructor of
subclasses of this
* object to set it up properly to do level-set Calculations. The
argument
* that you pass Initialize is the radius of the neighborhood needed
to perform
* the calculations. If your subclass does not do any additional
neighborhood
* processing, then the default radius should be 1 in each direction.
Now, this is pretty high up in the hierarchy, so the message is very
likely not to be read by users that are doing what Kun rightfully
wants to do.
To me, this call
> ThresholdFunctionType::RadiusType r;
> r[0] = r[1] = r[2] =1;
> m_LevelSetFunction->Initialize(r);
shouldn't be required when using SparseFieldImageFilter directly, as
in Kun's case.
In usual level set filters, the Initialize(r) method is called in
itk::SegmentationLevelSetImageFilter::SetSegmentationFunction,
which does the following
virtual void SetSegmentationFunction(SegmentationFunctionType *s)
{
m_SegmentationFunction = s;
typename SegmentationFunctionType::RadiusType r;
r.Fill( 1 );
m_SegmentationFunction->Initialize(r);
this->SetDifferenceFunction(m_SegmentationFunction);
this->Modified();
}
One drawback is that initialize is called with radius of 1, and it a
function subclass needs a radius of 2 it has to call Initialize(r)
again but forcibly after the SetSegmentationFunction call, which it's
not clean (and not documented).
Now, to me a concrete level set function should know what
neighborhood radius it uses by default and should be able to set it
up independently from the image filter, it shouldn't be up to the
image filter to set it.
In fact, the documentation for LevelSetFunction says that Initialize
should be called in the constructor of subclasses.
One option could be to call Initialize(r) in the constructor of all
concrete subclasses and remove it from SetSegmentationFunction
(We can't call it once for all in the constructor of
itk::SegmentationLevelSetFunction because Initialize is virtual and
it's being overridden in the subclasses).
This is a backward incompatible change, because people who coded
custom level set functions should also add the call to Initialize(r)
in the constructor.
There is a backward compatible option:
- to introduce a Initialize() method (without the radius as an
argument) that uses the m_Radius member in FiniteDifferenceFunction.
- set m_Radius to some proper value in the constructors of subclasses
(or default it to 1 in the constructor of
itk::SegmentationLevelSetFunction)
- modify SetSegmentationFunction in this way:
if m_Radius is zero in all directions (the way it's set in the
constructor of FiniteDifferenceFunction), use the Initialize(r)
signature with radius 1 the way it is now;
else, use Initialize(), which uses m_Radius;
This way we keep backward compatibility and give level set functions
a chance to have a radius != 1.
In this case, the user is required to call function->Initialize()
before using it, but at least he/she doesn't deal with radius.
Last, we could make itk::LevelSetFunction throw an exception if it's
being used uninitialized (which would require the addition of a
initialized state flag), in order to avoid plain crashes like the one
Kun reported.
I hope the above is intelligible... it's easier to do it than to
write about it for sure :-)
Luca
On Jul 30, 2008, at 1:10 AM, Kun wrote:
> Thanks, Luca,
>
> I have found the problem. The LevelSetFunction should be
> initialized first,otherwise the radius will set 0, then such an
> error happens. Also, it seems that the SpeedImage should be
> calculated before sending to the parallelfilter.
>
> The code as follows:
>
> m_LevelSetFunction = ThresholdFunctionType::New();
> m_LevelSetFunction -> SetUpperThreshold(150);
> m_LevelSetFunction -> SetLowerThreshold(100);
> m_LevelSetFunction -> SetFeatureImage(SourceImage);
>
> ThresholdFunctionType::RadiusType r;
> r[0] = r[1] = r[2] =1;
> m_LevelSetFunction->Initialize(r);
>
> m_LevelSetFunction->AllocateSpeedImage();
> m_LevelSetFunction->CalculateSpeedImage();
>
> parallelfilter = ParallelSparseFieldFilterType::New();
> parallelfilter -> SetInput(InitImage);
> parallelfilter -> SetNumberOfLayers(3);
> parallelfilter -> SetIsoSurfaceValue(0.0);
> parallelfilter -> SetDifferenceFunction
> (m_LevelSetFunction);
> parallelfilter -> Update();
>
>
> Appreciate and Thanks all.
>
> Kun
>
> From: Luca Antiga <luca.antiga at gmail.com>
> Date: Tue, Jul 29, 2008 at 10:59 AM
> Subject: Re: [Insight-users] problem with
> ParallelSparseFieldLevelSetImageFilter
> To: ITK Users <insight-users at itk.org>
>
>
> Dear Kun,
> I'll try to reproduce the problem and get back to you.
> Keep in touch
>
> Luca
>
>
>
>
>
>
>
> _______________________________________________
> Insight-users mailing list
> Insight-users at itk.org
> http://www.itk.org/mailman/listinfo/insight-users
More information about the Insight-users
mailing list