<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
  <meta content="text/html;charset=ISO-8859-1" http-equiv="Content-Type">
  <title></title>
</head>
<body bgcolor="#ffffff" text="#000000">
<font face="Helvetica, Arial, sans-serif"><small>Hi insight-users,<br>
<br>
I am using the <font face="Courier New, Courier, monospace">itk::HessianRecursiveGaussianImageFilter</font>
and have noticed it executes quite slow for 'large' 3-D datasets. Here
are some times I recorded:<br>
<br>
itkTestHessian TestHessian_128x128x128.mhd 1 1.0 &gt;&gt; Time = 4.28sec<br>
</small></font><font face="Helvetica, Arial, sans-serif"><small>itkTestHessian
TestHessian_256x256x256.mhd 1 1.0 &gt;&gt; Time = 6.2e+003sec = 1hr
43min<br>
</small></font><font face="Helvetica, Arial, sans-serif"><small>itkTestHessian
TestHessian_512x512x512.mhd 1 1.0 &gt;&gt; I gave up...</small></font><br>
<font face="Helvetica, Arial, sans-serif"><small><br>
<b>My questions:</b><br>
1. Have other people experienced similar execution times using this
filter, or am I doing something wrong? I understand the filter performs
separable convolution multiple times in multiple dimensions (ie. it's
not a simple computation), but these times seem impractical for
datasets 256x256x256 or bigger...<br>
2. Are there any techniques (besides relying on Moore's Law) to speed
up this filter? I am interested in the <i>whole</i> image, so using an
image function would not help. </small></font><font
 face="Helvetica, Arial, sans-serif"><small>(NOTE: I compiled my test
in <font face="Courier New, Courier, monospace">Release</font> mode
with optimization for maximum speed ie. <font
 face="Courier New, Courier, monospace">/O2</font>).</small></font><br>
<font face="Helvetica, Arial, sans-serif"><small><br>
Thanks for any help and/or ideas.<br>
<br>
Cheers, Dan<br>
<a class="moz-txt-link-abbreviated" href="mailto:d.mueller@qut.edu.au">d.mueller@qut.edu.au</a><br>
<b><br>
</b></small></font><small><font face="Helvetica, Arial, sans-serif"><b>My
system:</b><br>
</font></small><small><font face="Helvetica, Arial, sans-serif">Platform:
Windows XP SP2<br>
Computer: Intel Pentium 3.00 GHz, dual core, 1GB physical RAM<br>
Compiler: Microsoft Visual Studio 2005 (v8.0.50727.762 SP1)<br>
CMake: 2.4.2<br>
ITK: 3.2.0 CVS on Tues 27 Mar 2007</font></small><br>
<font face="Helvetica, Arial, sans-serif"><small><br>
<b>My test code:</b><br>
<font face="Courier New, Courier, monospace">/*=========================================================================<br>
&nbsp; itkTestHessian.cxx<br>
=========================================================================*/<br>
<br>
#include &lt;iomanip&gt;<br>
#include "itkImage.h"<br>
#include "itkNumericTraits.h"<br>
#include "itkCommand.h"<br>
#include "itkImageFileReader.h"<br>
#include "itkImageFileWriter.h"<br>
#include "itkHessianRecursiveGaussianImageFilter.h"<br>
#include "itkTimeProbe.h"<br>
<br>
// Declare general types<br>
const unsigned int Dimension = 3;<br>
typedef float PixelType;<br>
typedef itk::Image&lt; PixelType, Dimension &gt; ImageType;<br>
typedef itk::ImageFileReader&lt; ImageType &gt; ReaderType;<br>
typedef itk::ImageFileWriter&lt; ImageType &gt; WriterType;<br>
typedef itk::HessianRecursiveGaussianImageFilter&lt; ImageType &gt;
HessianFilterType;<br>
<br>
// Declare a command to display the progress in a nice block format<br>
class ProgressCommand : public itk::Command <br>
{<br>
public:<br>
&nbsp; typedef&nbsp; ProgressCommand&nbsp;&nbsp; Self;<br>
&nbsp; typedef&nbsp; itk::Command&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Superclass;<br>
&nbsp; typedef&nbsp; itk::SmartPointer&lt;Self&gt;&nbsp; Pointer;<br>
&nbsp; itkNewMacro( Self );<br>
<br>
protected:<br>
&nbsp; ProgressCommand() { m_LastProgress = -1; };<br>
&nbsp; float m_LastProgress;<br>
<br>
public:<br>
<br>
&nbsp; void Execute(itk::Object *caller, const itk::EventObject &amp; event)<br>
&nbsp; {<br>
&nbsp;&nbsp;&nbsp; Execute( (const itk::Object *)caller, event);<br>
&nbsp; }<br>
<br>
&nbsp; void Execute(const itk::Object * object, const itk::EventObject &amp;
event)<br>
&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp; const itk::ProcessObject* process = dynamic_cast&lt; const
itk::ProcessObject* &gt;( object );<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp; if( ! itk::ProgressEvent().CheckEvent( &amp;event ) )<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return;<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp; int fprogress = (process-&gt;GetProgress() * 100.0);<br>
&nbsp;&nbsp;&nbsp; &nbsp; int progress = (int)(process-&gt;GetProgress() * 100.0);<br>
&nbsp;&nbsp;&nbsp; &nbsp; if ((int)m_LastProgress == progress)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; return;<br>
&nbsp;&nbsp;&nbsp; &nbsp; if ((int)m_LastProgress != (progress - 1))<br>
&nbsp;&nbsp;&nbsp; &nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; std::cout &lt;&lt; std::setfill('0') &lt;&lt; std::setw(3)
&lt;&lt; (progress - 1) &lt;&lt; " ";<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (fprogress &gt; 0.0 &amp;&amp; (progress - 1) % 10 == 0)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; std::cout &lt;&lt; std::endl;<br>
&nbsp;&nbsp;&nbsp; &nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp; if (fprogress &gt; 0.0 &amp;&amp; fprogress &lt;= 100.0)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; std::cout &lt;&lt; std::setfill('0') &lt;&lt; std::setw(3)
&lt;&lt; progress &lt;&lt; " ";<br>
&nbsp;&nbsp;&nbsp; &nbsp; if (fprogress &gt; 0.0 &amp;&amp; progress % 10 == 0)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; std::cout &lt;&lt; std::endl;<br>
&nbsp;&nbsp;&nbsp; &nbsp; m_LastProgress = fprogress;<br>
&nbsp; }&nbsp;&nbsp; <br>
};<br>
<br>
int main(int argc, char* argv[])<br>
{<br>
&nbsp;&nbsp;&nbsp; // Display header<br>
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; "Hessian Test -------------------------"
&lt;&lt; std::endl;<br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; // Check arguments<br>
&nbsp;&nbsp;&nbsp; if (argc &lt; 4)<br>
&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; std::cerr &lt;&lt; "Usage: " &lt;&lt; argv[0] &lt;&lt;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; " InputFilename" &lt;&lt;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; " NormalizeAcrossScale" &lt;&lt;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; " Sigma" &lt;&lt;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; " \n";<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return EXIT_FAILURE;<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; // Setup the algorithm parameters<br>
&nbsp;&nbsp;&nbsp; unsigned int argn = 1;<br>
&nbsp;&nbsp;&nbsp; char* InputFilename&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = argv[argn++];<br>
&nbsp;&nbsp;&nbsp; bool NormalizeAcrossScale&nbsp; = (bool)atoi( argv[argn++] );<br>
&nbsp;&nbsp;&nbsp; double Sigma&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = atof( argv[argn++] );<br>
<br>
&nbsp;&nbsp;&nbsp; // Display parameters<br>
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; "InputFilename:" &lt;&lt; InputFilename &lt;&lt;
std::endl;<br>
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; "NormalizeAcrossScale:" &lt;&lt;
NormalizeAcrossScale &lt;&lt; std::endl;<br>
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; "Sigma:" &lt;&lt; Sigma &lt;&lt; std::endl;<br>
&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; "------------------------------------" &lt;&lt;
std::endl;<br>
&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; try<br>
&nbsp;&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // Read input image<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; std::cout &lt;&lt; "Reading input..." &lt;&lt; std::endl;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ReaderType::Pointer reader = ReaderType::New();<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; reader-&gt;SetFileName( InputFilename );<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; reader-&gt;Update();<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // Setup Hessian<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; std::cout &lt;&lt; "Computing Hessian..." &lt;&lt; std::endl;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; HessianFilterType::Pointer filterHessian =
HessianFilterType::New();<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; filterHessian-&gt;SetInput( reader-&gt;GetOutput() );<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; filterHessian-&gt;SetSigma( Sigma );<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; filterHessian-&gt;SetNormalizeAcrossScale( NormalizeAcrossScale
);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ProgressCommand::Pointer observerHessian =
ProgressCommand::New();<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; filterHessian-&gt;AddObserver( itk::ProgressEvent(),
observerHessian );<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Compute and time hessian<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; itk::TimeProbe time;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; time.Start();<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; filterHessian-&gt;Update( );<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; time.Stop();<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; std::cout &lt;&lt; std::setprecision(3) &lt;&lt; "Time: "
&lt;&lt; time.GetMeanTime() &lt;&lt; std::endl;<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; catch (itk::ExceptionObject &amp; err)<br>
&nbsp;&nbsp;&nbsp; { <br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; std::cout &lt;&lt; "ExceptionObject caught !" &lt;&lt;
std::endl; <br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; std::cout &lt;&lt; err &lt;&lt; std::endl; <br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return EXIT_FAILURE;<br>
&nbsp;&nbsp;&nbsp; }<br>
<br>
&nbsp;&nbsp;&nbsp; //Return<br>
&nbsp;&nbsp;&nbsp; return EXIT_SUCCESS;<br>
}</font><br>
</small></font>
</body>
</html>