[Insight-developers] In place filtering
Miller, James V (Research)
millerjv@crd.ge.com
Tue, 11 Mar 2003 17:12:37 -0500
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_001_01C2E81B.52F8E700
Content-Type: text/plain;
charset="iso-8859-1"
I just checked in code to allow the in place filtering of images. By this I
mean that a filter can overwrite its input in order to build the output.
The pipeline mechanism is managed, see the discussion below.
There is a base class, InPlaceImageFilter, that you can derive in place
filters off of. Since the output overwrites the input, the input pixel type
must match the output pixel type. Thus, InPlaceImageFilter only has one
template parameter.
I have checked in an example in place filter,
itkShiftScaleInPlaceImageFilter, and a test,
itkShiftScaleInPlaceImageFilterTest.
In place filtering work as follows:
InPlaceImageFilter overrides the AllocateOutputs() method from ImageSource.
Instead of allocating the bulk data, it grafts the input bulk data onto the
output data object. If there are multiple outputs, the remaining outputs
are allocated as normally. By grafting the input onto the output, we are
transferring ownership of the bulk data to the output data object. The
input data object must then release its hold on the bulk data. This is done
in ReleaseInputs(), described below.
InPlaceImageFilter overrides the ReleaseInputs() method from ProcessObject.
The first input is always released. Remaining inputs are released iff the
ReleaseDataFlag is set. (ProcessObject::ReleaseInputs() normally just
releases the bulk data if the ReleaseDataFlag is set. InPlaceFilters always
release the bulk data for the first input).
If you subclass InPlaceImageFilter and provided a ThreadedGenerateData
implementation, then you do not need to do anything else to manage the
allocation of outputs or releasing of inputs. If you provide a GenerateData
implementation, then you need to either call AllocateOutputs() or provide a
similar implementation to graft the input onto the output.
If you filter has multiple inputs and outputs, you may need to override both
these methods to have the behavior you desire.
InPlace filters require the input and output pixel type be the same. They
also require the regions to match. The default implementations of region
negotiation will have the output requested and largest possible regions
match the input requested and largest possible regions. So for simple
InPlace filtering, you do not need to do anything special to manage the
regions.
InPlace filters have the benefit that only one image buffer is used. This
can reduce the memory footprint of a processing stage. Note, however, this
benefit has a cost. Consider the following pipeline:
A ---> B --- > C
|
---> D --> E
Let B be an InPlace filter. When C calls Update(), A, B, and C will
execute. If E calls Update() afterwards,
then A, D, and E will need to execute. Since B overwrote its input, A's
output bulk data had to be released. So when D goes to execute, A no longer
has output bulk data. So A must re-execute in order to generate the data
for D.
Given other restructurings we have made to the pipeline in the past year or
so, the change to support in place filtering is fairly minimal. One could
argue that some of our filters could operate as either in place or standard
filters. The FunctorImageFilters come to mind immediately. Currently, we
need two implementations for such filters. We could however implement these
filters with a mode and a single filter could operate as in place or
standard. I hesitate to do that since THAT would be fairly invasive and
people would have to be very careful inside those implementations.
Feedback welcomed.
Jim Miller
_____________________________________
Visualization & Computer Vision
GE Research
Bldg. KW, Room C218B
P.O. Box 8, Schenectady NY 12301
millerjv@research.ge.com <mailto:millerjv@research.ge.com>
james.miller@research.ge.com
(518) 387-4005, Dial Comm: 8*833-4005,
Cell: (518) 505-7065, Fax: (518) 387-6981
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office"
/>
------_=_NextPart_001_01C2E81B.52F8E700
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 6.00.2715.400" name=GENERATOR></HEAD>
<BODY>
<DIV><SPAN class=412284521-11032003><FONT size=2>I just checked in code to allow
the in place filtering of images. By this I mean that a filter can
overwrite its input in order to build the output. The pipeline mechanism
is managed, see the discussion below.</FONT></SPAN></DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2></FONT></SPAN> </DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2>There is a base class,
InPlaceImageFilter, that you can derive in place filters off of. Since the
output overwrites the input, the input pixel type must match the output pixel
type. Thus, InPlaceImageFilter only has one template
parameter.</FONT></SPAN></DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2></FONT></SPAN> </DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2>I have checked in an example in
place filter, itkShiftScaleInPlaceImageFilter, and a test,
itkShiftScaleInPlaceImageFilterTest.</FONT></SPAN></DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2></FONT></SPAN> </DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2>In place filtering work as
follows:</FONT></SPAN></DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2></FONT></SPAN> </DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2>InPlaceImageFilter overrides
the </FONT></SPAN><SPAN class=412284521-11032003><FONT
size=2>AllocateOutputs() method from ImageSource. Instead of allocating
the bulk data, it grafts the input bulk data onto the output data object.
If there are multiple outputs, the remaining outputs are allocated as normally.
By grafting the input onto the output, we are transferring ownership of the bulk
data to the output data object. The input data object must then release
its hold on the bulk data. This is done in ReleaseInputs(),
described below.</FONT></SPAN></DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2></FONT></SPAN> </DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2>InPlaceImageFilter overrides
the ReleaseInputs() method from ProcessObject. The first input is always
released. Remaining inputs are released iff the ReleaseDataFlag is set.
(ProcessObject::ReleaseInputs() normally just releases the bulk data if the
ReleaseDataFlag is set. InPlaceFilters always release the bulk data for
the first input).</FONT></SPAN></DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2></FONT></SPAN> </DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2>If you subclass
InPlaceImageFilter and provided a ThreadedGenerateData implementation, then you
do not need to do anything else to manage the allocation of outputs or releasing
of inputs. If you provide a GenerateData implementation, then you need to
either call AllocateOutputs() or provide a similar implementation to graft the
input onto the output.</FONT></SPAN></DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2></FONT></SPAN> </DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2>If you filter has multiple
inputs and outputs, you may need to override both these methods to have the
behavior you desire.</FONT></SPAN></DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2></FONT></SPAN> </DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2>InPlace filters require the
input and output pixel type be the same. They also require the regions to
match. The default implementations of region negotiation will have the
output requested and largest possible regions match the input requested and
largest possible regions. So for simple InPlace filtering, you do not need to do
anything special to manage the regions.</FONT></SPAN></DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2></FONT></SPAN> </DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2>InPlace filters have the
benefit that only one image buffer is used. This can reduce the memory
footprint of a processing stage. Note, however, this benefit has a
cost. Consider the following pipeline:</FONT></SPAN></DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2></FONT></SPAN> </DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2>A ---> B --- >
C</FONT></SPAN></DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2>
|</FONT></SPAN></DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2> ---> D
--> E</FONT></SPAN></DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2></FONT></SPAN> </DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2>Let B be an InPlace
filter. When C calls Update(), A, B, and C will execute. If E calls
Update() afterwards, </FONT></SPAN></DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2>then A, D, and E will need to
execute. Since B overwrote its input, A's output bulk data had to be
released. So when D goes to execute, A no longer has output bulk
data. So A must re-execute in order to generate the data for
D.</FONT></SPAN></DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2></FONT></SPAN> </DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2>Given other restructurings we
have made to the pipeline in the past year or so, the change to support in place
filtering is fairly minimal. One could argue that some of our filters
could operate as either in place or standard filters. The FunctorImageFilters
come to mind immediately. Currently, we need two implementations for such
filters. We could however implement these filters with a mode and a single
filter could operate as in place or standard. I hesitate to do that since
THAT would be fairly invasive and people would have to be very careful inside
those implementations. </FONT></SPAN></DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2></FONT></SPAN> </DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2>Feedback
welcomed.</FONT></SPAN></DIV>
<DIV><SPAN class=412284521-11032003></SPAN> </DIV>
<DIV class=Section1>
<P style="MARGIN: 0in 0in 0pt"><B><SPAN
style="COLOR: navy; FONT-FAMILY: 'Comic Sans MS'">Jim Miller</SPAN></B>
<BR><B><I><SPAN
style="FONT-SIZE: 10pt; COLOR: red; FONT-FAMILY: Arial">_____________________________________</SPAN></I></B><BR><EM><SPAN
style="FONT-SIZE: 7.5pt; COLOR: black; FONT-FAMILY: Arial">Visualization &
Computer Vision</SPAN></EM><I><SPAN
style="FONT-SIZE: 7.5pt; COLOR: black; FONT-FAMILY: Arial"><BR><EM>GE
Research</EM><BR><EM>Bldg. KW, Room C218B</EM><BR><EM>P.O. Box 8, Schenectady NY
12301</EM><BR><BR></SPAN></I><EM><U><SPAN
style="FONT-SIZE: 7.5pt; COLOR: blue"><A
href="mailto:millerjv@research.ge.com">millerjv@research.ge.com</A></SPAN></U></EM></P>
<P style="MARGIN: 0in 0in 0pt"><EM><U><SPAN
style="FONT-SIZE: 7.5pt; COLOR: blue">james.miller@research.ge.com</SPAN></U></EM><BR><I><SPAN
style="FONT-SIZE: 7.5pt; COLOR: black; FONT-FAMILY: Arial">(518) 387-4005, Dial
Comm: 8*833-4005, </SPAN></I><BR><I><SPAN
style="FONT-SIZE: 7.5pt; COLOR: black; FONT-FAMILY: Arial">Cell: (518) 505-7065,
Fax: (518) 387-6981</SPAN></I> </P>
<P class=MsoNormal> <?xml:namespace prefix = o ns =
"urn:schemas-microsoft-com:office:office" /><o:p></o:p></P></DIV>
<DIV> </DIV></BODY></HTML>
------_=_NextPart_001_01C2E81B.52F8E700--