<div dir="ltr">Hi Matt,<div><br></div><div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><span style="font-size:13px">Good to hear about your progress!</span></blockquote><div><br></div><div>your answers help me a lot!</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><span style="font-size:13px">There may be that there is a local minima that<br></span><span style="font-size:13px">is catching the optimizer</span></blockquote><div><br></div><div>Yes Matt, but the strange thing is that while the value of a metric is little better the result is worse...should not be better? or nearly equal ?</div><div><br></div></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">  As a first step, you can call SetNumberOfThreads on an<br>Object</blockquote><div><br></div><div>I had a compile error when trying to use this method (no exist member funtion), I think it is no available in the ITKv4. I tried to use a SetMaximumNumberOfThreads method, but do not notice any improvement in performance.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"> <span style="font-size:13px">or call itk::MultiThreader::</span><span style="font-size:13px">SetGlobalDefaultNumberOfThread</span><span style="font-size:13px">s</span></blockquote><div><br></div><div>It seems a bit complicated to use Matt ...<br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"> <span style="font-size:13px">There is a lot of interest in improving the mutual information metric<br></span><span style="font-size:13px">performance</span></blockquote><div><br></div><div>Yes, in my GA approach is critical the execution time of the Metric...because it must be calculated for each individual in the population. I think I have to use an alternative like a GA-Surrogate model to improve my implementation.</div><div><br></div><div>Thanks Matt, </div></div><div class="gmail_extra"><br><div class="gmail_quote">2015-04-13 12:38 GMT-04:00 Matt McCormick <span dir="ltr"><<a href="mailto:matt.mccormick@kitware.com" target="_blank">matt.mccormick@kitware.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi Gabriel,<br>
<br>
Good to hear about your progress!<br>
<br>
To get a better idea of what is happening in the optimization, it may<br>
insightful to visualize the cost function and where the optimizer is<br>
moving over that space. There may be that there is a local minima that<br>
is catching the optimizer.  See, for example, the later parts of this<br>
video, which displays the cost function as a surface and the<br>
progression of the optimization [1]. See the Metrics section of the<br>
ITK Software Guide for another example and discussion on how to do<br>
this.  We can make use of the ITK Command class, the IterationEvent,<br>
and the ExhaustiveOptimizer.<br>
<br>
The code itself is the best place to find details on multithreading in<br>
the metrics.  As a first step, you can call SetNumberOfThreads on an<br>
Object or call itk::MultiThreader::SetGlobalDefaultNumberOfThreads.<br>
There is a lot of interest in improving the mutual information metric<br>
performance -- please keep the list informed of your experiences.<br>
<br>
Thanks,<br>
Matt<br>
<br>
[1] <a href="https://drive.google.com/file/d/0B986LSX8iqF-bl9qQWZobmRWeEk/view?usp=sharing" target="_blank">https://drive.google.com/file/d/0B986LSX8iqF-bl9qQWZobmRWeEk/view?usp=sharing</a><br>
<div class="HOEnZb"><div class="h5"><br>
On Thu, Apr 9, 2015 at 9:17 PM, Gabriel A. Giménez<br>
<<a href="mailto:gabrielgimenez85@gmail.com">gabrielgimenez85@gmail.com</a>> wrote:<br>
> Hi Matt!<br>
><br>
>> If you are working with a current version of ITK, when you get the<br>
>> inverse transform, it should transfer the Center for you. The Center<br>
>> point locations are the FixedParameters for the parent class,<br>
>> MatrixOffsetTransformBase. The relationship with parent classes can be<br>
>> found by examining the Doxygen page for the class [1].<br>
><br>
><br>
> I took a few days to read the RIRE documentation and I came to the<br>
> conclusion that the direction of registration is not really<br>
> relevant...taking up CT as the fexed image and MR as the moving image can be<br>
> used the transformation that provides ITK...without having to calculate the<br>
> inverse.<br>
><br>
><br>
>> Do you get the same result by applying the TransformPoint() method of<br>
>> the inverse transform? This is the API call that should be applied to<br>
>> transform a point.<br>
><br>
><br>
> Yes Matt, I get the same results using the API.<br>
><br>
> But...I made some changes in my optimizers and I got very good results, like<br>
> this ( with RegularStepGradientDescentOptimizerv4 and<br>
> MattesMutualInformationImageToImageMetricv4):<br>
><br>
> iterations = 200<br>
> Metric value  = -0.709388<br>
> versor X      = 0.0155583<br>
>  versor Y      = 0.00642035<br>
>  versor Z      = -0.0487144<br>
>  Translation X = 7.82977<br>
>  Translation Y = -60.1034<br>
>  Translation Z = -23.6258<br>
> +-----------------------------------------------------------------------------------------------+<br>
> |           X GT|           Y GT|           Z GT|            X R|<br>
> Y R|            Z R|<br>
> -----------------------------------------------------------------------------------------------+<br>
> |      -7.573100|     -41.253400|     -27.309300|      -7.661395|<br>
> -40.915138|     -26.044441|<br>
> |     324.872200|     -72.815900|     -32.906300|     324.712907|<br>
> -73.345104|     -30.833635|<br>
> |      24.160700|     291.039300|     -16.272700|      24.902019|<br>
> 291.325008|     -15.874605|<br>
> |     356.606000|     259.476800|     -21.869700|     357.276322|<br>
> 258.895042|     -20.663798|<br>
> |      -6.055400|     -45.115700|      84.613700|      -6.394922|<br>
> -44.465633|      85.892103|<br>
> |     326.389900|     -76.678200|      79.016800|     325.979381|<br>
> -76.895599|      81.102910|<br>
> |      25.678400|     287.176900|      95.650300|      26.168493|<br>
> 287.774513|      96.061940|<br>
> |     358.123700|     255.614500|      90.053400|     358.542796|<br>
> 255.344547|      91.272747|<br>
> +-----------------------------------------------------------------------------------------------+<br>
> [X, Y, Z]GT are  the "ground truth" values and [X, Y, Z]R are my results<br>
><br>
> Now, something I find strange is that when increasing the number of<br>
> iterations...metric value limprovement is too little but the result is<br>
> little worse..., example:<br>
><br>
> Iterations    = 334<br>
> Metric value  = -0.710918<br>
>  versor X      = 0.0216566<br>
>  versor Y      = 0.00700629<br>
>  versor Z      = -0.0508766<br>
>  Translation X = 7.80722<br>
>  Translation Y = -60.5124<br>
>  Translation Z = -24.1047<br>
><br>
> +-----------------------------------------------------------------------------------------------+<br>
> |           X GT|           Y GT|           Z GT|            X R|<br>
> Y R|            Z R|<br>
> +-----------------------------------------------------------------------------------------------+<br>
> |      -7.573100|     -41.253400|     -27.309300|      -8.342271|<br>
> -39.764911|     -28.121895|<br>
> |     324.872200|     -72.815900|     -32.906300|     323.882938|<br>
> -73.594962|     -33.530625|<br>
> |      24.160700|     291.039300|     -16.272700|      25.690487|<br>
> 292.179801|     -13.916412|<br>
> |     356.606000|     259.476800|     -21.869700|     357.915696|<br>
> 258.349750|     -19.325143|<br>
> |      -6.055400|     -45.115700|      84.613700|      -7.022108|<br>
> -44.688304|      83.762051|<br>
> |     326.389900|     -76.678200|      79.016800|     325.203101|<br>
> -78.518355|      78.353321|<br>
> |      25.678400|     287.176900|      95.650300|      27.010650|<br>
> 287.256408|      97.967534|<br>
> |     358.123700|     255.614500|      90.053400|     359.235859|<br>
> 253.426357|      92.558803|<br>
> +-----------------------------------------------------------------------------------------------+<br>
><br>
> This pattern is repeated with other optimizers ( like OnePlusOne and  a GA<br>
> approach that I am implementing ), that you think about it?<br>
><br>
> Other questions Matt...:<br>
><br>
> How works the multithreaded in metrics ? is customizable? improve<br>
> performance? specifically in the case of Mattes Mutual Information...<br>
><br>
> I tried using the helper CenteredVersorTransformInitializer... but the<br>
> transformation that generates makes, incredibly and also very strange,the<br>
> optimizers does not advance...using CenteredTransformInitializer this does<br>
> not happen...<br>
><br>
> Really Thanks in advance Matt!<br>
> Regards,<br>
><br>
><br>
><br>
> 2015-04-07 15:03 GMT-04:00 Matt McCormick <<a href="mailto:matt.mccormick@kitware.com">matt.mccormick@kitware.com</a>>:<br>
><br>
>> Hi Gabriel!<br>
>><br>
>> > I am use RIRE project, specifically  CT (movig) and MR_PD (fixed)<br>
>> > images.<br>
>> > Basically, I hava a set of point (in millimeters) of the CT image to<br>
>> > which<br>
>> > apply the trasform result of the registration and updaload this results<br>
>> > in<br>
>> > the web for the evaluation. Example of set of points and his "ground<br>
>> > truth"<br>
>> > :<br>
>> ><br>
>> > Point      x          y          z        new_x       new_y       new_z<br>
>> ><br>
>> >   1       0.0000     0.0000     0.0000   -7.5731    -41.2534    -27.3093<br>
>> >   2     333.9870     0.0000     0.0000  324.8722    -72.8159    -32.9063<br>
>> >   3       0.0000   333.9870     0.0000   24.1607    291.0393    -16.2727<br>
>> >   4     333.9870   333.9870     0.0000  356.6060    259.4768    -21.8697<br>
>> >   5       0.0000     0.0000   112.0000   -6.0554    -45.1157     84.6137<br>
>> >   6     333.9870     0.0000   112.0000  326.3899    -76.6782     79.0168<br>
>> >   7       0.0000   333.9870   112.0000   25.6784    287.1769     95.6503<br>
>> >   8     333.9870   333.9870   112.0000  358.1237    255.6145     90.0534<br>
>><br>
>> Trying to reproduce previous results is a good path forward.<br>
>><br>
>> > So, the first I need is the transformation to apply, for that I do the<br>
>> > following :<br>
>> ><br>
>> >    //get the inverse transform<br>
>> >    TransformType::Pointer inverseTransform = TransformType::New();<br>
>> >    inverseTransform->SetCenter( finalTransform->GetCenter() );<br>
>> >    bool response = finalTransform->GetInverse(inverseTransform);<br>
>> ><br>
>> ><br>
>> > It makes sense to use the same center in the inverse transform?. A<br>
>> > "quaternion" define an "axis" (right part) of rotation and an angle to<br>
>> > use<br>
>> > for rotate the image about this axis...why use a center of rotation...?<br>
>><br>
>> If you are working with a current version of ITK, when you get the<br>
>> inverse transform, it should transfer the Center for you. The Center<br>
>> point locations are the FixedParameters for the parent class,<br>
>> MatrixOffsetTransformBase. The relationship with parent classes can be<br>
>> found by examining the Doxygen page for the class [1].<br>
>><br>
>><br>
>> > Second, apply this transform...as follows:<br>
>> ><br>
>> > NewPoint = RotationMatrix * OriginalPoint + Offset<br>
>> ><br>
>> > The rotation matrix and the offset are obtained from the inverse<br>
>> > transforme<br>
>> > objetc. Found something wrong? something that is not taking into account<br>
>> > ?<br>
>> > The results do not appear to be correct...the calculated error is too<br>
>> > big<br>
>> > and does not correspond with the visual result.<br>
>><br>
>> Do you get the same result by applying the TransformPoint() method of<br>
>> the inverse transform? This is the API call that should be applied to<br>
>> transform a point.<br>
>><br>
>> Thanks,<br>
>> Matt<br>
>><br>
>><br>
>> [1]<br>
>> <a href="http://www.itk.org/Doxygen/html/classitk_1_1VersorRigid3DTransform.html" target="_blank">http://www.itk.org/Doxygen/html/classitk_1_1VersorRigid3DTransform.html</a><br>
><br>
><br>
><br>
><br>
> --<br>
> Gabriel Alberto Giménez.<br>
</div></div></blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature"><div dir="ltr"><font color="#666666" size="1"><i><b>Gabriel Alberto Giménez.</b></i></font></div></div>
</div>