[Insight-developers] Mini-pipelines in filters
Miller, James V (CRD)
millerjv@crd.ge.com
Fri, 12 Oct 2001 12:36:47 -0400
This message is in MIME format. Since your mail reader does not understand
this format, some or all of this message may not be legible.
------_=_NextPart_000_01C1533C.15F893C0
Content-Type: multipart/alternative;
boundary="----_=_NextPart_001_01C1533C.15F893C0"
------_=_NextPart_001_01C1533C.15F893C0
Content-Type: text/plain;
charset="iso-8859-1"
I have made changes to the architecture to support running mini-pipelines inside of filters. The
changes provide an official API to doing these operations. The method SetOutput() will be removed
from the system since it cannot be used safely. Here are a summary of changes:
1. ProcessObject::MakeOutput(unsigned int idx) - Every subclass of ProcessObject must have a
method that can construct a DataObject of the appropriate type to be used as the idx'th output. This
method returns a SmartPointer to the constructed DataObject. This method is used internally to
ProcessObject to keep its output array valid. Most filters have a single output and can use the
default implementations in ImageSource or MeshSource. If a filter has multiple outputs of different
types, then that filter will have to provide a MakeOutput() method.
1. I added this method to ImageSource and MeshSource. Other subclasses of ProcessObject like
ImageIO, MultiResolutionRegistration, RegistrationMethod, and Writer need to have this method
defined. I am not sure what it should do in those cases.
2. ImageSource::GraftOutput(), MeshSource::GraftOutput() - These methods take an image or mesh
respectively and grab a handle to the bulk data (PixelContainer, etc.) and copies of the region
ivars, spacing etc. This allows to set up a mini-pipeline to write its output into your filters
output bulk data area and allows you to transfer the bulk data from the end of a mini-pipeline to
your filters output. Note the two data objects are distinct, the simply reference the same bulk data
array. See the usage below. The MeshSource implementation is incomplete. I need to touch base with
Will to see what needs to be copied.
I modified two filters to illustrate how to use these methods. The first was the
DerivativeImageFilter. This filter instantiates a single filter internally and delegates the input
and output to that filter. The critical section of the GenerateData() method now looks like:
filter->SetInput(this->GetInput());
filter->GraftOutput(this->GetOutput());
filter->Update();
this->GraftOutput(filter->GetOutput());
The second filter was the DiscreteGaussianImageFilter. This filter has a mini-pipeline that is
executed several times in a loop. The first time through the loop the mini-pipeline input is the
filter's input. Subsequent times through the loop the input to the mini-pipeline is the output of
the mini-pipeline from the previous iteration. In this case, we need to use GraftOutput() in
conjunction with DisconnectPipeline(). The critical section of the GenerateData() method for this
filter now looks like:
filter->GraftOutput( output );
swapPtrA = this->GetInput();
for (unsigned int i = 0; i < ImageDimension; ++i)
{
// Set up the operator for this dimension
oper->SetDirection(i);
oper->SetVariance(m_Variance[i]);
oper->SetMaximumError(m_MaximumError[i]);
oper->CreateDirectional();
// Set up the filter and run the mini-pipeline
filter->SetOperator(*oper);
filter->SetInput(swapPtrA);
filter->Update();
// Disconnect the output of the mini-pipeline so that it can be
// used as the input to the mini-pipeline
swapPtrA = filter->GetOutput();
swapPtrA->DisconnectPipeline();
}
// Graft the last output of the mini-pipeline onto this filters output so
// the final output has the correct region ivars and a handle to the final
// bulk data
this->GraftOutput(swapPtrA);
ToDo -
* I need to finish MeshSource::GraftOutput().
* Need to determine whether MakeOutput() needs to be implemented in ImageIO,
MultiResolutionRegistration, RegistrationMethod, and Writer.
* Looks like the ImageAdaptors do not provide the necessary API to support these changes. I'll
look into adding the appropriate methods.
* Remove SetOutput() whereever it is used . It looks like the GradientRecursiveGaussian and
some of the VectorNeighborhood operators are using SetOutput().
I added a warning macro to SetOutput() so you can identify at run time that the method is slated to
be removed.
Jim Miller
_____________________________________
Visualization & Computer Vision
GE Corporate Research & Development
Bldg. KW, Room C218B
P.O. Box 8, Schenectady NY 12301
millerjv@crd.ge.com < mailto:millerjv@crd.ge.com <mailto:millerjv@crd.ge.com> >
(518) 387-4005, Dial Comm: 8*833-4005,
Cell: (518) 505-7065, Fax: (518) 387-6981
------_=_NextPart_001_01C1533C.15F893C0
Content-Type: text/html;
charset="iso-8859-1"
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<META content="MSHTML 5.50.4807.2300" name=GENERATOR></HEAD>
<BODY>
<DIV><SPAN class=930253013-12102001><FONT size=2>I have made changes to the
architecture to support running mini-pipelines inside of filters. The
changes provide an official API to doing these operations. The method
SetOutput() will be removed from the system since it cannot be used safely. Here
are a summary of changes:</FONT></SPAN></DIV>
<OL>
<LI><SPAN class=930253013-12102001><FONT
size=2>ProcessObject::MakeOutput(unsigned int idx) - Every subclass of
ProcessObject must have a method that can construct a DataObject of the
appropriate type to be used as the idx'th output. This method returns a
SmartPointer to the constructed DataObject. This method is used
internally to ProcessObject to keep its output array valid. Most filters have
a single output and can use the default implementations in ImageSource or
MeshSource. If a filter has multiple outputs of different types, then that
filter will have to provide a MakeOutput() method.</FONT></SPAN></LI>
<OL>
<LI><SPAN class=930253013-12102001><FONT size=2>I added this method to
ImageSource and MeshSource. Other subclasses of ProcessObject like
ImageIO, MultiResolutionRegistration, RegistrationMethod, and Writer need to
have this method defined. I am not sure what it should do in those
cases.</FONT></SPAN></LI></OL>
<LI><SPAN class=930253013-12102001><FONT size=2>ImageSource::GraftOutput(),
MeshSource::GraftOutput() - These methods take an image or mesh respectively
and grab a handle to the bulk data (PixelContainer, etc.) and copies of the
region ivars, spacing etc. This allows to set up a mini-pipeline to
write its output into your filters output bulk data area and allows you to
transfer the bulk data from the end of a mini-pipeline to your filters
output. Note the two data objects are distinct, the simply reference the
same bulk data array. See the usage below. The MeshSource implementation
is incomplete. I need to touch base with Will to see what needs to be
copied.</FONT></SPAN></LI></OL>
<DIV><SPAN class=930253013-12102001><FONT size=2>I modified two filters to
illustrate how to use these methods. The first was the
DerivativeImageFilter. This filter instantiates a single filter internally
and delegates the input and output to that filter. The critical section of
the GenerateData() method now looks like:</FONT></SPAN></DIV>
<DIV><SPAN class=930253013-12102001><FONT size=2></FONT></SPAN> </DIV>
<DIV><SPAN class=930253013-12102001><FONT size=2>
filter->SetInput(this->GetInput());</FONT></SPAN></DIV>
<DIV><SPAN class=930253013-12102001><FONT size=2>
filter->GraftOutput(this->GetOutput());</FONT></SPAN><SPAN
class=930253013-12102001><FONT size=2><BR>
filter->Update();</FONT></SPAN></DIV>
<DIV><SPAN class=930253013-12102001><FONT size=2>
this->GraftOutput(filter->GetOutput());<BR></FONT></SPAN></DIV>
<DIV><SPAN class=930253013-12102001><FONT size=2>The second filter was the
DiscreteGaussianImageFilter. This filter has a mini-pipeline that is
executed several times in a loop. The first time through the loop the
mini-pipeline input is the filter's input. Subsequent times through the
loop the input to the mini-pipeline is the output of the mini-pipeline from the
previous iteration. In this case, we need to use GraftOutput() in
conjunction with DisconnectPipeline(). The critical section of the
GenerateData() method for this filter now looks like:</FONT></SPAN></DIV>
<DIV><SPAN class=930253013-12102001><FONT size=2></FONT></SPAN> </DIV>
<DIV><SPAN class=930253013-12102001><FONT
size=2> filter->GraftOutput( output );<BR> swapPtrA =
this->GetInput();<BR> for (unsigned int i = 0; i < ImageDimension;
++i)<BR> {<BR> // Set up the operator for
this dimension<BR>
oper->SetDirection(i);<BR>
oper->SetVariance(m_Variance[i]);<BR>
oper->SetMaximumError(m_MaximumError[i]);<BR>
oper->CreateDirectional();</FONT></SPAN></DIV>
<DIV> </DIV>
<DIV><SPAN class=930253013-12102001><FONT size=2> // Set up
the filter and run the mini-pipeline<BR>
filter->SetOperator(*oper);<BR>
filter->SetInput(swapPtrA);<BR>
filter->Update();</FONT></SPAN></DIV>
<DIV> </DIV>
<DIV><SPAN class=930253013-12102001><FONT size=2> //
Disconnect the output of the mini-pipeline so that it can
be<BR> // used as the input to the
mini-pipeline<BR> swapPtrA =
filter->GetOutput();<BR>
swapPtrA->DisconnectPipeline();</FONT></SPAN><SPAN
class=930253013-12102001><FONT size=2><BR> }<BR> //
Graft the last output of the mini-pipeline onto this filters output so<BR>
// the final output has the correct region ivars and a handle to the
final<BR> // bulk data<BR>
this->GraftOutput(swapPtrA);<BR></FONT></SPAN></DIV>
<DIV><SPAN class=930253013-12102001><FONT
size=2><STRONG></STRONG></FONT></SPAN> </DIV>
<DIV><SPAN class=930253013-12102001><FONT size=2><STRONG>ToDo</STRONG> -
</FONT></SPAN></DIV>
<UL>
<LI><SPAN class=930253013-12102001><FONT size=2>I need to finish
MeshSource::GraftOutput(). </FONT></SPAN></LI>
<LI><SPAN class=930253013-12102001><FONT size=2>Need to determine whether
MakeOutput() needs to be implemented in ImageIO, MultiResolutionRegistration,
RegistrationMethod, and Writer.</FONT></SPAN></LI>
<LI><FONT size=2><SPAN class=930253013-12102001>Looks like the ImageAdaptors
do not provide the necessary API to support these changes. I'll look
into adding the appropriate methods.</SPAN></FONT></LI>
<LI><FONT size=2><SPAN class=930253013-12102001></SPAN><SPAN
class=930253013-12102001>Remove SetOutput() whereever it is used . It
looks like the GradientRecursiveGaussian and some of the VectorNeighborhood
operators are using SetOutput().</SPAN></FONT></LI></UL>
<DIV><FONT size=2><SPAN class=930253013-12102001>I added a warning macro to
SetOutput() so you can identify at run time that the method is slated to be
removed.</DIV></SPAN></FONT>
<DIV><SPAN class=930253013-12102001><FONT size=2></FONT></SPAN> </DIV><BR>
<P><B><FONT face="Comic Sans MS" color=#000080>Jim Miller</FONT></B>
<BR><B><I><FONT face=Arial color=#ff0000
size=2>_____________________________________</FONT></I></B><I></I><BR><I></I><I><FONT
face=Arial color=#000000 size=1>Visualization & Computer Vision<BR>GE
Corporate Research & Development<BR>Bldg. KW, Room C218B<BR>P.O. Box 8,
Schenectady NY 12301<BR><BR></FONT><U><FONT face=Arial color=#0000ff
size=1>millerjv@crd.ge.com <<A
href="mailto:millerjv@crd.ge.com">mailto:millerjv@crd.ge.com</A>></FONT></U></I><BR><I><FONT
face=Arial color=#000000 size=1>(518) 387-4005, Dial Comm: 8*833-4005,
</FONT></I><BR><I><FONT face=Arial color=#000000 size=1>Cell: (518) 505-7065,
Fax: (518) 387-6981</FONT></I> </P><BR>
<DIV> </DIV></BODY></HTML>
------_=_NextPart_001_01C1533C.15F893C0--
------_=_NextPart_000_01C1533C.15F893C0
Content-Type: application/octet-stream;
name="Miller, James V (CRD).vcf"
Content-Disposition: attachment;
filename="Miller, James V (CRD).vcf"
BEGIN:VCARD
VERSION:2.1
N:Miller;James
FN:Miller, James V (CRD)
ORG:CRD;ESL
TITLE:Computer Scientist
TEL;WORK;VOICE:*833-4005
TEL;WORK;VOICE:1 518 387-4005
ADR;WORK:;KW-C218B;P.O. Box 8;Schenectady;New York;12301;USA
LABEL;WORK;ENCODING=QUOTED-PRINTABLE:KW-C218B=0D=0AP.O. Box 8=0D=0ASchenectady, New York 12301=0D=0AUSA
EMAIL;PREF;INTERNET:millerjv@crd.ge.com
REV:20010420T140329Z
END:VCARD
------_=_NextPart_000_01C1533C.15F893C0--