[Insight-users] Combining CompositeFilterExample and CannyEdgeDetectionImageFilter

Dan Mueller d.mueller at qut.edu.au
Sun Jul 2 20:19:04 EDT 2006


Hi Sholomo,

Here are my attempted answers to your questions:

1. Why divide the pipeline setup and execution between the constructor 
and GenerateData(.) method? The main reason stems from the usage of the 
pipeline: when a filter parameter is modified, the GenerateData(.) 
methods for all upstream filters are re-executed to update the pipeline 
result. If the code setting up the pipeline is included in the 
GenerateData(.) method, it will be unnecessarily executed again when a 
filter is updated. *Simple answer*=save unnecessary computation.

2. Why is GraftOutput(.) called on both the last filter in the pipeline 
and the composite filter itself? I am not an expert regarding the 
subject matter of this question; but I'll have a go. From inspecting the 
code, the GraftOutput(.) method basically copies/overwrites the 
PixelContainer pointer for an Image (see Image::Graft(.) method). The 
first call ensures that the output of last filter in the composite 
filter is set as the total output of the composite filter. The second 
call ensures that the total output of the composite filter is set as the 
output of the last filter in the composite filter. Basically this 
results in the output Image of the composite filter pointing to the 
PixelContainer of the last filter in the composite pipeline. *Simple 
answer*=to ensure the output of the composite filter (ie. an Image) has 
a pointer to the PixelContainer from the last filter in the mini-pipeline.

3. Are the GetInput(.) and GetOutput(.) methods the same inside or 
outside a composite filter? Nearly, but not quite. At the ProcessObject 
level the GetInput(.) and GetOutput(.) methods are similar - they both 
return a pointer to a DataObject. However, most (all?) composite filters 
will inherit from ImageSource which overrides GetOutput(.) to return an 
OutputImageType pointer. Of course OutputImageType * is really Image<.> 
* which is really DataObject *, so these representations are related 
through inheritance. Ultimately, what you need to be aware of is (1) the 
output of a ProcessObject is 1 or more DataObjects, and (2) the inputs 
of a ProcessObject are DataObjects, and an Image is a subclass of  
DataObject. *(sort of ) simple answer*=GetInput(.) and GetOutput(.) are 
ways to obtain the DataObjects given to and resultant from ITK filters 
(ie. ProcessObjects).

I hope this answered your questions adequately and accurately (any other 
help or corrections?).

Cheers

Dan


Shlomo Kashani. wrote:
> Hi,
>  
> I am writing a composite filter based amongst others on the 
> CompositeFilterExample, the CannyEdgeDetectionImageFilter.cxx (which 
> is based On 3 other filters) and several more filters which I havent 
> written yet. I sucessfuly used the example CompositeFilterExample to 
> convert CannyEdgeDetectionImageFilter to a composite
> filter in which the sequential filtering operation is done in the 
> GenerateData() methood. Even though the filtering operation works 
> well, I have a problem understanding the pipeline operation in the 
> CompositeFilterExample class. The constructor sets up a pipeline as 
> follows:
>  
> template <class TImageType>
> CompositeIrisRecognitionFilter<TImageType>
> ::CompositeIrisRecognitionFilter()
> { 
>   m_CastToRealFilter = CastToRealFilter::New();
>   m_CannyFilter = CannyFilter::New();
>   m_RescaleFilter = RescaleFilter::New();   
>  
>   // Set up the pipeline, this is MY code based exactly on 
> CompositeFilterExample
>   m_CannyFilter->SetInput( m_CastToRealFilter->GetOutput() );
>   // Set the variance for the Gaussian smoothing filter
>   m_CannyFilter->SetVariance(m_GaussianVariance);
>   m_RescaleFilter->SetInput( m_CannyFilter->GetOutput() );                
>            
>   //  Default variance for the canny edge detector, tested on
>   //  the UPOL iris image database
>   m_GaussianVariance=50.0;
> }
>  
> And the GenerateData() methood executes the pipeline as folows:
>  
> template <class TImageType>
> void
> CompositeIrisRecognitionFilter<TImageType>::
> GenerateData()
> {
>   //  The output of an edge filter is 0 or 1
>   m_RescaleFilter->SetOutputMinimum(   0 );
>   m_RescaleFilter->SetOutputMaximum( 255 );
>  
>   // Run the pipeline
>   m_CastToRealFilter->SetInput( this->GetInput() );
>   m_RescaleFilter->GraftOutput( this->GetOutput() );
>   m_RescaleFilter->Update();
>   this->GraftOutput( m_RescaleFilter->GetOutput() );  
>                               
> }
>  
> My questions are:
> 1-why are the pipeline set up and pipeline executions placed in two 
> different methods? I placed both in the GenerateData methood And as 
> expected it was still working. Is there an architectual advantage to 
> the seperation of  operations? I think it adds confusion and breaks 
> the logic sequential order of operations
> 2-How does GraftOutput work exactly, why do I have to use it twice in 
> this case?
> 3-is the invocation of the methood this->GetInput() equivalent to 
> reader->GetOutput() in a non Composite filter (e.g one that does 
> everything in the main methhod)?
>  
> Thank you very much for your help,
>  
> Shlomo.
>
> ------------------------------------------------------------------------
> Do you Yahoo!?
> Get on board. You're invited 
> <http://us.rd.yahoo.com/evt=40791/*http://advision.webevents.yahoo.com/handraisers> 
> to try the new Yahoo! Mail Beta.
> ------------------------------------------------------------------------
>
> _______________________________________________
> 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