[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.&nbsp; By this I mean that a filter can 
overwrite its input in order to build the output.&nbsp; The pipeline mechanism 
is managed, see the discussion below.</FONT></SPAN></DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2></FONT></SPAN>&nbsp;</DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2>There is a base class, 
InPlaceImageFilter, that you can derive in place filters off of.&nbsp; Since the 
output overwrites the input, the input pixel type must match the output pixel 
type.&nbsp; Thus, InPlaceImageFilter only has one template 
parameter.</FONT></SPAN></DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2></FONT></SPAN>&nbsp;</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>&nbsp;</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>&nbsp;</DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2>InPlaceImageFilter overrides 
the&nbsp;</FONT></SPAN><SPAN class=412284521-11032003><FONT 
size=2>AllocateOutputs() method from ImageSource.&nbsp; Instead of allocating 
the bulk data, it grafts the input bulk data onto the output data object.&nbsp; 
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.&nbsp; The input data object must then release 
its hold on the bulk data.&nbsp; This is done in ReleaseInputs(), 
described&nbsp;below.</FONT></SPAN></DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2></FONT></SPAN>&nbsp;</DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2>InPlaceImageFilter overrides 
the ReleaseInputs() method from ProcessObject.&nbsp; The first input is always 
released.&nbsp; Remaining inputs are released iff the ReleaseDataFlag is set. 
(ProcessObject::ReleaseInputs() normally just releases the bulk data if the 
ReleaseDataFlag is set.&nbsp; InPlaceFilters always release the bulk data for 
the first input).</FONT></SPAN></DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2></FONT></SPAN>&nbsp;</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.&nbsp; 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>&nbsp;</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>&nbsp;</DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2>InPlace filters require the 
input and output pixel type be the same.&nbsp; They also require the regions to 
match.&nbsp; 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>&nbsp;</DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2>InPlace filters have the 
benefit that only one image buffer is used.&nbsp; This can reduce the memory 
footprint of a processing stage.&nbsp; Note, however, this benefit has a 
cost.&nbsp; Consider the following pipeline:</FONT></SPAN></DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2></FONT></SPAN>&nbsp;</DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2>A ---&gt; B --- &gt; 
C</FONT></SPAN></DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2>&nbsp;&nbsp;&nbsp; 
|</FONT></SPAN></DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2>&nbsp;&nbsp;&nbsp; ---&gt; D 
--&gt; E</FONT></SPAN></DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2></FONT></SPAN>&nbsp;</DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2>Let B be an InPlace 
filter.&nbsp; When C calls Update(), A, B, and C will execute.&nbsp; 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.&nbsp; Since B overwrote its input, A's output bulk data had to be 
released.&nbsp; So when D goes to execute, A no longer has output bulk 
data.&nbsp; 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>&nbsp;</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.&nbsp; 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.&nbsp; We could however implement these filters with a mode and a single 
filter could operate as in place or standard.&nbsp; 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>&nbsp;</DIV>
<DIV><SPAN class=412284521-11032003><FONT size=2>Feedback 
welcomed.</FONT></SPAN></DIV>
<DIV><SPAN class=412284521-11032003></SPAN>&nbsp;</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 &amp; 
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>&nbsp;<?xml:namespace prefix = o ns = 
"urn:schemas-microsoft-com:office:office" /><o:p></o:p></P></DIV>
<DIV>&nbsp;</DIV></BODY></HTML>

------_=_NextPart_001_01C2E81B.52F8E700--