<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>