<div><br></div><div>Hi Luis et al.,</div><div><br></div><div>In this loop (see below), is it necessary to &quot;reset&quot; the registration method (optimizer or anything else)?  Could there be any &quot;hang-over&quot; from previous calls in the loop?</div>
<div><br></div>TIA,<div>Darren</div><div><br></div><div><br><br><div class="gmail_quote">On Tue, Mar 9, 2010 at 3:07 PM, Darren Weber <span dir="ltr">&lt;<a href="mailto:darren.weber.lists@gmail.com">darren.weber.lists@gmail.com</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><div><br></div><div>FYI, here&#39;s a snip from the &quot;rotation loop&quot; (see ImageRegistration6.cxx for the rest):</div>
<div><br></div><div><br></div><div><br></div><div><div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">    // The registration fails when the angle of rotation is large, so we need a</span></font></div>

<div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">    // loop to evaluate a range of angles to find one that will work well.</span></font></div>
<div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large"><br></span></font></div><div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">    double angleInDegrees[] = { 0.0, 10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0, 110.0, 120.0, 130.0, 140.0, 150.0, 160.0, 170.0, 180.0 };</span></font></div>

<div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large"><br></span></font></div><div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">    double angleInRadians, bestAngleInRadians;</span></font></div>

<div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">    unsigned int bestIterations = 0;</span></font></div><div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">    TransformType::Pointer rigid2DFinalTransform = TransformType::New();</span></font></div>

<div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large"><div>    OptimizerType::MeasureType bestMetric = 0.0;</div><div><br></div></span></font></div>
<div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">    for( unsigned int i = 0; i &lt; 19; i++ )</span></font></div><div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">        {</span></font></div>

<div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">        angleInRadians = angleInDegrees[i] * vnl_math::pi / 180.0;</span></font></div><div>
<font face="&#39;courier new&#39;, monospace"><span style="font-size:large">        std::cout</span></font></div><div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">            &lt;&lt; std::endl</span></font></div>

<div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">            &lt;&lt; &quot;Loop &quot; &lt;&lt; i &lt;&lt; &quot;, trying:&quot; &lt;&lt; std::endl</span></font></div>
<div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">            &lt;&lt; &quot;angleInDegrees = &quot; &lt;&lt; angleInDegrees[i] &lt;&lt; &quot; degrees &quot; &lt;&lt; std::endl</span></font></div>

<div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">            &lt;&lt; &quot;angleInRadians = &quot; &lt;&lt; angleInRadians    &lt;&lt; std::endl</span></font></div>
<div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">            &lt;&lt; std::endl;</span></font></div><div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">        initializer-&gt;InitializeTransform();</span></font></div>

<div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">        rigid2DTransform-&gt;SetAngle( angleInRadians );</span></font></div><div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">        registration-&gt;SetInitialTransformParameters( rigid2DTransform-&gt;GetParameters() );</span></font></div>

<div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large"><br></span></font></div><div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">        try </span></font></div>
<div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">            { </span></font></div><div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">            registration-&gt;StartRegistration(); </span></font></div>

<div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">            if( VERBOSE )</span></font></div><div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">                {</span></font></div>

<div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">                std::cout &lt;&lt; std::endl</span></font></div><div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">                    &lt;&lt; optim &lt;&lt; std::endl</span></font></div>

<div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">                    &lt;&lt; std::endl;</span></font></div><div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">                }</span></font></div>

<div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">            } </span></font></div><div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">        catch( itk::ExceptionObject &amp; err ) </span></font></div>

<div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">            { </span></font></div><div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">            std::cerr &lt;&lt; &quot;ExceptionObject caught !&quot; &lt;&lt; std::endl; </span></font></div>

<div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">            std::cerr &lt;&lt; err &lt;&lt; std::endl; </span></font></div><div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">            return EXIT_FAILURE;</span></font></div>

<div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">            } </span></font></div><div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large"><br>
</span></font></div><div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">        // Check the metric and store the best angle</span></font></div>
<div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">        if( i == 0 )</span></font></div><div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">            bestMetric = optim-&gt;GetValue();</span></font></div>

<div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">        if( bestMetric &gt; optim-&gt;GetValue() )</span></font></div><div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">            {</span></font></div>

<div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">            bestMetric = optim-&gt;GetValue();</span></font></div><div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">            bestIterations = optim-&gt;GetCurrentIteration();</span></font></div>

<div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">            bestAngleInRadians = angleInRadians;</span></font></div><div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">            // ** Set the final rigid2DTransform **</span></font></div>

<div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">            rigid2DFinalTransform-&gt;SetParameters( registration-&gt;GetLastTransformParameters() );</span></font></div>
<div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">            rigid2DFinalTransform-&gt;SetFixedParameters( rigid2DTransform-&gt;GetFixedParameters() );</span></font></div>
<div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">            }</span></font></div><div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">        std::cout</span></font></div>

<div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">            &lt;&lt; std::endl</span></font></div><div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">            &lt;&lt; &quot;After loop &quot; &lt;&lt; i &lt;&lt; &quot;, metrics are:&quot; &lt;&lt; std::endl</span></font></div>

<div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">            &lt;&lt; &quot;angleInDegrees = &quot; &lt;&lt; angleInDegrees[i] &lt;&lt; &quot; degrees &quot; &lt;&lt; std::endl</span></font></div>

<div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">            &lt;&lt; &quot;angleInRadians = &quot; &lt;&lt; angleInRadians    &lt;&lt; std::endl</span></font></div>
<div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">            &lt;&lt; &quot;bestMetric = &quot; &lt;&lt; bestMetric &lt;&lt; std::endl</span></font></div>
<div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">            &lt;&lt; &quot;currentMetric = &quot; &lt;&lt; optim-&gt;GetValue() &lt;&lt; std::endl</span></font></div>
<div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">            &lt;&lt; std::endl;</span></font></div><div><font face="&#39;courier new&#39;, monospace"><span style="font-size:large">        }</span></font></div>

<div><br></div><div><br></div><div><br></div><div>Best, </div><div>Darren</div><font color="#888888"><div><br></div><div><br></div></font></div><div><div></div><div class="h5"><div><br></div><div><br></div><div><br></div>
<br><br><div class="gmail_quote">On Mon, Mar 8, 2010 at 11:14 AM, Darren Weber <span dir="ltr">&lt;<a href="mailto:darren.weber.lists@gmail.com" target="_blank">darren.weber.lists@gmail.com</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><br></div><div>Hi Luis et al.,</div><div><br></div><div>Thanks for considering this and offering suggestions.</div>

<div><br></div><div>There are thousands of images to register.  It&#39;s possible to manually note approximate initialization values for the rotation of all the images.  However, it may be easier (perhaps not quicker) to create a &quot;rotation loop&quot; that:</div>


<div><br></div><div> (a) sets a rotation value between 0 to pi (stepping 15 degrees),</div><div><br></div><div> (b) calls the registration method, then</div><div><br></div><div> (c) checks the metric for the lowest value (for mean sq metric) to identify and store the rotation that provides the &quot;best&quot; registration.</div>


<div><br></div><div>The extra &quot;rotation&quot; loop means running the registration N times (say 13 times for 0:15:180 [in Octave syntax]) and there may be a final run with the &quot;best&quot; rotation value.</div><div>


<br></div><div>Is this reasonable?  Is there are better way to do this?</div><div><br></div>As a novice with optimization, I&#39;m surprised that some kind of quick estimate for the full range of rotations is not built into the optimization routine or the registration method.<div>


<br></div><div>Take care,</div><div>Darren</div><div><div></div><div><div><br></div><div><br></div><div><br><br><div class="gmail_quote">On Sat, Mar 6, 2010 at 3:58 PM, Luis Ibanez <span dir="ltr">&lt;<a href="mailto:luis.ibanez@kitware.com" target="_blank">luis.ibanez@kitware.com</a>&gt;</span> wrote:<br>


<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Darren,<br>
<br>
<br>
Thanks for posting all the source code and images that<br>
reproduce the problem that you are observing.<br>
<br>
<br>
As Richard pointed out, the registration process must be<br>
initialized properly.<br>
<br>
<br>
It is very unlikely that an optimization process will manage<br>
to register two images that are 140 degrees off, as the ones<br>
that you kindly posted.<br>
<br>
<br>
So you should:<br>
<br>
1)  Initialize the Transform with an angle close to 140 degrees.<br>
<br>
2)  Use the Rigid2DTransform instead of the<br>
     CenteredRigid2DTransform (this later one is deprecated)<br>
<br>
3)  Remove all the Change image filters that you have in your<br>
     code. They shouldn&#39;t be necessary.<br>
<br>
<br>
Please find attached a simplified variation of the example:<br>
<br>
    Insight/Examples/Registration/<br>
                            ImageRegistration6.cxx<br>
<br>
With this attached .cxx file,<br>
I manage to register your two images with the following output:<br>
<br>
 Angle (radians) 2.45657<br>
 Angle (degrees) 140.751<br>
 Translation X = 1.67046<br>
 Translation Y = -0.480926<br>
 Iterations    = 92<br>
 Metric value  = 6.19969e+07<br>
<br>
<br>
I ran it with the following set of command line arguments:<br>
<br>
ImageRegistration6<br>
<br>
     section0004_w1.tif section0005_w1.tif 150.0 output.tiff<br>
<br>
<br>
Where &quot;150.0&quot; is the initial angle to set in the Transform.<br>
<br>
<br>
Please give it a try at this attached code and let us<br>
know if you find any problems.<br>
<br>
<br>
     Thanks<br>
<br>
<br>
            Luis<br>
<br>
<br>
--------------------------------------------------------------------------------------<br>
<div><div></div><div>On Fri, Mar 5, 2010 at 7:56 PM, Richard Beare &lt;<a href="mailto:richard.beare@gmail.com" target="_blank">richard.beare@gmail.com</a>&gt; wrote:<br>
&gt; Good initialization is essential for all registration, with the<br>
&gt; rotation component often the most critical. If the rotation is greater<br>
&gt; than 15 degrees then you&#39;re probably going to have trouble.<br>
&gt;<br>
&gt; If you&#39;re trying to build an automated process rather than a one off,<br>
&gt; then here are some options.<br>
&gt;<br>
&gt; Moments based initialization as a first step. This is good if the<br>
&gt; scene is reasonably simple, or you have masks defining the regions of<br>
&gt; interest. You can check how similar the major moments are. If they are<br>
&gt; sufficiently dissimilar then the initialization is likely to be<br>
&gt; accurate along the major axis, but potentially flipped. In this case<br>
&gt; you need to try both options and select the one that gives the best<br>
&gt; resulting cost. If the moments are similar then the initialization<br>
&gt; will be unreliable and sensitive to small changes, so you need to try<br>
&gt; a series of angles covering the entire 360 degrees and select the best<br>
&gt; result as defined by your cost metric.<br>
&gt;<br>
&gt; On Sat, Mar 6, 2010 at 11:45 AM, Darren Weber<br>
&gt; &lt;<a href="mailto:darren.weber.lists@gmail.com" target="_blank">darren.weber.lists@gmail.com</a>&gt; wrote:<br>
&gt;&gt;<br>
&gt;&gt; I&#39;ve got a couple of images that clearly need nearly 180 degree rotation for<br>
&gt;&gt; registration, see:<br>
&gt;&gt; <a href="ftp://anonymous" target="_blank">ftp://anonymous</a>@<a href="http://ftp.buckinstitute.org/dweber/section0004_w1.tif" target="_blank">ftp.buckinstitute.org/dweber/section0004_w1.tif</a><br>
&gt;&gt; <a href="ftp://anonymous" target="_blank">ftp://anonymous</a>@<a href="http://ftp.buckinstitute.org/dweber/section0005_w1.tif" target="_blank">ftp.buckinstitute.org/dweber/section0005_w1.tif</a><br>
&gt;&gt; The registration fails to rotate the images into alignment.  I&#39;m using:<br>
&gt;&gt; // Registration components<br>
&gt;&gt; #include &quot;itkImageRegistrationMethod.h&quot;<br>
&gt;&gt; #include &quot;itkMeanSquaresImageToImageMetric.h&quot;<br>
&gt;&gt; #include &quot;itkLinearInterpolateImageFunction.h&quot;<br>
&gt;&gt; #include &quot;itkRegularStepGradientDescentOptimizer.h&quot;<br>
&gt;&gt; // Transforms<br>
&gt;&gt; #include &quot;itkCenteredRigid2DTransform.h&quot;<br>
&gt;&gt; #include &quot;itkCenteredTransformInitializer.h&quot;<br>
&gt;&gt;<br>
&gt;&gt; What can I do about it?  Have I selected the wrong transform for rotations?<br>
&gt;&gt; I&#39;ve prepared a package of my test program and data for download here:<br>
&gt;&gt; <a href="ftp://anonymous" target="_blank">ftp://anonymous</a>@<a href="http://ftp.buckinstitute.org/dweber/itkRegistrationTest.tar.gz" target="_blank">ftp.buckinstitute.org/dweber/itkRegistrationTest.tar.gz</a><br>



&gt;&gt; The program is built against ITK 3.16 (and it uses Boost).<br>
&gt;&gt; TIA,<br>
&gt;&gt; Darren<br>
&gt;&gt;<br>
&gt;&gt; _____________________________________<br>
&gt;&gt; Powered by <a href="http://www.kitware.com" target="_blank">www.kitware.com</a><br>
&gt;&gt;<br>
&gt;&gt; Visit other Kitware open-source projects at<br>
&gt;&gt; <a href="http://www.kitware.com/opensource/opensource.html" target="_blank">http://www.kitware.com/opensource/opensource.html</a><br>
&gt;&gt;<br>
&gt;&gt; Kitware offers ITK Training Courses, for more information visit:<br>
&gt;&gt; <a href="http://www.kitware.com/products/protraining.html" target="_blank">http://www.kitware.com/products/protraining.html</a><br>
&gt;&gt;<br>
&gt;&gt; Please keep messages on-topic and check the ITK FAQ at:<br>
&gt;&gt; <a href="http://www.itk.org/Wiki/ITK_FAQ" target="_blank">http://www.itk.org/Wiki/ITK_FAQ</a><br>
&gt;&gt;<br>
&gt;&gt; Follow this link to subscribe/unsubscribe:<br>
&gt;&gt; <a href="http://www.itk.org/mailman/listinfo/insight-users" target="_blank">http://www.itk.org/mailman/listinfo/insight-users</a><br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt; _____________________________________<br>
&gt; Powered by <a href="http://www.kitware.com" target="_blank">www.kitware.com</a><br>
&gt;<br>
&gt; Visit other Kitware open-source projects at<br>
&gt; <a href="http://www.kitware.com/opensource/opensource.html" target="_blank">http://www.kitware.com/opensource/opensource.html</a><br>
&gt;<br>
&gt; Kitware offers ITK Training Courses, for more information visit:<br>
&gt; <a href="http://www.kitware.com/products/protraining.html" target="_blank">http://www.kitware.com/products/protraining.html</a><br>
&gt;<br>
&gt; Please keep messages on-topic and check the ITK FAQ at:<br>
&gt; <a href="http://www.itk.org/Wiki/ITK_FAQ" target="_blank">http://www.itk.org/Wiki/ITK_FAQ</a><br>
&gt;<br>
&gt; Follow this link to subscribe/unsubscribe:<br>
&gt; <a href="http://www.itk.org/mailman/listinfo/insight-users" target="_blank">http://www.itk.org/mailman/listinfo/insight-users</a><br>
&gt;<br>
</div></div></blockquote></div><br></div>
</div></div></blockquote></div><br>
</div></div></blockquote></div><br></div>